Skip to content

Commit

Permalink
[M3][Color] Updated color harmonization demo
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 446199668
  • Loading branch information
Material Design Team authored and dsn5ft committed May 3, 2022
1 parent 2fa78da commit dc65df3
Show file tree
Hide file tree
Showing 10 changed files with 598 additions and 146 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package io.material.catalog.color;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
Expand All @@ -32,7 +32,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;

/** Tests for {@link ColorHarmonizationFragment} */
/** Tests for {@link ColorHarmonizationDemoFragment} */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class ColorHarmonizationDemoFragmentTest {
Expand All @@ -57,11 +57,34 @@ public void setUpAndLaunchFragment() {
}

@Test
public void checkColorHexValueTextIsShown() {
onView(withId(R.id.cat_color_enabled_switch)).perform(click());
public void checkButtonsAreShown() {
onView(withId(R.id.red_button_dark)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.red_button_light)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.yellow_button_dark)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.yellow_button_light)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.green_button_dark)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.green_button_light)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.blue_button_dark)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.blue_button_light)).perform(scrollTo()).check(matches(isDisplayed()));
}

onView(withId(R.id.material_button_color_hex_value)).check(matches(isDisplayed()));
onView(withId(R.id.material_unelevated_button_color_hex_value)).check(matches(isDisplayed()));
onView(withId(R.id.material_text_input_color_hex_value)).check(matches(isDisplayed()));
@Test
public void checkColorPalettesAreShown() {
onView(withId(R.id.cat_colors_error)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.cat_colors_harmonized_error))
.perform(scrollTo())
.check(matches(isDisplayed()));
onView(withId(R.id.cat_colors_yellow)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.cat_colors_harmonized_yellow))
.perform(scrollTo())
.check(matches(isDisplayed()));
onView(withId(R.id.cat_colors_green)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.cat_colors_harmonized_green))
.perform(scrollTo())
.check(matches(isDisplayed()));
onView(withId(R.id.cat_colors_blue)).perform(scrollTo()).check(matches(isDisplayed()));
onView(withId(R.id.cat_colors_harmonized_blue))
.perform(scrollTo())
.check(matches(isDisplayed()));
}
}
2 changes: 1 addition & 1 deletion catalog/java/io/material/catalog/color/ColorGrid.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ final class ColorGrid {
@NonNull private final MaterialColorSpec materialColorSpecAccentContainer;
@NonNull private final MaterialColorSpec materialColorSpecOnAccentContainer;

static ColorGrid createFromColorGridData(Context context, ColorGridData colorGridData) {
static ColorGrid createFromColorGridData(ColorGridData colorGridData) {
ColorRoles colorRoles = colorGridData.getColorRoles();
ColorRoleNames colorRoleNames = colorGridData.getColorRoleNames();
MaterialColorSpec[] materialColorSpecs =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,88 +18,137 @@

import io.material.catalog.R;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.LayoutRes;
import android.widget.LinearLayout;
import androidx.annotation.IdRes;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.color.MaterialColors;
import com.google.android.material.color.DynamicColors;
import com.google.android.material.color.HarmonizedColors;
import com.google.android.material.color.HarmonizedColorsOptions;
import com.google.android.material.switchmaterial.SwitchMaterial;
import com.google.android.material.textfield.TextInputLayout;
import io.material.catalog.feature.DemoFragment;
import java.util.ArrayList;
import java.util.List;

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

private static final int GREEN_RESOURCE_ID = R.color.green40;
private static final int RED_RESOURCE_ID = R.color.red40;
private static final int BLUE_RESOURCE_ID = R.color.blue90;
private static final HarmonizableButtonData[] HARMONIZABLE_BUTTON_DATA_LIST =
new HarmonizableButtonData[] {
new HarmonizableButtonData(
R.id.red_button_dark, R.color.error_reference, /* isLightButton= */ false),
new HarmonizableButtonData(
R.id.red_button_light, R.color.error_reference, /* isLightButton= */ true),
new HarmonizableButtonData(
R.id.yellow_button_dark, R.color.yellow_reference, /* isLightButton= */ false),
new HarmonizableButtonData(
R.id.yellow_button_light, R.color.yellow_reference, /* isLightButton= */ true),
new HarmonizableButtonData(
R.id.green_button_dark, R.color.green_reference, /* isLightButton= */ false),
new HarmonizableButtonData(
R.id.green_button_light, R.color.green_reference, /* isLightButton= */ true),
new HarmonizableButtonData(
R.id.blue_button_dark, R.color.blue_reference, /* isLightButton= */ false),
new HarmonizableButtonData(
R.id.blue_button_light, R.color.blue_reference, /* isLightButton= */ true),
};
// TODO(b/231143697): Refactor this class to a DemoActivity and showcase harmonization using
// error color attributes.
private static final ColorHarmonizationGridRowData[] HARMONIZATION_GRID_ROW_DATA_LIST =
new ColorHarmonizationGridRowData[] {
new ColorHarmonizationGridRowData(
R.id.cat_colors_error,
R.id.cat_colors_harmonized_error,
R.color.error_reference,
R.array.cat_error_strings),
new ColorHarmonizationGridRowData(
R.id.cat_colors_yellow,
R.id.cat_colors_harmonized_yellow,
R.color.yellow_reference,
R.array.cat_yellow_strings),
new ColorHarmonizationGridRowData(
R.id.cat_colors_green,
R.id.cat_colors_harmonized_green,
R.color.green_reference,
R.array.cat_green_strings),
new ColorHarmonizationGridRowData(
R.id.cat_colors_blue,
R.id.cat_colors_harmonized_blue,
R.color.blue_reference,
R.array.cat_blue_strings)
};

private Context dynamicColorsContext;
private Context harmonizedContext;
private View demoView;

private final List<HarmonizableButton> harmonizableButtonList = new ArrayList<>();

@Nullable
@Override
public View onCreateDemoView(
@Nullable LayoutInflater layoutInflater,
@Nullable ViewGroup viewGroup,
@Nullable Bundle bundle) {
View view = layoutInflater.inflate(getColorsContent(), viewGroup, false /* attachToRoot */);
MaterialButton elevatedButton = view.findViewById(R.id.material_button);
MaterialButton unelevatedButton = view.findViewById(R.id.material_unelevated_button);
TextInputLayout textInputLayout = view.findViewById(R.id.material_text_input_layout);
TextView buttonColorHexValueText = view.findViewById(R.id.material_button_color_hex_value);
TextView unelevatedButtonColorHexValueText =
view.findViewById(R.id.material_unelevated_button_color_hex_value);
TextView textInputColorHexValueText =
view.findViewById(R.id.material_text_input_color_hex_value);

elevatedButton.setBackgroundColor(getResources().getColor(GREEN_RESOURCE_ID));
unelevatedButton.setBackgroundColor(getResources().getColor(RED_RESOURCE_ID));
textInputLayout.setBoxBackgroundColor(getResources().getColor(BLUE_RESOURCE_ID));

SwitchMaterial enabledSwitch = view.findViewById(R.id.cat_color_enabled_switch);
enabledSwitch.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
buttonColorHexValueText.setVisibility(View.VISIBLE);
unelevatedButtonColorHexValueText.setVisibility(View.VISIBLE);
textInputColorHexValueText.setVisibility(View.VISIBLE);
demoView =
layoutInflater.inflate(
R.layout.cat_colors_harmonization_fragment, viewGroup, false /* attachToRoot */);

int maybeHarmonizedGreen = maybeHarmonizeWithPrimary(GREEN_RESOURCE_ID, isChecked);
int maybeHarmonizedRed = maybeHarmonizeWithPrimary(RED_RESOURCE_ID, isChecked);
int maybeHarmonizedBlue = maybeHarmonizeWithPrimary(BLUE_RESOURCE_ID, isChecked);

elevatedButton.setBackgroundColor(maybeHarmonizedGreen);
unelevatedButton.setBackgroundColor(maybeHarmonizedRed);
textInputLayout.setBoxBackgroundColor(maybeHarmonizedBlue);

// The %06X gives us zero-padded hex (always 6 chars long).
buttonColorHexValueText.setText(
getColorHexValueText(R.string.cat_color_hex_value_text, maybeHarmonizedGreen));
unelevatedButtonColorHexValueText.setText(
getColorHexValueText(R.string.cat_color_hex_value_text, maybeHarmonizedRed));
textInputColorHexValueText.setText(
getColorHexValueText(R.string.cat_color_hex_value_text, maybeHarmonizedBlue));
});

return view;
}
dynamicColorsContext = DynamicColors.wrapContextIfAvailable(requireContext());
HarmonizedColorsOptions options =
new HarmonizedColorsOptions.Builder()
.setColorResourceIds(
new int[] {
R.color.error_reference,
R.color.yellow_reference,
R.color.blue_reference,
R.color.green_reference,
})
.build();
harmonizedContext = HarmonizedColors.wrapContextIfAvailable(dynamicColorsContext, options);

private int maybeHarmonizeWithPrimary(@ColorRes int colorResId, boolean harmonize) {
return harmonize
? MaterialColors.harmonizeWithPrimary(getContext(), getResources().getColor(colorResId))
: getResources().getColor(colorResId);
for (ColorHarmonizationGridRowData colorHarmonizationGridRowData :
HARMONIZATION_GRID_ROW_DATA_LIST) {
createColorGridAndPopulateLayout(
dynamicColorsContext,
colorHarmonizationGridRowData,
colorHarmonizationGridRowData.getLeftLayoutId());
createColorGridAndPopulateLayout(
harmonizedContext,
colorHarmonizationGridRowData,
colorHarmonizationGridRowData.getRightLayoutId());
}
// Setup buttons text color based on current theme.
for (HarmonizableButtonData harmonizableButtonData : HARMONIZABLE_BUTTON_DATA_LIST) {
harmonizableButtonList.add(HarmonizableButton.create(demoView, harmonizableButtonData));
}
updateButtons(/* harmonize= */ false);
SwitchMaterial enabledSwitch = demoView.findViewById(R.id.cat_color_enabled_switch);
enabledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> updateButtons(isChecked));
return demoView;
}

