Merge "Updates BannerMessagePreference to new style" into sc-dev

This commit is contained in:
Marie Matheson
2021-05-19 08:26:03 +00:00
committed by Android (Google) Code Review
14 changed files with 921 additions and 88 deletions

View File

@@ -15,8 +15,9 @@ android_library {
static_libs: [ static_libs: [
"androidx.preference_preference", "androidx.preference_preference",
"SettingsLibSettingsTheme",
], ],
sdk_version: "system_current", sdk_version: "system_current",
min_sdk_version: "21", min_sdk_version: "28",
} }

View File

@@ -18,6 +18,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settingslib.widget"> package="com.android.settingslib.widget">
<uses-sdk android:minSdkVersion="21"/> <uses-sdk android:minSdkVersion="28"/>
</manifest> </manifest>

View File

@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
<issue
id="NewApi"
message="`@android:style/Widget.DeviceDefault.Button.Borderless.Colored` requires API level 28 (current min is 21)"
errorLine1=" style=&quot;@android:style/Widget.DeviceDefault.Button.Borderless.Colored&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="frameworks/base/packages/SettingsLib/BannerMessagePreference/res/layout/banner_message.xml"
line="65"
column="13"/>
</issue>
<issue
id="NewApi"
message="`@android:style/Widget.DeviceDefault.Button.Borderless.Colored` requires API level 28 (current min is 21)"
errorLine1=" style=&quot;@android:style/Widget.DeviceDefault.Button.Borderless.Colored&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="frameworks/base/packages/SettingsLib/BannerMessagePreference/res/layout/banner_message.xml"
line="71"
column="13"/>
</issue>
<issue
id="NewApi"
message="`?android:attr/colorError` requires API level 26 (current min is 21)"
errorLine1=" android:fillColor=&quot;?android:attr/colorError&quot;"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="frameworks/base/packages/SettingsLib/BannerMessagePreference/res/drawable/ic_warning.xml"
line="24"
column="9"/>
</issue>
</issues>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="?android:attr/background" />
<corners android:radius="28dp"/>
</shape>

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2021 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:attr/textColorSecondary"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12 19,6.41z"/>
</vector>

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
style="@style/Banner.Preference.SettingsLib">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/banner_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignParentStart="true"
android:importantForAccessibility="no" />
<ImageButton
android:id="@+id/banner_dismiss_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/settingslib_ic_cross"
android:layout_alignParentEnd="true"
android:contentDescription="@string/accessibility_banner_message_dismiss"
style="@style/Banner.Dismiss.SettingsLib" />
</RelativeLayout>
<TextView
android:id="@+id/banner_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
android:textAppearance="@style/Banner.Title.SettingsLib"/>
<TextView
android:id="@+id/banner_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
android:textAppearance="@style/Banner.Subtitle.SettingsLib"
android:visibility="gone"/>
<TextView
android:id="@+id/banner_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:paddingBottom="8dp"
android:textAppearance="@style/Banner.Summary.SettingsLib"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:minHeight="8dp"
android:gravity="end">
<Button
android:id="@+id/banner_negative_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Banner.ButtonText.SettingsLib"/>
<Button
android:id="@+id/banner_positive_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Banner.ButtonText.SettingsLib"/>
</LinearLayout>
</LinearLayout>

View File

