Skip to content

Commit 1dbd3dd

Browse files
Material Design Teamdsn5ft
authored andcommitted
[M3][Color] Updated color harmonization demo
PiperOrigin-RevId: 446199668 (cherry picked from commit dc65df3)
1 parent b402cb3 commit 1dbd3dd

File tree

10 files changed

+598
-146
lines changed

10 files changed

+598
-146
lines changed

catalog/androidTest/javatests/io/material/catalog/color/ColorHarmonizationDemoFragmentTest.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package io.material.catalog.color;
1818

1919
import static androidx.test.espresso.Espresso.onView;
20-
import static androidx.test.espresso.action.ViewActions.click;
20+
import static androidx.test.espresso.action.ViewActions.scrollTo;
2121
import static androidx.test.espresso.assertion.ViewAssertions.matches;
2222
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
2323
import static androidx.test.espresso.matcher.ViewMatchers.withId;
@@ -32,7 +32,7 @@
3232
import org.junit.Test;
3333
import org.junit.runner.RunWith;
3434

35-
/** Tests for {@link ColorHarmonizationFragment} */
35+
/** Tests for {@link ColorHarmonizationDemoFragment} */
3636
@MediumTest
3737
@RunWith(AndroidJUnit4.class)
3838
public class ColorHarmonizationDemoFragmentTest {
@@ -57,11 +57,34 @@ public void setUpAndLaunchFragment() {
5757
}
5858

5959
@Test
60-
public void checkColorHexValueTextIsShown() {
61-
onView(withId(R.id.cat_color_enabled_switch)).perform(click());
60+
public void checkButtonsAreShown() {
61+
onView(withId(R.id.red_button_dark)).perform(scrollTo()).check(matches(isDisplayed()));
62+
onView(withId(R.id.red_button_light)).perform(scrollTo()).check(matches(isDisplayed()));
63+
onView(withId(R.id.yellow_button_dark)).perform(scrollTo()).check(matches(isDisplayed()));
64+
onView(withId(R.id.yellow_button_light)).perform(scrollTo()).check(matches(isDisplayed()));
65+
onView(withId(R.id.green_button_dark)).perform(scrollTo()).check(matches(isDisplayed()));
66+
onView(withId(R.id.green_button_light)).perform(scrollTo()).check(matches(isDisplayed()));
67+
onView(withId(R.id.blue_button_dark)).perform(scrollTo()).check(matches(isDisplayed()));
68+
onView(withId(R.id.blue_button_light)).perform(scrollTo()).check(matches(isDisplayed()));
69+
}
6270

63-
onView(withId(R.id.material_button_color_hex_value)).check(matches(isDisplayed()));
64-
onView(withId(R.id.material_unelevated_button_color_hex_value)).check(matches(isDisplayed()));
65-
onView(withId(R.id.material_text_input_color_hex_value)).check(matches(isDisplayed()));
71+
@Test
72+
public void checkColorPalettesAreShown() {
73+
onView(withId(R.id.cat_colors_error)).perform(scrollTo()).check(matches(isDisplayed()));
74+
onView(withId(R.id.cat_colors_harmonized_error))
75+
.perform(scrollTo())
76+
.check(matches(isDisplayed()));
77+
onView(withId(R.id.cat_colors_yellow)).perform(scrollTo()).check(matches(isDisplayed()));
78+
onView(withId(R.id.cat_colors_harmonized_yellow))
79+
.perform(scrollTo())
80+
.check(matches(isDisplayed()));
81+
onView(withId(R.id.cat_colors_green)).perform(scrollTo()).check(matches(isDisplayed()));
82+
onView(withId(R.id.cat_colors_harmonized_green))
83+
.perform(scrollTo())
84+
.check(matches(isDisplayed()));
85+
onView(withId(R.id.cat_colors_blue)).perform(scrollTo()).check(matches(isDisplayed()));
86+
onView(withId(R.id.cat_colors_harmonized_blue))
87+
.perform(scrollTo())
88+
.check(matches(isDisplayed()));
6689
}
6790
}

catalog/java/io/material/catalog/color/ColorGrid.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ final class ColorGrid {
3535
@NonNull private final MaterialColorSpec materialColorSpecAccentContainer;
3636
@NonNull private final MaterialColorSpec materialColorSpecOnAccentContainer;
3737

38-
static ColorGrid createFromColorGridData(Context context, ColorGridData colorGridData) {
38+
static ColorGrid createFromColorGridData(ColorGridData colorGridData) {
3939
ColorRoles colorRoles = colorGridData.getColorRoles();
4040
ColorRoleNames colorRoleNames = colorGridData.getColorRoleNames();
4141
MaterialColorSpec[] materialColorSpecs =

catalog/java/io/material/catalog/color/ColorHarmonizationDemoFragment.java

Lines changed: 108 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -18,88 +18,137 @@
1818

1919
import io.material.catalog.R;
2020

21+
import android.content.Context;
2122
import android.os.Bundle;
2223
import android.view.LayoutInflater;
2324
import android.view.View;
2425
import android.view.ViewGroup;
25-
import android.widget.TextView;
26-
import androidx.annotation.ColorInt;
27-
import androidx.annotation.ColorRes;
28-
import androidx.annotation.LayoutRes;
26+
import android.widget.LinearLayout;
27+
import androidx.annotation.IdRes;
2928
import androidx.annotation.Nullable;
30-
import androidx.annotation.StringRes;
31-
import com.google.android.material.button.MaterialButton;
32-
import com.google.android.material.color.MaterialColors;
29+
import com.google.android.material.color.DynamicColors;
30+
import com.google.android.material.color.HarmonizedColors;
31+
import com.google.android.material.color.HarmonizedColorsOptions;
3332
import com.google.android.material.switchmaterial.SwitchMaterial;
34-
import com.google.android.material.textfield.TextInputLayout;
3533
import io.material.catalog.feature.DemoFragment;
34+
import java.util.ArrayList;
35+
import java.util.List;
3636

3737
/** A fragment that displays the Color Harmonization demo for the Catalog app. */
3838
public class ColorHarmonizationDemoFragment extends DemoFragment {
3939

40-
private static final int GREEN_RESOURCE_ID = R.color.green40;
41-
private static final int RED_RESOURCE_ID = R.color.red40;
42-
private static final int BLUE_RESOURCE_ID = R.color.blue90;
40+
private static final HarmonizableButtonData[] HARMONIZABLE_BUTTON_DATA_LIST =
41+
new HarmonizableButtonData[] {
42+
new HarmonizableButtonData(
43+
R.id.red_button_dark, R.color.error_reference, /* isLightButton= */ false),
44+
new HarmonizableButtonData(
45+
R.id.red_button_light, R.color.error_reference, /* isLightButton= */ true),
46+
new HarmonizableButtonData(
47+
R.id.yellow_button_dark, R.color.yellow_reference, /* isLightButton= */ false),
48+
new HarmonizableButtonData(
49+
R.id.yellow_button_light, R.color.yellow_reference, /* isLightButton= */ true),
50+
new HarmonizableButtonData(
51+
R.id.green_button_dark, R.color.green_reference, /* isLightButton= */ false),
52+
new HarmonizableButtonData(
53+
R.id.green_button_light, R.color.green_reference, /* isLightButton= */ true),
54+
new HarmonizableButtonData(
55+
R.id.blue_button_dark, R.color.blue_reference, /* isLightButton= */ false),
56+
new HarmonizableButtonData(
57+
R.id.blue_button_light, R.color.blue_reference, /* isLightButton= */ true),
58+
};
59+
// TODO(b/231143697): Refactor this class to a DemoActivity and showcase harmonization using
60+
// error color attributes.
61+
private static final ColorHarmonizationGridRowData[] HARMONIZATION_GRID_ROW_DATA_LIST =
62+
new ColorHarmonizationGridRowData[] {
63+
new ColorHarmonizationGridRowData(
64+
R.id.cat_colors_error,
65+
R.id.cat_colors_harmonized_error,
66+
R.color.error_reference,
67+
R.array.cat_error_strings),
68+
new ColorHarmonizationGridRowData(
69+
R.id.cat_colors_yellow,
70+
R.id.cat_colors_harmonized_yellow,
71+
R.color.yellow_reference,
72+
R.array.cat_yellow_strings),
73+
new ColorHarmonizationGridRowData(
74+
R.id.cat_colors_green,
75+
R.id.cat_colors_harmonized_green,
76+
R.color.green_reference,
77+
R.array.cat_green_strings),
78+
new ColorHarmonizationGridRowData(
79+
R.id.cat_colors_blue,
80+
R.id.cat_colors_harmonized_blue,
81+
R.color.blue_reference,
82+
R.array.cat_blue_strings)
83+
};
84+
85+
private Context dynamicColorsContext;
86+
private Context harmonizedContext;
87+
private View demoView;
88+
89+
private final List<HarmonizableButton> harmonizableButtonList = new ArrayList<>();
4390

4491
@Nullable
4592
@Override
4693
public View onCreateDemoView(
4794
@Nullable LayoutInflater layoutInflater,
4895
@Nullable ViewGroup viewGroup,
4996
@Nullable Bundle bundle) {
50-
View view = layoutInflater.inflate(getColorsContent(), viewGroup, false /* attachToRoot */);
51-
MaterialButton elevatedButton = view.findViewById(R.id.material_button);
52-
MaterialButton unelevatedButton = view.findViewById(R.id.material_unelevated_button);
53-
TextInputLayout textInputLayout = view.findViewById(R.id.material_text_input_layout);
54-
TextView buttonColorHexValueText = view.findViewById(R.id.material_button_color_hex_value);
55-
TextView unelevatedButtonColorHexValueText =
56-
view.findViewById(R.id.material_unelevated_button_color_hex_value);
57-
TextView textInputColorHexValueText =
58-
view.findViewById(R.id.material_text_input_color_hex_value);
59-
60-
elevatedButton.setBackgroundColor(getResources().getColor(GREEN_RESOURCE_ID));
61-
unelevatedButton.setBackgroundColor(getResources().getColor(RED_RESOURCE_ID));
62-
textInputLayout.setBoxBackgroundColor(getResources().getColor(BLUE_RESOURCE_ID));
63-
64-
SwitchMaterial enabledSwitch = view.findViewById(R.id.cat_color_enabled_switch);
65-
enabledSwitch.setOnCheckedChangeListener(
66-
(buttonView, isChecked) -> {
67-
buttonColorHexValueText.setVisibility(View.VISIBLE);
68-
unelevatedButtonColorHexValueText.setVisibility(View.VISIBLE);
69-
textInputColorHexValueText.setVisibility(View.VISIBLE);
97+
demoView =
98+
layoutInflater.inflate(
99+
R.layout.cat_colors_harmonization_fragment, viewGroup, false /* attachToRoot */);
70100

71-
int maybeHarmonizedGreen = maybeHarmonizeWithPrimary(GREEN_RESOURCE_ID, isChecked);
72-
int maybeHarmonizedRed = maybeHarmonizeWithPrimary(RED_RESOURCE_ID, isChecked);
73-
int maybeHarmonizedBlue = maybeHarmonizeWithPrimary(BLUE_RESOURCE_ID, isChecked);
74-
75-
elevatedButton.setBackgroundColor(maybeHarmonizedGreen);
76-
unelevatedButton.setBackgroundColor(maybeHarmonizedRed);
77-
textInputLayout.setBoxBackgroundColor(maybeHarmonizedBlue);
78-
79-
// The %06X gives us zero-padded hex (always 6 chars long).
80-
buttonColorHexValueText.setText(
81-
getColorHexValueText(R.string.cat_color_hex_value_text, maybeHarmonizedGreen));
82-
unelevatedButtonColorHexValueText.setText(
83-
getColorHexValueText(R.string.cat_color_hex_value_text, maybeHarmonizedRed));
84-
textInputColorHexValueText.setText(
85-
getColorHexValueText(R.string.cat_color_hex_value_text, maybeHarmonizedBlue));
86-
});
87-
88-
return view;
89-
}
101+
dynamicColorsContext = DynamicColors.wrapContextIfAvailable(requireContext());
102+
HarmonizedColorsOptions options =
103+
new HarmonizedColorsOptions.Builder()
104+
.setColorResourceIds(
105+
new int[] {
106+
R.color.error_reference,
107+
R.color.yellow_reference,
108+
R.color.blue_reference,
109+
R.color.green_reference,
110+
})
111+
.build();
112+
harmonizedContext = HarmonizedColors.wrapContextIfAvailable(dynamicColorsContext, options);
90113

91-
private int maybeHarmonizeWithPrimary(@ColorRes int colorResId, boolean harmonize) {
92-
return harmonize
93-
? MaterialColors.harmonizeWithPrimary(getContext(), getResources().getColor(colorResId))
94-
: getResources().getColor(colorResId);
114+
for (ColorHarmonizationGridRowData colorHarmonizationGridRowData :
115+
HARMONIZATION_GRID_ROW_DATA_LIST) {
116+
createColorGridAndPopulateLayout(
117+
dynamicColorsContext,
118+
colorHarmonizationGridRowData,
119+
colorHarmonizationGridRowData.getLeftLayoutId());
120+
createColorGridAndPopulateLayout(
121+
harmonizedContext,
122+
colorHarmonizationGridRowData,
123+
colorHarmonizationGridRowData.getRightLayoutId());
124+
}
125+
// Setup buttons text color based on current theme.
126+
for (HarmonizableButtonData harmonizableButtonData : HARMONIZABLE_BUTTON_DATA_LIST) {
127+
harmonizableButtonList.add(HarmonizableButton.create(demoView, harmonizableButtonData));
128+
}
129+
updateButtons(/* harmonize= */ false);
130+
SwitchMaterial enabledSwitch = demoView.findViewById(R.id.cat_color_enabled_switch);
131+
enabledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> updateButtons(isChecked));
132+
return demoView;
95133
}
96134

97-
private CharSequence getColorHexValueText(@StringRes int stringResId, @ColorInt int color) {
98-
return getResources().getString(stringResId, String.format("#%06X", (0xFFFFFF & color)));
135+
private void createColorGridAndPopulateLayout(
136+
Context context,
137+
ColorHarmonizationGridRowData colorHarmonizationGridRowData,
138+
@IdRes int layoutId) {
139+
ColorGrid colorGrid =
140+
ColorGrid.createFromColorGridData(
141+
ColorGridData.createFromColorResId(
142+
context,
143+
colorHarmonizationGridRowData.getColorResId(),
144+
colorHarmonizationGridRowData.getColorNameIds()));
145+
LinearLayout layout = demoView.findViewById(layoutId);
146+
layout.addView(colorGrid.renderView(context, layout));
99147
}
100148

101-
@LayoutRes
102-
protected int getColorsContent() {
103-
return R.layout.cat_colors_harmonization_fragment;
149+
private void updateButtons(boolean harmonize) {
150+
for (HarmonizableButton button : harmonizableButtonList) {
151+
button.updateColors(harmonize);
152+
}
104153
}
105154
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.material.catalog.color;
18+
19+
import androidx.annotation.ArrayRes;
20+
import androidx.annotation.ColorRes;
21+
import androidx.annotation.IdRes;
22+
23+
/** A class that provides data for a row in the Color Harmonization demo grid. */
24+
final class ColorHarmonizationGridRowData {
25+
26+
@IdRes private final int leftLayoutId;
27+
@IdRes private final int rightLayoutId;
28+
@ColorRes private final int colorResId;
29+
@ArrayRes private final int colorNameIds;
30+
31+
ColorHarmonizationGridRowData(
32+
@IdRes int leftLayoutId,
33+
@IdRes int rightLayoutId,
34+
@ColorRes int colorResId,
35+
@ArrayRes int colorNameIds) {
36+
this.leftLayoutId = leftLayoutId;
37+
this.rightLayoutId = rightLayoutId;
38+
this.colorResId = colorResId;
39+
this.colorNameIds = colorNameIds;
40+
}
41+
42+
@IdRes
43+
int getLeftLayoutId() {
44+
return leftLayoutId;
45+
}
46+
47+
@IdRes
48+
int getRightLayoutId() {
49+
return rightLayoutId;
50+
}
51+
52+
@ColorRes
53+
int getColorResId() {
54+
return colorResId;
55+
}
56+
57+
@ArrayRes
58+
int getColorNameIds() {
59+
return colorNameIds;
60+
}
61+
}

catalog/java/io/material/catalog/color/ColorRow.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import io.material.catalog.R;
2020

21-
import android.graphics.Color;
2221
import android.view.LayoutInflater;
2322
import android.view.View;
2423
import android.widget.LinearLayout;
@@ -75,16 +74,8 @@ private void bindColorRoleItem(
7574
TextView colorRole = view.findViewById(textViewId);
7675

7776
colorRole.setText(colorRoleTextResID);
78-
colorRole.setTextColor(getTextColor(colorAttrResId));
79-
colorRole.setBackgroundColor(MaterialColors.getColor(view, colorAttrResId));
80-
}
81-
82-
private int getTextColor(@AttrRes int colorAttrResId) {
83-
if (!MaterialColors.isColorLight(MaterialColors.getColor(catColorsSchemeRow, colorAttrResId))) {
84-
// Use white text color if the color is considered dark.
85-
return Color.WHITE;
86-
} else {
87-
return Color.BLACK;
88-
}
77+
colorRole.setTextColor(
78+
ColorDemoUtils.getTextColor(MaterialColors.getColor(catColorsSchemeRow, colorAttrResId)));
79+
colorRole.setBackgroundColor(MaterialColors.getColor(catColorsSchemeRow, colorAttrResId));
8980
}
9081
}

0 commit comments

Comments
 (0)