private CharSequence getColorHexValueText(@StringRes int stringResId, @ColorInt int color) {
return getResources().getString(stringResId, String.format("#%06X", (0xFFFFFF & color)));
private void createColorGridAndPopulateLayout(
Context context,
ColorHarmonizationGridRowData colorHarmonizationGridRowData,
@IdRes int layoutId) {
ColorGrid colorGrid =
ColorGrid.createFromColorGridData(
ColorGridData.createFromColorResId(
context,
colorHarmonizationGridRowData.getColorResId(),
colorHarmonizationGridRowData.getColorNameIds()));
LinearLayout layout = demoView.findViewById(layoutId);
layout.addView(colorGrid.renderView(context, layout));
}

@LayoutRes
protected int getColorsContent() {
return R.layout.cat_colors_harmonization_fragment;
private void updateButtons(boolean harmonize) {
for (HarmonizableButton button : harmonizableButtonList) {
button.updateColors(harmonize);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.material.catalog.color;

import androidx.annotation.ArrayRes;
import androidx.annotation.ColorRes;
import androidx.annotation.IdRes;

/** A class that provides data for a row in the Color Harmonization demo grid. */
final class ColorHarmonizationGridRowData {

@IdRes private final int leftLayoutId;
@IdRes private final int rightLayoutId;
@ColorRes private final int colorResId;
@ArrayRes private final int colorNameIds;

ColorHarmonizationGridRowData(
@IdRes int leftLayoutId,
@IdRes int rightLayoutId,
@ColorRes int colorResId,
@ArrayRes int colorNameIds) {
this.leftLayoutId = leftLayoutId;
this.rightLayoutId = rightLayoutId;
this.colorResId = colorResId;
this.colorNameIds = colorNameIds;
}

@IdRes
int getLeftLayoutId() {
return leftLayoutId;
}

@IdRes
int getRightLayoutId() {
return rightLayoutId;
}

@ColorRes
int getColorResId() {
return colorResId;
}

@ArrayRes
int getColorNameIds() {
return colorNameIds;
}
}
15 changes: 3 additions & 12 deletions catalog/java/io/material/catalog/color/ColorRow.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import io.material.catalog.R;

import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
Expand Down Expand Up @@ -75,16 +74,8 @@ private void bindColorRoleItem(
TextView colorRole = view.findViewById(textViewId);

colorRole.setText(colorRoleTextResID);
colorRole.setTextColor(getTextColor(colorAttrResId));
colorRole.setBackgroundColor(MaterialColors.getColor(view, colorAttrResId));
}

private int getTextColor(@AttrRes int colorAttrResId) {
if (!MaterialColors.isColorLight(MaterialColors.getColor(catColorsSchemeRow, colorAttrResId))) {
// Use white text color if the color is considered dark.
return Color.WHITE;
} else {
return Color.BLACK;
}
colorRole.setTextColor(
ColorDemoUtils.getTextColor(MaterialColors.getColor(catColorsSchemeRow, colorAttrResId)));
colorRole.setBackgroundColor(MaterialColors.getColor(catColorsSchemeRow, colorAttrResId));
}
}
Loading

0 comments on commit dc65df3

Please sign in to comment.