@@ -30,8 +30,10 @@
android:orientation="horizontal"> android:orientation="horizontal">
<ImageView <ImageView
android:id="@+id/banner_icon"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:importantForAccessibility="no"
android:src="@drawable/ic_warning"/> android:src="@drawable/ic_warning"/>
<LinearLayout <LinearLayout
@@ -70,4 +72,19 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"/> style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"/>
</LinearLayout> </LinearLayout>
<!-- Not supported before v31 -->
<TextView
android:id="@+id/banner_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
<!-- Not supported before v31 -->
<ImageButton
android:id="@+id/banner_dismiss_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/accessibility_banner_message_dismiss"
android:visibility="gone"/>
</LinearLayout> </LinearLayout>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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.
-->
<resources>
<color name="banner_background_attention_high">#3B2D2C</color> <!-- red card background -->
<color name="banner_background_attention_medium">#333121</color> <!-- yellow card background -->
<color name="banner_background_attention_low">#2B3328</color> <!-- green card background -->
<color name="banner_accent_attention_high">#F28B82</color> <!-- red accent color -->
<color name="banner_accent_attention_medium">#FDD663</color> <!-- yellow accent color -->
<color name="banner_accent_attention_low">#81C995</color> <!-- green accent color -->
</resources>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 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.
-->
<resources>
<style name="Banner.Preference.SettingsLib"
parent="android:Widget.DeviceDefault">
<item name="android:paddingStart">20dp</item>
<item name="android:paddingEnd">20dp</item>
<item name="android:paddingTop">20dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:layout_marginTop">8dp</item>
<item name="android:layout_marginStart">16dp</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:layout_marginEnd">16dp</item>
<item name="android:background">@drawable/settingslib_card_background</item>
</style>
<style name="Banner.Title.SettingsLib"
parent="@android:style/TextAppearance.Material.Subhead">
<item name="android:textSize">20sp</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="Banner.Subtitle.SettingsLib"
parent="@*android:style/TextAppearance.DeviceDefault.Body1">
<item name="android:textColor">?android:attr/textColorSecondary</item>
<item name="android:textSize">14sp</item>
</style>
<style name="Banner.Summary.SettingsLib"
parent="@*android:style/TextAppearance.DeviceDefault.Body1">
<item name="android:textColor">?android:attr/textColorSecondary</item>
<item name="android:textSize">14sp</item>
</style>
<style name="Banner.Dismiss.SettingsLib"
parent="android:Widget.DeviceDefault.ImageButton">
<item name="android:background">@android:color/transparent</item>
</style>
<style name="Banner.ButtonText.SettingsLib"
parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
<item name="android:textColor">?android:attr/colorAccent</item>
</style>
</resources>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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.
-->
<resources>
<declare-styleable name="BannerMessagePreference">
<attr format="enum" name="attentionLevel">
<enum name="high" value="0"/>
<enum name="medium" value="1"/>
<enum name="low" value="2"/>
</attr>
<attr format="string" name="subtitle" />
</declare-styleable>
</resources>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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.
-->
<resources>
<color name="banner_background_attention_high">#FFDAD5</color> <!-- red card background -->
<color name="banner_background_attention_medium">#F0E3A8</color> <!-- yellow card background -->
<color name="banner_background_attention_low">#CFEBC0</color> <!-- green card background -->
<color name="banner_accent_attention_high">#BB3322</color> <!-- red accent color -->
<color name="banner_accent_attention_medium">#895900</color> <!-- yellow accent color -->
<color name="banner_accent_attention_low">#1D7233</color> <!-- green accent color -->
</resources>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Content description of the dismiss button on a banner message for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_banner_message_dismiss">Dismiss</string>
</resources>

View File

