diff options
author | 2025-03-18 18:12:02 +0800 | |
---|---|---|
committer | 2025-03-20 16:21:18 +0800 | |
commit | 441200df2f12270948ee4a56739840335408086b (patch) | |
tree | 43245e262c5f4c2cf959a50c8c83439388d94204 /packages/SettingsLib | |
parent | 3f7b4cb595e228c59ed57cc344907720378af8af (diff) |
[Expressive Design] Update color logic in BannerMessage
- Button Color should change if attention level updated.
- Flip text color of negative btn under attention level MEDIUM for contrast
- Fix some test failure.
Bug: 397336535
Bug: 359066481
Test: atest BannerMessagePreferenceTest
Flag: com.android.settingslib.widget.theme.flags.is_expressive_design_enabled
Change-Id: I9d2a76d2daa427ecb9c0fd2cb80d240fd6941097
Diffstat (limited to 'packages/SettingsLib')
10 files changed, 371 insertions, 80 deletions
diff --git a/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_button_background_normal.xml b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_button_background_normal.xml index 8037a8bb75be..8a234fa6ca9e 100644 --- a/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_button_background_normal.xml +++ b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_button_background_normal.xml @@ -17,8 +17,8 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="false" - android:alpha="@dimen/material_emphasis_disabled_background" android:color="?attr/colorOnSurface"/> + android:alpha="@dimen/material_emphasis_disabled_background" android:color="@color/settingslib_materialColorPrimary"/> <item android:state_checked="true" android:color="?attr/colorContainerChecked"/> <item android:state_checkable="true" android:color="?attr/colorContainerUnchecked"/> - <item android:color="?attr/colorContainer" /> + <item android:color="@color/settingslib_materialColorPrimary" /> </selector>
\ No newline at end of file diff --git a/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_high.xml b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_high.xml new file mode 100644 index 000000000000..43b236938956 --- /dev/null +++ b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_high.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2025 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:alpha="@dimen/material_emphasis_disabled" android:color="@color/settingslib_colorContentLevel_high"/> + <item android:color="@color/settingslib_colorContentLevel_high" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_low.xml b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_low.xml new file mode 100644 index 000000000000..b7a9d7c5175b --- /dev/null +++ b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_low.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2025 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:alpha="@dimen/material_emphasis_disabled" android:color="@color/settingslib_colorContentLevel_low"/> + <item android:color="@color/settingslib_colorContentLevel_low" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_medium.xml b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_medium.xml new file mode 100644 index 000000000000..8e41cb03f4d1 --- /dev/null +++ b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_medium.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2025 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:alpha="@dimen/material_emphasis_disabled" android:color="@color/settingslib_colorContentLevel_medium"/> + <item android:color="@color/settingslib_colorContentLevel_medium" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_normal.xml b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_normal.xml new file mode 100644 index 000000000000..1dd5cdecfffc --- /dev/null +++ b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_filled_button_content_normal.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2025 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:alpha="@dimen/material_emphasis_disabled" android:color="@color/settingslib_materialColorOnPrimary"/> + <item android:color="@color/settingslib_materialColorOnPrimary" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_outline_button_content.xml b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_outline_button_content.xml new file mode 100644 index 000000000000..3a06fb38d5d8 --- /dev/null +++ b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_outline_button_content.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2025 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:alpha="@dimen/material_emphasis_disabled" android:color="@color/settingslib_materialColorOnSurface"/> + <item android:color="@color/settingslib_materialColorOnSurface" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_outline_button_stroke_normal.xml b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_outline_button_stroke_normal.xml new file mode 100644 index 000000000000..8d0b65712d35 --- /dev/null +++ b/packages/SettingsLib/BannerMessagePreference/res/color/settingslib_banner_outline_button_stroke_normal.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2025 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:alpha="@dimen/material_emphasis_disabled_background" android:color="@color/settingslib_materialColorOutline"/> + <item android:color="@color/settingslib_materialColorOutline" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-v36/styles_expressive.xml b/packages/SettingsLib/BannerMessagePreference/res/values-v36/styles_expressive.xml index 09e07ccef683..cd9faecc49c4 100644 --- a/packages/SettingsLib/BannerMessagePreference/res/values-v36/styles_expressive.xml +++ b/packages/SettingsLib/BannerMessagePreference/res/values-v36/styles_expressive.xml @@ -64,7 +64,6 @@ <style name="Banner.PositiveButton.SettingsLib.Expressive" parent="@style/SettingsLibButtonStyle.Expressive.Filled.Extra"> - <item name="android:textColor">?android:attr/textColorPrimaryInverse</item> <item name="materialSizeOverlay">@style/SizeOverlay.Material3Expressive.Button.Small</item> </style> diff --git a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java index c90a76a39510..dbd0f6424ff8 100644 --- a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java +++ b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java @@ -58,35 +58,42 @@ public class BannerMessagePreference extends Preference implements GroupSectionD HIGH(0, R.color.banner_background_attention_high, R.color.banner_accent_attention_high, - R.color.settingslib_banner_button_background_high), + R.color.settingslib_banner_button_background_high, + R.color.settingslib_banner_filled_button_content_high), MEDIUM(1, R.color.banner_background_attention_medium, R.color.banner_accent_attention_medium, - R.color.settingslib_banner_button_background_medium), + R.color.settingslib_banner_button_background_medium, + R.color.settingslib_banner_filled_button_content_medium), LOW(2, R.color.banner_background_attention_low, R.color.banner_accent_attention_low, - R.color.settingslib_banner_button_background_low), + R.color.settingslib_banner_button_background_low, + R.color.settingslib_banner_filled_button_content_low), NORMAL(3, R.color.banner_background_attention_normal, R.color.banner_accent_attention_normal, - R.color.settingslib_banner_button_background_normal); + R.color.settingslib_banner_button_background_normal, + R.color.settingslib_banner_filled_button_content_normal); // Corresponds to the enum value of R.attr.attentionLevel private final int mAttrValue; @ColorRes private final int mBackgroundColorResId; @ColorRes private final int mAccentColorResId; @ColorRes private final int mButtonBackgroundColorResId; + @ColorRes private final int mButtonContentColorResId; AttentionLevel( int attrValue, @ColorRes int backgroundColorResId, @ColorRes int accentColorResId, - @ColorRes int buttonBackgroundColorResId) { + @ColorRes int buttonBackgroundColorResId, + @ColorRes int buttonContentColorResId) { mAttrValue = attrValue; mBackgroundColorResId = backgroundColorResId; mAccentColorResId = accentColorResId; mButtonBackgroundColorResId = buttonBackgroundColorResId; + mButtonContentColorResId = buttonContentColorResId; } static AttentionLevel fromAttr(int attrValue) { @@ -109,6 +116,10 @@ public class BannerMessagePreference extends Preference implements GroupSectionD public @ColorRes int getButtonBackgroundColorResId() { return mButtonBackgroundColorResId; } + + public @ColorRes int getButtonContentColorResId() { + return mButtonContentColorResId; + } } private static final String TAG = "BannerPreference"; @@ -181,6 +192,7 @@ public class BannerMessagePreference extends Preference implements GroupSectionD public void onBindViewHolder(@NonNull PreferenceViewHolder holder) { super.onBindViewHolder(holder); final Context context = getContext(); + final Resources resources = context.getResources(); final TextView titleView = (TextView) holder.findViewById(R.id.banner_title); CharSequence title = getTitle(); @@ -200,7 +212,7 @@ public class BannerMessagePreference extends Preference implements GroupSectionD final Resources.Theme theme = context.getTheme(); @ColorInt final int accentColor = - context.getResources().getColor(mAttentionLevel.getAccentColorResId(), theme); + resources.getColor(mAttentionLevel.getAccentColorResId(), theme); final ImageView iconView = (ImageView) holder.findViewById(R.id.banner_icon); if (iconView != null) { @@ -211,9 +223,7 @@ public class BannerMessagePreference extends Preference implements GroupSectionD } else { iconView.setVisibility(View.VISIBLE); iconView.setImageDrawable( - icon == null - ? getContext().getDrawable(R.drawable.ic_warning) - : icon); + icon == null ? context.getDrawable(R.drawable.ic_warning) : icon); if (mAttentionLevel != AttentionLevel.NORMAL && !SettingsThemeHelper.isExpressiveTheme(context)) { iconView.setColorFilter( @@ -224,14 +234,24 @@ public class BannerMessagePreference extends Preference implements GroupSectionD if (IS_AT_LEAST_S) { @ColorInt final int backgroundColor = - context.getResources().getColor( - mAttentionLevel.getBackgroundColorResId(), theme); - - @ColorInt final int btnBackgroundColor = - context.getResources().getColor(mAttentionLevel.getButtonBackgroundColorResId(), - theme); - ColorStateList strokeColor = context.getResources().getColorStateList( - mAttentionLevel.getButtonBackgroundColorResId(), theme); + resources.getColor(mAttentionLevel.getBackgroundColorResId(), theme); + + ColorStateList btnBackgroundColor = + resources.getColorStateList( + mAttentionLevel.getButtonBackgroundColorResId(), theme); + ColorStateList btnStrokeColor = + mAttentionLevel == AttentionLevel.NORMAL + ? resources.getColorStateList( + R.color.settingslib_banner_outline_button_stroke_normal, theme) + : btnBackgroundColor; + ColorStateList filledBtnTextColor = + resources.getColorStateList( + mAttentionLevel.getButtonContentColorResId(), theme); + ColorStateList outlineBtnTextColor = + mAttentionLevel == AttentionLevel.NORMAL + ? btnBackgroundColor + : resources.getColorStateList( + R.color.settingslib_banner_outline_button_content, theme); holder.setDividerAllowedAbove(false); holder.setDividerAllowedBelow(false); @@ -242,10 +262,10 @@ public class BannerMessagePreference extends Preference implements GroupSectionD mPositiveButtonInfo.mColor = accentColor; mNegativeButtonInfo.mColor = accentColor; - if (mAttentionLevel != AttentionLevel.NORMAL) { - mPositiveButtonInfo.mBackgroundColor = btnBackgroundColor; - mNegativeButtonInfo.mStrokeColor = strokeColor; - } + mPositiveButtonInfo.mBackgroundColor = btnBackgroundColor; + mPositiveButtonInfo.mTextColor = filledBtnTextColor; + mNegativeButtonInfo.mStrokeColor = btnStrokeColor; + mNegativeButtonInfo.mTextColor = outlineBtnTextColor; mDismissButtonInfo.mButton = (ImageButton) holder.findViewById(R.id.banner_dismiss_btn); mDismissButtonInfo.setUpButton(); @@ -261,8 +281,6 @@ public class BannerMessagePreference extends Preference implements GroupSectionD headerView.setText(mHeader); headerView.setVisibility(TextUtils.isEmpty(mHeader) ? View.GONE : View.VISIBLE); } - - } else { holder.setDividerAllowedAbove(true); holder.setDividerAllowedBelow(true); @@ -567,8 +585,9 @@ public class BannerMessagePreference extends Preference implements GroupSectionD private boolean mIsVisible = true; private boolean mIsEnabled = true; @ColorInt private int mColor; - @ColorInt private int mBackgroundColor; + @Nullable private ColorStateList mBackgroundColor; @Nullable private ColorStateList mStrokeColor; + @Nullable private ColorStateList mTextColor; void setUpButton() { if (mButton == null) { @@ -586,12 +605,15 @@ public class BannerMessagePreference extends Preference implements GroupSectionD if (IS_AT_LEAST_S) { if (btn != null && SettingsThemeHelper.isExpressiveTheme(btn.getContext())) { - if (mBackgroundColor != 0) { - btn.setBackgroundColor(mBackgroundColor); + if (mBackgroundColor != null) { + btn.setBackgroundTintList(mBackgroundColor); } if (mStrokeColor != null) { btn.setStrokeColor(mStrokeColor); } + if (mTextColor != null) { + btn.setTextColor(mTextColor); + } } else { mButton.setTextColor(mColor); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java index 7f4bdaeac855..83471ae9513e 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java @@ -18,6 +18,7 @@ package com.android.settingslib.widget; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.robolectric.Robolectric.setupActivity; @@ -25,6 +26,8 @@ import static org.robolectric.Shadows.shadowOf; import android.app.Activity; import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.Configuration; import android.graphics.ColorFilter; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; @@ -38,24 +41,34 @@ import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.ColorRes; +import androidx.annotation.NonNull; import androidx.preference.PreferenceViewHolder; -import com.android.settingslib.testutils.OverpoweredReflectionHelper; import com.android.settingslib.widget.preference.banner.R; +import com.google.android.material.button.MaterialButton; + import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; import org.robolectric.shadows.ShadowDrawable; import org.robolectric.shadows.ShadowTouchDelegate; import org.robolectric.util.ReflectionHelpers; -@Ignore("b/359066481") +import java.util.List; + @RunWith(RobolectricTestRunner.class) +@Config(shadows = {BannerMessagePreferenceTest.ShadowSettingsThemeHelper.class}) public class BannerMessagePreferenceTest { private Context mContext; @@ -66,14 +79,23 @@ public class BannerMessagePreferenceTest { private boolean mClickListenerCalled = false; private final View.OnClickListener mClickListener = v -> mClickListenerCalled = true; private final int mMinimumTargetSize = - RuntimeEnvironment.application.getResources() - .getDimensionPixelSize(com.android.settingslib.widget.theme.R.dimen.settingslib_preferred_minimum_touch_target); + RuntimeEnvironment.application + .getResources() + .getDimensionPixelSize( + com.android.settingslib.widget.theme.R.dimen + .settingslib_preferred_minimum_touch_target); - private static final int TEST_STRING_RES_ID = - R.string.accessibility_banner_message_dismiss; + private static final int TEST_STRING_RES_ID = R.string.accessibility_banner_message_dismiss; + + @Mock private View mMockBackgroundView; + @Mock private Drawable mMockCardBackground; + @Mock private MaterialButton mMockPositiveBtn; + @Mock private MaterialButton mMockNegativeBtn; @Before public void setUp() { + MockitoAnnotations.initMocks(this); + ShadowSettingsThemeHelper.setExpressiveTheme(false); mContext = RuntimeEnvironment.application; mClickListenerCalled = false; mBannerPreference = new BannerMessagePreference(mContext); @@ -90,6 +112,7 @@ public class BannerMessagePreferenceTest { .isEqualTo("test"); } + @Ignore("b/359066481") @Test public void onBindViewHolder_andOnLayoutView_dismissButtonTouchDelegate_isCorrectSize() { assumeAndroidS(); @@ -155,9 +178,8 @@ public class BannerMessagePreferenceTest { @Test public void onBindViewHolder_whenAtLeastS_whenSubtitleXmlAttribute_shouldSetSubtitle() { assumeAndroidS(); - AttributeSet mAttributeSet = Robolectric.buildAttributeSet() - .addAttribute(R.attr.subtitle, "Test") - .build(); + AttributeSet mAttributeSet = + Robolectric.buildAttributeSet().addAttribute(R.attr.subtitle, "Test").build(); mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet); mBannerPreference.onBindViewHolder(mHolder); @@ -185,8 +207,7 @@ public class BannerMessagePreferenceTest { ImageView mIcon = mRootView.findViewById(R.id.banner_icon); ShadowDrawable shadowDrawable = shadowOf(mIcon.getDrawable()); - assertThat(shadowDrawable.getCreatedFromResId()) - .isEqualTo(R.drawable.settingslib_ic_cross); + assertThat(shadowDrawable.getCreatedFromResId()).isEqualTo(R.drawable.settingslib_ic_cross); } @Test @@ -207,6 +228,7 @@ public class BannerMessagePreferenceTest { Button mPositiveButton = mRootView.findViewById(R.id.banner_positive_btn); assertThat(mPositiveButton.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mPositiveButton.getText()).isEqualTo(mContext.getString(TEST_STRING_RES_ID)); } @@ -218,6 +240,7 @@ public class BannerMessagePreferenceTest { Button mNegativeButton = mRootView.findViewById(R.id.banner_negative_btn); assertThat(mNegativeButton.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mNegativeButton.getText()).isEqualTo(mContext.getString(TEST_STRING_RES_ID)); } @@ -359,8 +382,6 @@ public class BannerMessagePreferenceTest { @Test public void onBindViewHolder_whenAtLeastS_whenAttentionUnset_setsHighTheme() { assumeAndroidS(); - Drawable mCardBackgroundSpy = spy(mRootView.getBackground()); - mRootView.setBackground(mCardBackgroundSpy); mBannerPreference.onBindViewHolder(mHolder); @@ -370,17 +391,15 @@ public class BannerMessagePreferenceTest { .isEqualTo(getColorId(R.color.banner_accent_attention_high)); assertThat(getButtonColor(R.id.banner_negative_btn)) .isEqualTo(getColorId(R.color.banner_accent_attention_high)); - verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_high)); + + verify(mMockCardBackground).setTint(getColorId(R.color.banner_background_attention_high)); } @Test public void onBindViewHolder_whenAtLeastS_whenAttentionHighByXML_setsHighTheme() { assumeAndroidS(); - Drawable mCardBackgroundSpy = spy(mRootView.getBackground()); - mRootView.setBackground(mCardBackgroundSpy); - AttributeSet mAttributeSet = Robolectric.buildAttributeSet() - .addAttribute(R.attr.attentionLevel, "high") - .build(); + AttributeSet mAttributeSet = + Robolectric.buildAttributeSet().addAttribute(R.attr.attentionLevel, "high").build(); mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet); mBannerPreference.onBindViewHolder(mHolder); @@ -391,17 +410,17 @@ public class BannerMessagePreferenceTest { .isEqualTo(getColorId(R.color.banner_accent_attention_high)); assertThat(getButtonColor(R.id.banner_negative_btn)) .isEqualTo(getColorId(R.color.banner_accent_attention_high)); - verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_high)); + + verify(mMockCardBackground).setTint(getColorId(R.color.banner_background_attention_high)); } @Test public void onBindViewHolder_whenAtLeastS_whenAttentionMediumByXML_setsMediumTheme() { assumeAndroidS(); - Drawable mCardBackgroundSpy = spy(mRootView.getBackground()); - mRootView.setBackground(mCardBackgroundSpy); - AttributeSet mAttributeSet = Robolectric.buildAttributeSet() - .addAttribute(R.attr.attentionLevel, "medium") - .build(); + AttributeSet mAttributeSet = + Robolectric.buildAttributeSet() + .addAttribute(R.attr.attentionLevel, "medium") + .build(); mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet); mBannerPreference.onBindViewHolder(mHolder); @@ -412,17 +431,15 @@ public class BannerMessagePreferenceTest { .isEqualTo(getColorId(R.color.banner_accent_attention_medium)); assertThat(getButtonColor(R.id.banner_negative_btn)) .isEqualTo(getColorId(R.color.banner_accent_attention_medium)); - verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_medium)); + + verify(mMockCardBackground).setTint(getColorId(R.color.banner_background_attention_medium)); } @Test public void onBindViewHolder_whenAtLeastS_whenAttentionLowByXML_setsLowTheme() { assumeAndroidS(); - Drawable mCardBackgroundSpy = spy(mRootView.getBackground()); - mRootView.setBackground(mCardBackgroundSpy); - AttributeSet mAttributeSet = Robolectric.buildAttributeSet() - .addAttribute(R.attr.attentionLevel, "low") - .build(); + AttributeSet mAttributeSet = + Robolectric.buildAttributeSet().addAttribute(R.attr.attentionLevel, "low").build(); mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet); mBannerPreference.onBindViewHolder(mHolder); @@ -433,14 +450,13 @@ public class BannerMessagePreferenceTest { .isEqualTo(getColorId(R.color.banner_accent_attention_low)); assertThat(getButtonColor(R.id.banner_negative_btn)) .isEqualTo(getColorId(R.color.banner_accent_attention_low)); - verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_low)); + + verify(mMockCardBackground).setTint(getColorId(R.color.banner_background_attention_low)); } @Test public void setAttentionLevel_whenAtLeastS_whenHighAttention_setsHighTheme() { assumeAndroidS(); - Drawable mCardBackgroundSpy = spy(mRootView.getBackground()); - mRootView.setBackground(mCardBackgroundSpy); mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.HIGH); mBannerPreference.onBindViewHolder(mHolder); @@ -451,14 +467,44 @@ public class BannerMessagePreferenceTest { .isEqualTo(getColorId(R.color.banner_accent_attention_high)); assertThat(getButtonColor(R.id.banner_negative_btn)) .isEqualTo(getColorId(R.color.banner_accent_attention_high)); - verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_high)); + + verify(mMockCardBackground).setTint(getColorId(R.color.banner_background_attention_high)); } @Test - public void setAttentionLevel_whenAtLeastS_whenMedAttention_setsMediumTheme() { + public void setAttentionLevel_whenAtLeastS_whenHighAttentionAndExpressiveTheme_setsBtnTheme() { + setExpressiveTheme(true); + assumeAndroidS(); + assertThat(SettingsThemeHelper.isExpressiveTheme(mContext)).isTrue(); + assertThat(SettingsThemeHelper.isExpressiveTheme(mContext)).isTrue(); + doReturn(mMockPositiveBtn).when(mHolder).findViewById(R.id.banner_positive_btn); + doReturn(mMockNegativeBtn).when(mHolder).findViewById(R.id.banner_negative_btn); + assertThat(SettingsThemeHelper.isExpressiveTheme(mContext)).isTrue(); + mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.HIGH); + final ArgumentCaptor<ColorStateList> captor = ArgumentCaptor.forClass(ColorStateList.class); + ColorStateList filledBtnBackground = + getColorStateList(R.color.settingslib_banner_button_background_high); + ColorStateList filledBtnTextColor = + getColorStateList(R.color.settingslib_banner_filled_button_content_high); + ColorStateList outlineBtnTextColor = + getColorStateList(R.color.settingslib_banner_outline_button_content); + + mBannerPreference.onBindViewHolder(mHolder); + + verify(mMockPositiveBtn).setBackgroundTintList(captor.capture()); + verify(mMockPositiveBtn).setTextColor(captor.capture()); + verify(mMockNegativeBtn).setStrokeColor(captor.capture()); + verify(mMockNegativeBtn).setTextColor(captor.capture()); + List<ColorStateList> colors = captor.getAllValues(); + assertThat(colors.get(0).getColors()).isEqualTo(filledBtnBackground.getColors()); + assertThat(colors.get(1).getColors()).isEqualTo(filledBtnTextColor.getColors()); + assertThat(colors.get(2).getColors()).isEqualTo(filledBtnBackground.getColors()); + assertThat(colors.get(3).getColors()).isEqualTo(outlineBtnTextColor.getColors()); + } + + @Test + public void setAttentionLevel_whenAtLeastS_whenMedAttention_setsBtnMediumTheme() { assumeAndroidS(); - Drawable mCardBackgroundSpy = spy(mRootView.getBackground()); - mRootView.setBackground(mCardBackgroundSpy); mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.MEDIUM); mBannerPreference.onBindViewHolder(mHolder); @@ -469,14 +515,42 @@ public class BannerMessagePreferenceTest { .isEqualTo(getColorId(R.color.banner_accent_attention_medium)); assertThat(getButtonColor(R.id.banner_negative_btn)) .isEqualTo(getColorId(R.color.banner_accent_attention_medium)); - verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_medium)); + + verify(mMockCardBackground).setTint(getColorId(R.color.banner_background_attention_medium)); + } + + @Test + public void setAttentionLevel_whenAtLeastS_whenMedAttentionAndExpressiveTheme_setsBtnTheme() { + setExpressiveTheme(true); + mContext.getResources().getConfiguration().uiMode = Configuration.UI_MODE_NIGHT_NO; + assumeAndroidS(); + doReturn(mMockPositiveBtn).when(mHolder).findViewById(R.id.banner_positive_btn); + doReturn(mMockNegativeBtn).when(mHolder).findViewById(R.id.banner_negative_btn); + mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.MEDIUM); + final ArgumentCaptor<ColorStateList> captor = ArgumentCaptor.forClass(ColorStateList.class); + ColorStateList filledBtnBackground = + getColorStateList(R.color.settingslib_banner_button_background_medium); + ColorStateList filledBtnTextColor = + getColorStateList(R.color.settingslib_banner_filled_button_content_medium); + ColorStateList outlineBtnTextColor = + getColorStateList(R.color.settingslib_banner_outline_button_content); + + mBannerPreference.onBindViewHolder(mHolder); + + verify(mMockPositiveBtn).setBackgroundTintList(captor.capture()); + verify(mMockPositiveBtn).setTextColor(captor.capture()); + verify(mMockNegativeBtn).setStrokeColor(captor.capture()); + verify(mMockNegativeBtn).setTextColor(captor.capture()); + List<ColorStateList> colors = captor.getAllValues(); + assertThat(colors.get(0).getColors()).isEqualTo(filledBtnBackground.getColors()); + assertThat(colors.get(1).getColors()).isEqualTo(filledBtnTextColor.getColors()); + assertThat(colors.get(2).getColors()).isEqualTo(filledBtnBackground.getColors()); + assertThat(colors.get(3).getColors()).isEqualTo(outlineBtnTextColor.getColors()); } @Test public void setAttentionLevel_whenAtLeastS_whenLowAttention_setsLowTheme() { assumeAndroidS(); - Drawable mCardBackgroundSpy = spy(mRootView.getBackground()); - mRootView.setBackground(mCardBackgroundSpy); mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.LOW); mBannerPreference.onBindViewHolder(mHolder); @@ -487,7 +561,37 @@ public class BannerMessagePreferenceTest { .isEqualTo(getColorId(R.color.banner_accent_attention_low)); assertThat(getButtonColor(R.id.banner_negative_btn)) .isEqualTo(getColorId(R.color.banner_accent_attention_low)); - verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_low)); + verify(mMockCardBackground).setTint(getColorId(R.color.banner_background_attention_low)); + } + + @Test + public void + setAttentionLevel_whenAtLeastS_whenNormalAttentionAndExpressiveTheme_setsBtnTheme() { + setExpressiveTheme(true); + mContext.getResources().getConfiguration().uiMode = Configuration.UI_MODE_NIGHT_NO; + assumeAndroidS(); + doReturn(mMockPositiveBtn).when(mHolder).findViewById(R.id.banner_positive_btn); + doReturn(mMockNegativeBtn).when(mHolder).findViewById(R.id.banner_negative_btn); + mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.NORMAL); + final ArgumentCaptor<ColorStateList> captor = ArgumentCaptor.forClass(ColorStateList.class); + ColorStateList filledBtnBackground = + getColorStateList(R.color.settingslib_banner_button_background_normal); + ColorStateList filledBtnTextColor = + getColorStateList(R.color.settingslib_banner_filled_button_content_normal); + ColorStateList outlineBtnStrokeColor = + getColorStateList(R.color.settingslib_banner_outline_button_stroke_normal); + + mBannerPreference.onBindViewHolder(mHolder); + + verify(mMockPositiveBtn).setBackgroundTintList(captor.capture()); + verify(mMockPositiveBtn).setTextColor(captor.capture()); + verify(mMockNegativeBtn).setStrokeColor(captor.capture()); + verify(mMockNegativeBtn).setTextColor(captor.capture()); + List<ColorStateList> colors = captor.getAllValues(); + assertThat(colors.get(0).getColors()).isEqualTo(filledBtnBackground.getColors()); + assertThat(colors.get(1).getColors()).isEqualTo(filledBtnTextColor.getColors()); + assertThat(colors.get(2).getColors()).isEqualTo(outlineBtnStrokeColor.getColors()); + assertThat(colors.get(3).getColors()).isEqualTo(filledBtnBackground.getColors()); } private int getButtonColor(int buttonResId) { @@ -495,6 +599,11 @@ public class BannerMessagePreferenceTest { return mButton.getTextColors().getDefaultColor(); } + private ColorStateList getButtonTextColor(int buttonResId) { + Button mButton = mRootView.findViewById(buttonResId); + return mButton.getTextColors(); + } + private ColorFilter getColorFilter(@ColorRes int colorResId) { return new PorterDuffColorFilter(getColorId(colorResId), PorterDuff.Mode.SRC_IN); } @@ -503,28 +612,57 @@ public class BannerMessagePreferenceTest { return mContext.getResources().getColor(colorResId, mContext.getTheme()); } + private ColorStateList getColorStateList(@ColorRes int colorResId) { + return mContext.getResources().getColorStateList(colorResId, mContext.getTheme()); + } + private void assumeAndroidR() { ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 30); ReflectionHelpers.setStaticField(Build.VERSION.class, "CODENAME", "R"); - OverpoweredReflectionHelper - .setStaticField(BannerMessagePreference.class, "IS_AT_LEAST_S", false); - // Reset view holder to use correct layout. - } - + // Refresh the static final field IS_AT_LEAST_S + mBannerPreference = new BannerMessagePreference(mContext); + setUpViewHolder(); + } private void assumeAndroidS() { ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 31); ReflectionHelpers.setStaticField(Build.VERSION.class, "CODENAME", "S"); - OverpoweredReflectionHelper - .setStaticField(BannerMessagePreference.class, "IS_AT_LEAST_S", true); - // Re-inflate view to update layout. + + // Refresh the static final field IS_AT_LEAST_S + mBannerPreference = new BannerMessagePreference(mContext); setUpViewHolder(); } + private void setExpressiveTheme(boolean isExpressiveTheme) { + ShadowSettingsThemeHelper.setExpressiveTheme(isExpressiveTheme); + assertThat(SettingsThemeHelper.isExpressiveTheme(mContext)).isEqualTo(isExpressiveTheme); + if (isExpressiveTheme) { + doReturn(mContext).when(mMockPositiveBtn).getContext(); + doReturn(mContext).when(mMockNegativeBtn).getContext(); + } + } + private void setUpViewHolder() { mRootView = View.inflate(mContext, mBannerPreference.getLayoutResource(), null /* parent */); - mHolder = PreferenceViewHolder.createInstanceForTests(mRootView); + mHolder = spy(PreferenceViewHolder.createInstanceForTests(mRootView)); + doReturn(mMockBackgroundView).when(mHolder).findViewById(R.id.banner_background); + doReturn(mMockCardBackground).when(mMockBackgroundView).getBackground(); + } + + @Implements(SettingsThemeHelper.class) + public static class ShadowSettingsThemeHelper { + private static boolean sIsExpressiveTheme; + + /** Shadow implementation of isExpressiveTheme */ + @Implementation + public static boolean isExpressiveTheme(@NonNull Context context) { + return sIsExpressiveTheme; + } + + static void setExpressiveTheme(boolean isExpressiveTheme) { + sIsExpressiveTheme = isExpressiveTheme; + } } } |