@@ -17,13 +17,25 @@
package com.android.settingslib.widget; package com.android.settingslib.widget;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.core.os.BuildCompat;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder; import androidx.preference.PreferenceViewHolder;
@@ -33,55 +45,151 @@ import androidx.preference.PreferenceViewHolder;
*/ */
public class BannerMessagePreference extends Preference { public class BannerMessagePreference extends Preference {
public enum AttentionLevel {
HIGH(0, R.color.banner_background_attention_high, R.color.banner_accent_attention_high),
MEDIUM(1,
R.color.banner_background_attention_medium,
R.color.banner_accent_attention_medium),
LOW(2, R.color.banner_background_attention_low, R.color.banner_accent_attention_low);
// Corresponds to the enum valye of R.attr.attentionLevel
private final int mAttrValue;
@ColorRes private final int mBackgroundColorResId;
@ColorRes private final int mAccentColorResId;
AttentionLevel(int attrValue, @ColorRes int backgroundColorResId,
@ColorRes int accentColorResId) {
mAttrValue = attrValue;
mBackgroundColorResId = backgroundColorResId;
mAccentColorResId = accentColorResId;
}
static AttentionLevel fromAttr(int attrValue) {
for (AttentionLevel level : values()) {
if (level.mAttrValue == attrValue) {
return level;
}
}
throw new IllegalArgumentException();
}
@ColorRes int getAccentColorResId() {
return mAccentColorResId;
}
@ColorRes int getBackgroundColorResId() {
return mBackgroundColorResId;
}
}
private static final String TAG = "BannerPreference"; private static final String TAG = "BannerPreference";
private BannerMessagePreference.ButtonInfo mPositiveButtonInfo; private static final boolean IS_AT_LEAST_S = BuildCompat.isAtLeastS();
private BannerMessagePreference.ButtonInfo mNegativeButtonInfo;
private final BannerMessagePreference.ButtonInfo mPositiveButtonInfo =
new BannerMessagePreference.ButtonInfo();
private final BannerMessagePreference.ButtonInfo mNegativeButtonInfo =
new BannerMessagePreference.ButtonInfo();
private final BannerMessagePreference.DismissButtonInfo mDismissButtonInfo =
new BannerMessagePreference.DismissButtonInfo();
// Default attention level is High.
private AttentionLevel mAttentionLevel = AttentionLevel.HIGH;
private String mSubtitle;
public BannerMessagePreference(Context context) { public BannerMessagePreference(Context context) {
super(context); super(context);
init(); init(context, null /* attrs */);
} }
public BannerMessagePreference(Context context, AttributeSet attrs) { public BannerMessagePreference(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
init(); init(context, attrs);
} }
public BannerMessagePreference(Context context, AttributeSet attrs, int defStyleAttr) { public BannerMessagePreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
init(); init(context, attrs);
} }
public BannerMessagePreference(Context context, AttributeSet attrs, int defStyleAttr, public BannerMessagePreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) { int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
init(); init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setSelectable(false);
setLayoutResource(R.layout.settingslib_banner_message);
if (IS_AT_LEAST_S) {
if (attrs != null) {
// Get attention level and subtitle from layout XML
TypedArray a =
context.obtainStyledAttributes(attrs, R.styleable.BannerMessagePreference);
int mAttentionLevelValue =
a.getInt(R.styleable.BannerMessagePreference_attentionLevel, 0);
mAttentionLevel = AttentionLevel.fromAttr(mAttentionLevelValue);
mSubtitle = a.getString(R.styleable.BannerMessagePreference_subtitle);
a.recycle();
}
}
} }
@Override @Override
public void onBindViewHolder(PreferenceViewHolder holder) { public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder); super.onBindViewHolder(holder);
holder.setDividerAllowedAbove(true); final Context context = getContext();
holder.setDividerAllowedBelow(true);
final TextView titleView = (TextView) holder.findViewById(R.id.banner_title);
CharSequence title = getTitle();
titleView.setText(title);
titleView.setVisibility(title == null ? View.GONE : View.VISIBLE);
final TextView summaryView = (TextView) holder.findViewById(R.id.banner_summary);
summaryView.setText(getSummary());
mPositiveButtonInfo.mButton = (Button) holder.findViewById(R.id.banner_positive_btn); mPositiveButtonInfo.mButton = (Button) holder.findViewById(R.id.banner_positive_btn);
mNegativeButtonInfo.mButton = (Button) holder.findViewById(R.id.banner_negative_btn); mNegativeButtonInfo.mButton = (Button) holder.findViewById(R.id.banner_negative_btn);
mPositiveButtonInfo.setUpButton(); if (IS_AT_LEAST_S) {
mNegativeButtonInfo.setUpButton(); final Resources.Theme theme = context.getTheme();
@ColorInt final int accentColor =
context.getResources().getColor(mAttentionLevel.getAccentColorResId(), theme);
@ColorInt final int backgroundColor =
context.getResources().getColor(
mAttentionLevel.getBackgroundColorResId(), theme);
final TextView titleView = (TextView) holder.findViewById(R.id.banner_title); holder.setDividerAllowedAbove(false);
final TextView summaryView = (TextView) holder.findViewById(R.id.banner_summary); holder.setDividerAllowedBelow(false);
holder.itemView.getBackground().setTint(backgroundColor);
titleView.setText(getTitle()); mPositiveButtonInfo.mColor = accentColor;
summaryView.setText(getSummary()); mNegativeButtonInfo.mColor = accentColor;
mDismissButtonInfo.mButton = (ImageButton) holder.findViewById(R.id.banner_dismiss_btn);
mDismissButtonInfo.setUpButton();
final TextView subtitleView = (TextView) holder.findViewById(R.id.banner_subtitle);
subtitleView.setText(mSubtitle);
subtitleView.setVisibility(mSubtitle == null ? View.GONE : View.VISIBLE);
final ImageView iconView = (ImageView) holder.findViewById(R.id.banner_icon);
if (iconView != null) {
Drawable icon = getIcon();
iconView.setImageDrawable(
icon == null
? getContext().getDrawable(R.drawable.ic_warning)
: icon);
iconView.setColorFilter(
new PorterDuffColorFilter(accentColor, PorterDuff.Mode.SRC_IN));
}
} else {
holder.setDividerAllowedAbove(true);
holder.setDividerAllowedBelow(true);
} }
private void init() { mPositiveButtonInfo.setUpButton();
mPositiveButtonInfo = new BannerMessagePreference.ButtonInfo(); mNegativeButtonInfo.setUpButton();
mNegativeButtonInfo = new BannerMessagePreference.ButtonInfo();
setSelectable(false);
setLayoutResource(R.layout.banner_message);
} }
/** /**
@@ -106,6 +214,18 @@ public class BannerMessagePreference extends Preference {
return this; return this;
} }
/**
* Set the visibility state of dismiss button.
*/
@RequiresApi(Build.VERSION_CODES.S)
public BannerMessagePreference setDismissButtonVisible(boolean isVisible) {
if (isVisible != mDismissButtonInfo.mIsVisible) {
mDismissButtonInfo.mIsVisible = isVisible;
notifyChanged();
}
return this;
}
/** /**
* Register a callback to be invoked when positive button is clicked. * Register a callback to be invoked when positive button is clicked.
*/ */
@@ -130,13 +250,32 @@ public class BannerMessagePreference extends Preference {
return this; return this;
} }
/**
* Register a callback to be invoked when the dismiss button is clicked.
*/
@RequiresApi(Build.VERSION_CODES.S)
public BannerMessagePreference setDismissButtonOnClickListener(
View.OnClickListener listener) {
if (listener != mDismissButtonInfo.mListener) {
mDismissButtonInfo.mListener = listener;
notifyChanged();
}
return this;
}
/** /**
* Sets the text to be displayed in positive button. * Sets the text to be displayed in positive button.
*/ */
public BannerMessagePreference setPositiveButtonText(@StringRes int textResId) { public BannerMessagePreference setPositiveButtonText(@StringRes int textResId) {
final String newText = getContext().getString(textResId); return setPositiveButtonText(getContext().getString(textResId));
if (!TextUtils.equals(newText, mPositiveButtonInfo.mText)) { }
mPositiveButtonInfo.mText = newText;
/**
* Sets the text to be displayed in positive button.
*/
public BannerMessagePreference setPositiveButtonText(String positiveButtonText) {
if (!TextUtils.equals(positiveButtonText, mPositiveButtonInfo.mText)) {
mPositiveButtonInfo.mText = positiveButtonText;
notifyChanged(); notifyChanged();
} }
return this; return this;
@@ -146,9 +285,51 @@ public class BannerMessagePreference extends Preference {
* Sets the text to be displayed in negative button. * Sets the text to be displayed in negative button.
*/ */
public BannerMessagePreference setNegativeButtonText(@StringRes int textResId) { public BannerMessagePreference setNegativeButtonText(@StringRes int textResId) {
final String newText = getContext().getString(textResId); return setNegativeButtonText(getContext().getString(textResId));
if (!TextUtils.equals(newText, mNegativeButtonInfo.mText)) { }
mNegativeButtonInfo.mText = newText;
/**
* Sets the text to be displayed in negative button.
*/
public BannerMessagePreference setNegativeButtonText(String negativeButtonText) {
if (!TextUtils.equals(negativeButtonText, mNegativeButtonInfo.mText)) {
mNegativeButtonInfo.mText = negativeButtonText;
notifyChanged();
}
return this;
}
/**
* Sets the subtitle.
*/
@RequiresApi(Build.VERSION_CODES.S)
public BannerMessagePreference setSubtitle(@StringRes int textResId) {
return setSubtitle(getContext().getString(textResId));
}
/**
* Sets the subtitle.
*/
@RequiresApi(Build.VERSION_CODES.S)
public BannerMessagePreference setSubtitle(String subtitle) {
if (!TextUtils.equals(subtitle, mSubtitle)) {
mSubtitle = subtitle;
notifyChanged();
}
return this;
}
/**
* Sets the attention level. This will update the color theme of the preference.
*/
@RequiresApi(Build.VERSION_CODES.S)
public BannerMessagePreference setAttentionLevel(AttentionLevel attentionLevel) {
if (attentionLevel == mAttentionLevel) {
return this;
}
if (attentionLevel != null) {
mAttentionLevel = attentionLevel;
notifyChanged(); notifyChanged();
} }
return this; return this;
@@ -159,11 +340,16 @@ public class BannerMessagePreference extends Preference {
private CharSequence mText; private CharSequence mText;
private View.OnClickListener mListener; private View.OnClickListener mListener;
private boolean mIsVisible = true; private boolean mIsVisible = true;
@ColorInt private int mColor;
void setUpButton() { void setUpButton() {
mButton.setText(mText); mButton.setText(mText);
mButton.setOnClickListener(mListener); mButton.setOnClickListener(mListener);
if (IS_AT_LEAST_S) {
mButton.setTextColor(mColor);
}
if (shouldBeVisible()) { if (shouldBeVisible()) {
mButton.setVisibility(View.VISIBLE); mButton.setVisibility(View.VISIBLE);
} else { } else {
@@ -179,4 +365,26 @@ public class BannerMessagePreference extends Preference {
return mIsVisible && (!TextUtils.isEmpty(mText)); return mIsVisible && (!TextUtils.isEmpty(mText));
} }
} }
static class DismissButtonInfo {
private ImageButton mButton;
private View.OnClickListener mListener;
private boolean mIsVisible = true;
void setUpButton() {
mButton.setOnClickListener(mListener);
if (shouldBeVisible()) {
mButton.setVisibility(View.VISIBLE);
} else {
mButton.setVisibility(View.GONE);
}
}
/**
* By default, dismiss button is visible if it has a click listener.
*/
private boolean shouldBeVisible() {
return mIsVisible && (mListener != null);
}
}
} }

View File

@@ -18,18 +18,35 @@ package com.android.settingslib.widget;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context; import android.content.Context;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.ColorRes;
import androidx.preference.PreferenceViewHolder; import androidx.preference.PreferenceViewHolder;
import androidx.preference.R;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowDrawable;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class BannerMessagePreferenceTest { public class BannerMessagePreferenceTest {
@@ -39,16 +56,22 @@ public class BannerMessagePreferenceTest {
private BannerMessagePreference mBannerPreference; private BannerMessagePreference mBannerPreference;
private PreferenceViewHolder mHolder; private PreferenceViewHolder mHolder;
private boolean mClickListenerCalled = false;
private final View.OnClickListener mClickListener = v -> mClickListenerCalled = true;
private static final int TEST_STRING_RES_ID =
R.string.accessibility_banner_message_dismiss;
@Before @Before
public void setUp() { public void setUp() {
mContext = RuntimeEnvironment.application; mContext = RuntimeEnvironment.application;
mRootView = View.inflate(mContext, R.layout.banner_message, null /* parent */); mClickListenerCalled = false;
mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
mBannerPreference = new BannerMessagePreference(mContext); mBannerPreference = new BannerMessagePreference(mContext);
setUpViewHolder();
} }
@Test @Test
public void onBindViewHolder_shouldSetTitle() { public void onBindViewHolder_whenTitleSet_shouldSetTitle() {
mBannerPreference.setTitle("test"); mBannerPreference.setTitle("test");
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
@@ -58,7 +81,7 @@ public class BannerMessagePreferenceTest {
} }
@Test @Test
public void onBindViewHolder_shouldSetSummary() { public void onBindViewHolder_whenSummarySet_shouldSetSummary() {
mBannerPreference.setSummary("test"); mBannerPreference.setSummary("test");
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
@@ -68,30 +91,114 @@ public class BannerMessagePreferenceTest {
} }
@Test @Test
public void setPositiveButtonText_shouldShowPositiveButton() { public void onBindViewHolder_whenPreS_shouldBindView() {
mBannerPreference.setPositiveButtonText(R.string.tts_settings_title); assumeAndroidR();
mBannerPreference.setSummary("test");
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
assertThat(((Button) mRootView.findViewById(R.id.banner_positive_btn)).getVisibility()) assertThat(((TextView) mRootView.findViewById(R.id.banner_summary)).getText())
.isEqualTo(View.VISIBLE); .isEqualTo("test");
}
@Test
public void onBindViewHolder_whenAtLeastS_whenSubtitleSetByString_shouldSetSubtitle() {
assumeAndroidS();
mBannerPreference.setSubtitle("test");
mBannerPreference.onBindViewHolder(mHolder);
TextView mSubtitleView = mRootView.findViewById(R.id.banner_subtitle);
assertThat(mSubtitleView.getText()).isEqualTo("test");
assertThat(mSubtitleView.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void onBindViewHolder_whenAtLeastS_whenSubtitleSetByResId_shouldSetSubtitle() {
assumeAndroidS();
mBannerPreference.setSubtitle(TEST_STRING_RES_ID);
mBannerPreference.onBindViewHolder(mHolder);
TextView mSubtitleView = mRootView.findViewById(R.id.banner_subtitle);
assertThat(mSubtitleView.getText()).isEqualTo(mContext.getString(TEST_STRING_RES_ID));
assertThat(mSubtitleView.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void onBindViewHolder_whenAtLeastS_whenSubtitleXmlAttribute_shouldSetSubtitle() {
assumeAndroidS();
AttributeSet mAttributeSet = Robolectric.buildAttributeSet()
.addAttribute(R.attr.subtitle, "Test")
.build();
mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet);
mBannerPreference.onBindViewHolder(mHolder);
TextView mSubtitleView = mRootView.findViewById(R.id.banner_subtitle);
assertThat(mSubtitleView.getText()).isEqualTo("Test");
assertThat(mSubtitleView.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void onBindViewHolder_whenAtLeastS_shouldNotShowSubtitleIfUnset() {
assumeAndroidS();
mBannerPreference.onBindViewHolder(mHolder);
TextView mSubtitleView = mRootView.findViewById(R.id.banner_subtitle);
assertThat(mSubtitleView.getVisibility()).isEqualTo(View.GONE);
}
@Test
public void onBindViewHolder_whenAtLeastS_whenIconSet_shouldSetIcon() {
assumeAndroidS();
mBannerPreference.setIcon(R.drawable.settingslib_ic_cross);
mBannerPreference.onBindViewHolder(mHolder);
ImageView mIcon = mRootView.findViewById(R.id.banner_icon);
ShadowDrawable shadowDrawable = Shadows.shadowOf(mIcon.getDrawable());
assertThat(shadowDrawable.getCreatedFromResId())
.isEqualTo(R.drawable.settingslib_ic_cross);
}
@Test
public void onBindViewHolder_whenAtLeastS_whenNoIconSet_shouldSetIconToDefault() {
assumeAndroidS();
mBannerPreference.onBindViewHolder(mHolder);
ImageView mIcon = mRootView.findViewById(R.id.banner_icon);
ShadowDrawable shadowDrawable = Shadows.shadowOf(mIcon.getDrawable());
assertThat(shadowDrawable.getCreatedFromResId()).isEqualTo(R.drawable.ic_warning);
}
@Test
public void setPositiveButtonText_shouldShowPositiveButton() {
mBannerPreference.setPositiveButtonText(TEST_STRING_RES_ID);
mBannerPreference.onBindViewHolder(mHolder);
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));
} }
@Test @Test
public void setNegativeButtonText_shouldShowNegativeButton() { public void setNegativeButtonText_shouldShowNegativeButton() {
mBannerPreference.setNegativeButtonText(R.string.tts_settings_title); mBannerPreference.setNegativeButtonText(TEST_STRING_RES_ID);
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
assertThat(((Button) mRootView.findViewById(R.id.banner_negative_btn)).getVisibility()) Button mNegativeButton = mRootView.findViewById(R.id.banner_negative_btn);
.isEqualTo(View.VISIBLE); assertThat(mNegativeButton.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mNegativeButton.getText()).isEqualTo(mContext.getString(TEST_STRING_RES_ID));
} }
@Test @Test
public void withoutSetPositiveButtonText_shouldHidePositiveButton() { public void withoutSetPositiveButtonText_shouldHidePositiveButton() {
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
assertThat(((Button) mRootView.findViewById(R.id.banner_positive_btn)).getVisibility()) assertThat(mRootView.findViewById(R.id.banner_positive_btn).getVisibility())
.isEqualTo(View.GONE); .isEqualTo(View.GONE);
} }
@@ -99,51 +206,290 @@ public class BannerMessagePreferenceTest {
public void withoutSetNegativeButtonText_shouldHideNegativeButton() { public void withoutSetNegativeButtonText_shouldHideNegativeButton() {
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
assertThat(((Button) mRootView.findViewById(R.id.banner_negative_btn)).getVisibility()) assertThat(mRootView.findViewById(R.id.banner_negative_btn).getVisibility())
.isEqualTo(View.GONE); .isEqualTo(View.GONE);
} }
@Test @Test
public void setPositiveButtonVisible_withTrue_shouldShowPositiveButton() { public void setPositiveButtonVisible_withTrue_shouldShowPositiveButton() {
mBannerPreference.setPositiveButtonText(R.string.tts_settings_title); mBannerPreference.setPositiveButtonText(TEST_STRING_RES_ID);
mBannerPreference.setPositiveButtonVisible(true); mBannerPreference.setPositiveButtonVisible(true);
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
assertThat(((Button) mRootView.findViewById(R.id.banner_positive_btn)).getVisibility()) assertThat((mRootView.findViewById(R.id.banner_positive_btn)).getVisibility())
.isEqualTo(View.VISIBLE); .isEqualTo(View.VISIBLE);
} }
@Test @Test
public void setPositiveButtonVisible_withFalse_shouldHidePositiveButton() { public void setPositiveButtonVisible_withFalse_shouldHidePositiveButton() {
mBannerPreference.setPositiveButtonText(R.string.tts_settings_title); mBannerPreference.setPositiveButtonText(TEST_STRING_RES_ID);
mBannerPreference.setPositiveButtonVisible(false); mBannerPreference.setPositiveButtonVisible(false);
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
assertThat(((Button) mRootView.findViewById(R.id.banner_positive_btn)).getVisibility()) assertThat(mRootView.findViewById(R.id.banner_positive_btn).getVisibility())
.isEqualTo(View.GONE); .isEqualTo(View.GONE);
} }
@Test @Test
public void setNegativeButtonVisible_withTrue_shouldShowNegativeButton() { public void setNegativeButtonVisible_withTrue_shouldShowNegativeButton() {
mBannerPreference.setNegativeButtonText(R.string.tts_settings_title); mBannerPreference.setNegativeButtonText(TEST_STRING_RES_ID);
mBannerPreference.setNegativeButtonVisible(true); mBannerPreference.setNegativeButtonVisible(true);
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
assertThat(((Button) mRootView.findViewById(R.id.banner_negative_btn)).getVisibility()) assertThat(mRootView.findViewById(R.id.banner_negative_btn).getVisibility())
.isEqualTo(View.VISIBLE); .isEqualTo(View.VISIBLE);
} }
@Test @Test
public void setNegativeButtonVisible_withFalse_shouldHideNegativeButton() { public void setNegativeButtonVisible_withFalse_shouldHideNegativeButton() {
mBannerPreference.setNegativeButtonText(R.string.tts_settings_title); mBannerPreference.setNegativeButtonText(TEST_STRING_RES_ID);
mBannerPreference.setNegativeButtonVisible(false); mBannerPreference.setNegativeButtonVisible(false);
mBannerPreference.onBindViewHolder(mHolder); mBannerPreference.onBindViewHolder(mHolder);
assertThat(((Button) mRootView.findViewById(R.id.banner_negative_btn)).getVisibility()) assertThat(mRootView.findViewById(R.id.banner_negative_btn).getVisibility())
.isEqualTo(View.GONE); .isEqualTo(View.GONE);
} }
@Test
public void setPositiveButtonOnClickListener_setsClickListener() {
mBannerPreference.setPositiveButtonOnClickListener(mClickListener);
mBannerPreference.onBindViewHolder(mHolder);
mRootView.findViewById(R.id.banner_positive_btn).callOnClick();
assertThat(mClickListenerCalled).isTrue();
}
@Test
public void setNegativeButtonOnClickListener_setsClickListener() {
mBannerPreference.setNegativeButtonOnClickListener(mClickListener);
mBannerPreference.onBindViewHolder(mHolder);
mRootView.findViewById(R.id.banner_negative_btn).callOnClick();
assertThat(mClickListenerCalled).isTrue();
}
@Test
public void setDismissButtonOnClickListener_whenAtLeastS_setsClickListener() {
assumeAndroidS();
mBannerPreference.setDismissButtonOnClickListener(mClickListener);
mBannerPreference.onBindViewHolder(mHolder);
mRootView.findViewById(R.id.banner_dismiss_btn).callOnClick();
assertThat(mClickListenerCalled).isTrue();
}
@Test
public void onBindViewHolder_whenAtLeastS_withDismissOnClickListener_dismissIsVisible() {
assumeAndroidS();
mBannerPreference.setDismissButtonOnClickListener(mClickListener);
mBannerPreference.onBindViewHolder(mHolder);
assertThat((mRootView.findViewById(R.id.banner_dismiss_btn)).getVisibility())
.isEqualTo(View.VISIBLE);
}
@Test
public void onBindViewHolder_whenAtLeastS_withNoDismissClickListener_dimissButtonIsGone() {
assumeAndroidS();
mBannerPreference.onBindViewHolder(mHolder);
assertThat((mRootView.findViewById(R.id.banner_dismiss_btn)).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void onBindViewHolder_whenAtLeastS_withNoClickListenerAndVisible_dimissButtonIsGone() {
assumeAndroidS();
mBannerPreference.setDismissButtonVisible(true);
mBannerPreference.onBindViewHolder(mHolder);
assertThat(mRootView.findViewById(R.id.banner_dismiss_btn).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void onBindViewHolder_whenAtLeastS_withClickListenerAndNotVisible_dimissButtonIsGone() {
assumeAndroidS();
mBannerPreference.setDismissButtonOnClickListener(mClickListener);
mBannerPreference.setDismissButtonVisible(false);
mBannerPreference.onBindViewHolder(mHolder);
ImageButton mDismissButton = mRootView.findViewById(R.id.banner_dismiss_btn);
assertThat(mDismissButton.getVisibility()).isEqualTo(View.GONE);
}
@Test
public void onBindViewHolder_whenAtLeastS_whenAttentionUnset_setsHighTheme() {
assumeAndroidS();
Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
mRootView.setBackground(mCardBackgroundSpy);
mBannerPreference.onBindViewHolder(mHolder);
assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
.isEqualTo(getColorFilter(R.color.banner_accent_attention_high));
assertThat(getButtonColor(R.id.banner_positive_btn))
.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));
}
@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();
mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet);
mBannerPreference.onBindViewHolder(mHolder);
assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
.isEqualTo(getColorFilter(R.color.banner_accent_attention_high));
assertThat(getButtonColor(R.id.banner_positive_btn))
.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));
}
@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();
mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet);
mBannerPreference.onBindViewHolder(mHolder);
assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
.isEqualTo(getColorFilter(R.color.banner_accent_attention_medium));
assertThat(getButtonColor(R.id.banner_positive_btn))
.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));
}
@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();
mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet);
mBannerPreference.onBindViewHolder(mHolder);
assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
.isEqualTo(getColorFilter(R.color.banner_accent_attention_low));
assertThat(getButtonColor(R.id.banner_positive_btn))
.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));
}
@Test
public void setAttentionLevel_whenAtLeastS_whenHighAttention_setsHighTheme() {
assumeAndroidS();
Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
mRootView.setBackground(mCardBackgroundSpy);
mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.HIGH);
mBannerPreference.onBindViewHolder(mHolder);
assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
.isEqualTo(getColorFilter(R.color.banner_accent_attention_high));
assertThat(getButtonColor(R.id.banner_positive_btn))
.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));
}
@Test
public void setAttentionLevel_whenAtLeastS_whenMedAttention_setsMediumTheme() {
assumeAndroidS();
Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
mRootView.setBackground(mCardBackgroundSpy);
mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.MEDIUM);
mBannerPreference.onBindViewHolder(mHolder);
assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
.isEqualTo(getColorFilter(R.color.banner_accent_attention_medium));
assertThat(getButtonColor(R.id.banner_positive_btn))
.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));
}
@Test
public void setAttentionLevel_whenAtLeastS_whenLowAttention_setsLowTheme() {
assumeAndroidS();
Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
mRootView.setBackground(mCardBackgroundSpy);
mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.LOW);
mBannerPreference.onBindViewHolder(mHolder);
assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
.isEqualTo(getColorFilter(R.color.banner_accent_attention_low));
assertThat(getButtonColor(R.id.banner_positive_btn))
.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));
}
private int getButtonColor(int buttonResId) {
Button mButton = mRootView.findViewById(buttonResId);
return mButton.getTextColors().getDefaultColor();
}
private ColorFilter getColorFilter(@ColorRes int colorResId) {
return new PorterDuffColorFilter(getColorId(colorResId), PorterDuff.Mode.SRC_IN);
}
private int getColorId(@ColorRes int colorResId) {
return mContext.getResources().getColor(colorResId, mContext.getTheme());
}
private void assumeAndroidR() {
ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 30);
// Reset view holder to use correct layout.
}
private void assumeAndroidS() {
ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 31);
// Re-inflate view to update layout.
setUpViewHolder();
}
private void setUpViewHolder() {
mRootView =
View.inflate(mContext, mBannerPreference.getLayoutResource(), null /* parent */);
mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
}
} }