Merge "More tests for background tinting of AppCompatTextView" into mnc-ub-dev
diff --git a/v7/appcompat/tests/res/color/color_state_list_emerald_translucent.xml b/v7/appcompat/tests/res/color/color_state_list_emerald_translucent.xml
new file mode 100644
index 0000000..56fd16a
--- /dev/null
+++ b/v7/appcompat/tests/res/color/color_state_list_emerald_translucent.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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:color="@color/emerald_translucent_disabled" />
+ <item android:color="@color/emerald_translucent_default"/>
+</selector>
+
diff --git a/v7/appcompat/tests/res/drawable-mdpi/test_drawable.png b/v7/appcompat/tests/res/drawable-mdpi/test_drawable.png
index 1ce5321..c66ad10 100644
--- a/v7/appcompat/tests/res/drawable-mdpi/test_drawable.png
+++ b/v7/appcompat/tests/res/drawable-mdpi/test_drawable.png
Binary files differ
diff --git a/v7/appcompat/tests/res/drawable/test_background_blue.xml b/v7/appcompat/tests/res/drawable/test_background_blue.xml
new file mode 100644
index 0000000..fe4bca2
--- /dev/null
+++ b/v7/appcompat/tests/res/drawable/test_background_blue.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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"
+ android:shape="rectangle">
+ <solid
+ android:color="@color/test_blue" />
+</shape>
\ No newline at end of file
diff --git a/v7/appcompat/tests/res/drawable/test_background_green.xml b/v7/appcompat/tests/res/drawable/test_background_green.xml
new file mode 100644
index 0000000..b90d9bc
--- /dev/null
+++ b/v7/appcompat/tests/res/drawable/test_background_green.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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"
+ android:shape="rectangle">
+ <solid
+ android:color="@color/test_green" />
+</shape>
\ No newline at end of file
diff --git a/v7/appcompat/tests/res/drawable/test_background_red.xml b/v7/appcompat/tests/res/drawable/test_background_red.xml
new file mode 100644
index 0000000..87d808b
--- /dev/null
+++ b/v7/appcompat/tests/res/drawable/test_background_red.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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"
+ android:shape="rectangle">
+ <solid
+ android:color="@color/test_red" />
+</shape>
\ No newline at end of file
diff --git a/v7/appcompat/tests/res/layout/appcompat_textview_activity.xml b/v7/appcompat/tests/res/layout/appcompat_textview_activity.xml
index c621d0b..a7b33e6 100644
--- a/v7/appcompat/tests/res/layout/appcompat_textview_activity.xml
+++ b/v7/appcompat/tests/res/layout/appcompat_textview_activity.xml
@@ -40,7 +40,7 @@
android:text="@string/sample_text2" />
<android.support.v7.widget.AppCompatTextView
- android:id="@+id/text_view_no_background"
+ android:id="@+id/text_view_tinted_no_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/sample_text1"
@@ -48,13 +48,26 @@
app:backgroundTintMode="src_in" />
<android.support.v7.widget.AppCompatTextView
- android:id="@+id/text_view_tinted"
+ android:id="@+id/text_view_tinted_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/sample_text2"
android:background="@drawable/test_drawable"
app:backgroundTint="@color/color_state_list_lilac"
app:backgroundTintMode="src_in" />
+
+ <android.support.v7.widget.AppCompatTextView
+ android:id="@+id/text_view_untinted_no_background"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/sample_text2" />
+
+ <android.support.v7.widget.AppCompatTextView
+ android:id="@+id/text_view_untinted_background"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/sample_text2"
+ android:background="@drawable/test_background_green" />
</LinearLayout>
</ScrollView>
diff --git a/v7/appcompat/tests/res/values/colors.xml b/v7/appcompat/tests/res/values/colors.xml
index 7f13157..eaf38da 100644
--- a/v7/appcompat/tests/res/values/colors.xml
+++ b/v7/appcompat/tests/res/values/colors.xml
@@ -27,4 +27,7 @@
<color name="sand_disabled">#FFC080</color>
<color name="ocean_default">#50C0FF</color>
<color name="ocean_disabled">#90F0FF</color>
+
+ <color name="emerald_translucent_default">#8020A060</color>
+ <color name="emerald_translucent_disabled">#8070C090</color>
</resources>
diff --git a/v7/appcompat/tests/src/android/support/v7/testutils/AppCompatTintableViewActions.java b/v7/appcompat/tests/src/android/support/v7/testutils/AppCompatTintableViewActions.java
index 769875e..8f86796 100644
--- a/v7/appcompat/tests/src/android/support/v7/testutils/AppCompatTintableViewActions.java
+++ b/v7/appcompat/tests/src/android/support/v7/testutils/AppCompatTintableViewActions.java
@@ -17,6 +17,9 @@
package android.support.v7.testutils;
import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.v4.view.TintableBackgroundView;
@@ -83,4 +86,87 @@
}
};
}
+
+ /**
+ * Sets the passed mode as the background tint mode on a <code>View</code> that
+ * implements the <code>TintableBackgroundView</code> interface.
+ */
+ public static ViewAction setBackgroundTintMode(final PorterDuff.Mode tintMode) {
+ return new ViewAction() {
+ @Override
+ public Matcher<View> getConstraints() {
+ return allOf(isDisplayingAtLeast(90), TestUtilsMatchers.isTintableBackgroundView());
+ }
+
+ @Override
+ public String getDescription() {
+ return "set background tint mode";
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ uiController.loopMainThreadUntilIdle();
+
+ TintableBackgroundView tintableBackgroundView = (TintableBackgroundView) view;
+ tintableBackgroundView.setSupportBackgroundTintMode(tintMode);
+
+ uiController.loopMainThreadUntilIdle();
+ }
+ };
+ }
+
+ /**
+ * Sets background drawable on a <code>View</code> that implements the
+ * <code>TintableBackgroundView</code> interface.
+ */
+ public static ViewAction setBackgroundDrawable(final Drawable background) {
+ return new ViewAction() {
+ @Override
+ public Matcher<View> getConstraints() {
+ return allOf(TestUtilsMatchers.isTintableBackgroundView());
+ }
+
+ @Override
+ public String getDescription() {
+ return "set background drawable";
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ uiController.loopMainThreadUntilIdle();
+
+ view.setBackgroundDrawable(background);
+
+ uiController.loopMainThreadUntilIdle();
+ }
+ };
+ }
+
+ /**
+ * Sets background resource on a <code>View</code> that implements the
+ * <code>TintableBackgroundView</code> interface.
+ */
+ public static ViewAction setBackgroundResource(final @DrawableRes int resId) {
+ return new ViewAction() {
+ @Override
+ public Matcher<View> getConstraints() {
+ return allOf(TestUtilsMatchers.isTintableBackgroundView());
+ }
+
+ @Override
+ public String getDescription() {
+ return "set background resource";
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ uiController.loopMainThreadUntilIdle();
+
+ view.setBackgroundResource(resId);
+
+ uiController.loopMainThreadUntilIdle();
+ }
+ };
+ }
+
}
diff --git a/v7/appcompat/tests/src/android/support/v7/testutils/TestUtils.java b/v7/appcompat/tests/src/android/support/v7/testutils/TestUtils.java
index c366381..ae8e681 100644
--- a/v7/appcompat/tests/src/android/support/v7/testutils/TestUtils.java
+++ b/v7/appcompat/tests/src/android/support/v7/testutils/TestUtils.java
@@ -36,7 +36,7 @@
*/
public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Drawable drawable,
int drawableWidth, int drawableHeight, boolean callSetBounds, @ColorInt int color,
- boolean throwExceptionIfFails) {
+ int allowedComponentVariance, boolean throwExceptionIfFails) {
// Create a bitmap
Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight, Bitmap.Config.ARGB_8888);
// Create a canvas that wraps the bitmap
@@ -53,15 +53,34 @@
for (int row = 0; row < drawableHeight; row++) {
bitmap.getPixels(rowPixels, 0, drawableWidth, 0, row, drawableWidth, 1);
for (int column = 0; column < drawableWidth; column++) {
- if (rowPixels[column] != color) {
+ int sourceAlpha = Color.alpha(rowPixels[column]);
+ int sourceRed = Color.red(rowPixels[column]);
+ int sourceGreen = Color.green(rowPixels[column]);
+ int sourceBlue = Color.blue(rowPixels[column]);
+
+ int expectedAlpha = Color.alpha(color);
+ int expectedRed = Color.red(color);
+ int expectedGreen = Color.green(color);
+ int expectedBlue = Color.blue(color);
+
+ int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
+ int varianceRed = Math.abs(sourceRed - expectedRed);
+ int varianceGreen = Math.abs(sourceGreen - expectedGreen);
+ int varianceBlue = Math.abs(sourceBlue - expectedBlue);
+
+ boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
+ && (varianceRed <= allowedComponentVariance)
+ && (varianceGreen <= allowedComponentVariance)
+ && (varianceBlue <= allowedComponentVariance);
+
+ if (!isColorMatch) {
String mismatchDescription = failMessagePrefix
+ ": expected all drawable colors to be ["
- + Color.red(color) + "," + Color.green(color) + ","
- + Color.blue(color)
+ + expectedAlpha + "," + expectedRed + ","
+ + expectedGreen + "," + expectedBlue
+ "] but at position (" + row + "," + column + ") found ["
- + Color.red(rowPixels[column]) + ","
- + Color.green(rowPixels[column]) + ","
- + Color.blue(rowPixels[column]) + "]";
+ + sourceAlpha + "," + sourceRed + ","
+ + sourceGreen + "," + sourceBlue + "]";
if (throwExceptionIfFails) {
throw new RuntimeException(mismatchDescription);
} else {
diff --git a/v7/appcompat/tests/src/android/support/v7/testutils/TestUtilsMatchers.java b/v7/appcompat/tests/src/android/support/v7/testutils/TestUtilsMatchers.java
index 5a4bb4a..cab4518 100644
--- a/v7/appcompat/tests/src/android/support/v7/testutils/TestUtilsMatchers.java
+++ b/v7/appcompat/tests/src/android/support/v7/testutils/TestUtilsMatchers.java
@@ -58,7 +58,7 @@
// all pixels in a Drawable are of the same specified color.
try {
TestUtils.assertAllPixelsOfColor("", drawable, view.getWidth(),
- view.getHeight(), true, color, true);
+ view.getHeight(), true, color, 0, true);
// If we are here, the color comparison has passed.
failedComparisonDescription = null;
return true;
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java
index cd92e6a..d31ce90 100644
--- a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java
@@ -17,11 +17,13 @@
import android.content.res.ColorStateList;
import android.content.res.Resources;
-import android.graphics.Rect;
+import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
+import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.v4.content.res.ResourcesCompat;
+import android.support.v4.graphics.ColorUtils;
import android.support.v7.appcompat.test.R;
import android.support.v7.testutils.AppCompatTextViewActions;
import android.support.v7.testutils.AppCompatTintableViewActions;
@@ -83,18 +85,23 @@
}
private void verifyBackgroundIsColoredAs(String description,
- @NonNull AppCompatTextView textView, @ColorInt int color) {
- final Drawable background = textView.getBackground();
- final Rect backgroundBounds = background.getBounds();
+ @NonNull AppCompatTextView textView, @ColorInt int color,
+ int allowedComponentVariance) {
+ Drawable background = textView.getBackground();
TestUtils.assertAllPixelsOfColor(description,
- background, backgroundBounds.width(), backgroundBounds.height(), false,
- color, false);
+ background, textView.getWidth(), textView.getHeight(), true,
+ color, allowedComponentVariance, false);
}
+ /**
+ * This method tests that background tinting is not applied when the
+ * <code>AppCompatTextView</code> has no background.
+ */
@SmallTest
public void testBackgroundTintingWithNoBackground() {
+ final @IdRes int textViewId = R.id.text_view_tinted_no_background;
final AppCompatTextView textView =
- (AppCompatTextView) mContainer.findViewById(R.id.text_view_no_background);
+ (AppCompatTextView) mContainer.findViewById(textViewId);
// Note that all the asserts in this test check that the AppCompatTextView background
// is null. This is because the matching child in the activity doesn't define any
@@ -103,12 +110,12 @@
assertNull("No background after XML loading", textView.getBackground());
// Disable the text view and check that the background is still null.
- onView(withId(R.id.text_view_tinted)).perform(
+ onView(withId(textViewId)).perform(
AppCompatTintableViewActions.setEnabled(false));
assertNull("No background after disabling", textView.getBackground());
// Enable the text view and check that the background is still null.
- onView(withId(R.id.text_view_tinted)).perform(
+ onView(withId(textViewId)).perform(
AppCompatTintableViewActions.setEnabled(true));
assertNull("No background after re-enabling", textView.getBackground());
@@ -116,22 +123,28 @@
// is still null.
final ColorStateList sandColor = ResourcesCompat.getColorStateList(
getActivity().getResources(), R.color.color_state_list_sand, null);
- onView(withId(R.id.text_view_tinted)).perform(
+ onView(withId(textViewId)).perform(
AppCompatTintableViewActions.setBackgroundTintList(sandColor));
// Disable the text view and check that the background is still null.
- onView(withId(R.id.text_view_tinted)).perform(
+ onView(withId(textViewId)).perform(
AppCompatTintableViewActions.setEnabled(false));
assertNull("No background after disabling", textView.getBackground());
// Enable the text view and check that the background is still null.
- onView(withId(R.id.text_view_tinted)).perform(
+ onView(withId(textViewId)).perform(
AppCompatTintableViewActions.setEnabled(true));
assertNull("No background after re-enabling", textView.getBackground());
}
+ /**
+ * This method tests that background tinting is applied to <code>AppCompatTextView</code>
+ * in enabled and disabled state across a number of <code>ColorStateList</code>s set as
+ * background tint lists on the same background.
+ */
@SmallTest
- public void testBackgroundTinting() {
+ public void testBackgroundTintingAcrossStateChange() {
+ final @IdRes int textViewId = R.id.text_view_tinted_background;
final Resources res = getActivity().getResources();
@ColorInt int lilacDefault = ResourcesCompat.getColor(res, R.color.lilac_default, null);
@@ -141,71 +154,281 @@
@ColorInt int oceanDefault = ResourcesCompat.getColor(res, R.color.ocean_default, null);
@ColorInt int oceanDisabled = ResourcesCompat.getColor(res, R.color.ocean_disabled, null);
- final AppCompatTextView textViewTinted =
- (AppCompatTextView) mContainer.findViewById(R.id.text_view_tinted);
+ final AppCompatTextView textView =
+ (AppCompatTextView) mContainer.findViewById(textViewId);
- // Test the default state from tinting set up in the layout XML file.
- verifyBackgroundIsColoredAs("Default lilac tinting in enabled state", textViewTinted,
- lilacDefault);
+ // Test the default state for tinting set up in the layout XML file.
+ verifyBackgroundIsColoredAs("Default lilac tinting in enabled state", textView,
+ lilacDefault, 0);
// Disable the text view and check that the background has switched to the matching entry
// in the default color state list.
- onView(withId(R.id.text_view_tinted)).perform(
- AppCompatTintableViewActions.setEnabled(false));
- verifyBackgroundIsColoredAs("Default lilac tinting in disabled state", textViewTinted,
- lilacDisabled);
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(false));
+ verifyBackgroundIsColoredAs("Default lilac tinting in disabled state", textView,
+ lilacDisabled, 0);
// Enable the text view and check that the background has switched to the matching entry
// in the default color state list.
- onView(withId(R.id.text_view_tinted)).perform(
- AppCompatTintableViewActions.setEnabled(true));
- verifyBackgroundIsColoredAs("Default lilac tinting in re-enabled state", textViewTinted,
- lilacDefault);
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(true));
+ verifyBackgroundIsColoredAs("Default lilac tinting in re-enabled state", textView,
+ lilacDefault, 0);
// Load a new color state list, set it on the text view and check that the background has
// switched to the matching entry in newly set color state list.
final ColorStateList sandColor = ResourcesCompat.getColorStateList(
- getActivity().getResources(), R.color.color_state_list_sand, null);
- onView(withId(R.id.text_view_tinted)).perform(
+ res, R.color.color_state_list_sand, null);
+ onView(withId(textViewId)).perform(
AppCompatTintableViewActions.setBackgroundTintList(sandColor));
- verifyBackgroundIsColoredAs("New sand tinting in enabled state", textViewTinted,
- sandDefault);
+ verifyBackgroundIsColoredAs("New sand tinting in enabled state", textView,
+ sandDefault, 0);
// Disable the text view and check that the background has switched to the matching entry
// in the newly set color state list.
- onView(withId(R.id.text_view_tinted)).perform(
- AppCompatTintableViewActions.setEnabled(false));
- verifyBackgroundIsColoredAs("New sand tinting in disabled state", textViewTinted,
- sandDisabled);
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(false));
+ verifyBackgroundIsColoredAs("New sand tinting in disabled state", textView,
+ sandDisabled, 0);
// Enable the text view and check that the background has switched to the matching entry
// in the newly set color state list.
- onView(withId(R.id.text_view_tinted)).perform(
- AppCompatTintableViewActions.setEnabled(true));
- verifyBackgroundIsColoredAs("New sand tinting in re-enabled state", textViewTinted,
- sandDefault);
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(true));
+ verifyBackgroundIsColoredAs("New sand tinting in re-enabled state", textView,
+ sandDefault, 0);
// Load another color state list, set it on the text view and check that the background has
// switched to the matching entry in newly set color state list.
final ColorStateList oceanColor = ResourcesCompat.getColorStateList(
- getActivity().getResources(), R.color.color_state_list_ocean, null);
- onView(withId(R.id.text_view_tinted)).perform(
+ res, R.color.color_state_list_ocean, null);
+ onView(withId(textViewId)).perform(
AppCompatTintableViewActions.setBackgroundTintList(oceanColor));
- verifyBackgroundIsColoredAs("New ocean tinting in enabled state", textViewTinted,
- oceanDefault);
+ verifyBackgroundIsColoredAs("New ocean tinting in enabled state", textView,
+ oceanDefault, 0);
// Disable the text view and check that the background has switched to the matching entry
// in the newly set color state list.
- onView(withId(R.id.text_view_tinted)).perform(
- AppCompatTintableViewActions.setEnabled(false));
- verifyBackgroundIsColoredAs("New ocean tinting in disabled state", textViewTinted,
- oceanDisabled);
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(false));
+ verifyBackgroundIsColoredAs("New ocean tinting in disabled state", textView,
+ oceanDisabled, 0);
// Enable the text view and check that the background has switched to the matching entry
// in the newly set color state list.
- onView(withId(R.id.text_view_tinted)).perform(
- AppCompatTintableViewActions.setEnabled(true));
- verifyBackgroundIsColoredAs("New ocean tinting in re-enabled state", textViewTinted,
- oceanDefault);
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(true));
+ verifyBackgroundIsColoredAs("New ocean tinting in re-enabled state", textView,
+ oceanDefault, 0);
+ }
+
+ /**
+ * This method tests that background tinting applied to <code>AppCompatTextView</code>
+ * in enabled and disabled state across the same background respects the currently set
+ * background tinting mode.
+ */
+ @SmallTest
+ public void testBackgroundTintingAcrossModeChange() {
+ final @IdRes int textViewId = R.id.text_view_untinted_background;
+ final Resources res = getActivity().getResources();
+
+ @ColorInt int emeraldDefault = ResourcesCompat.getColor(
+ res, R.color.emerald_translucent_default, null);
+ @ColorInt int emeraldDisabled = ResourcesCompat.getColor(
+ res, R.color.emerald_translucent_disabled, null);
+ // This is the fill color of R.drawable.test_background_green set on our text view
+ // that we'll be testing in this method
+ @ColorInt int backgroundColor = ResourcesCompat.getColor(
+ res, R.color.test_green, null);
+
+ final AppCompatTextView textView =
+ (AppCompatTextView) mContainer.findViewById(textViewId);
+
+ // Test the default state for tinting set up in the layout XML file.
+ verifyBackgroundIsColoredAs("Default no tinting in enabled state", textView,
+ backgroundColor, 0);
+
+ // From this point on in this method we're allowing a margin of error in checking the
+ // color of the text view background. This is due to both translucent colors being used
+ // in the color state list and off-by-one discrepancies of SRC_OVER when it's compositing
+ // translucent color on top of solid fill color. This is where the allowed variance
+ // value of 2 comes from - one for compositing and one for color translucency.
+ final int allowedComponentVariance = 2;
+
+ // Set src_in tint mode on our text view
+ onView(withId(textViewId)).perform(
+ AppCompatTintableViewActions.setBackgroundTintMode(PorterDuff.Mode.SRC_IN));
+
+ // Load a new color state list, set it on the text view and check that the background has
+ // switched to the matching entry in newly set color state list.
+ final ColorStateList emeraldColor = ResourcesCompat.getColorStateList(
+ res, R.color.color_state_list_emerald_translucent, null);
+ onView(withId(textViewId)).perform(
+ AppCompatTintableViewActions.setBackgroundTintList(emeraldColor));
+ verifyBackgroundIsColoredAs("New emerald tinting in enabled state under src_in", textView,
+ emeraldDefault, allowedComponentVariance);
+
+ // Disable the text view and check that the background has switched to the matching entry
+ // in the newly set color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(false));
+ verifyBackgroundIsColoredAs("New emerald tinting in disabled state under src_in", textView,
+ emeraldDisabled, allowedComponentVariance);
+
+ // Set src_over tint mode on our text view. As the currently set tint list is using
+ // translucent colors, we expect the actual background of the view to be different under
+ // this new mode (unlike src_in and src_over that behave identically when the destination is
+ // a fully filled rectangle and the source is an opaque color).
+ onView(withId(textViewId)).perform(
+ AppCompatTintableViewActions.setBackgroundTintMode(PorterDuff.Mode.SRC_OVER));
+
+ // Enable the text view and check that the background has switched to the matching entry
+ // in the color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(true));
+ verifyBackgroundIsColoredAs("New emerald tinting in enabled state under src_over", textView,
+ ColorUtils.compositeColors(emeraldDefault, backgroundColor),
+ allowedComponentVariance);
+
+ // Disable the text view and check that the background has switched to the matching entry
+ // in the newly set color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(false));
+ verifyBackgroundIsColoredAs("New emerald tinting in disabled state under src_over",
+ textView, ColorUtils.compositeColors(emeraldDisabled, backgroundColor),
+ allowedComponentVariance);
+ }
+
+ /**
+ * This method tests that opaque background tinting applied to <code>AppCompatTextView</code>
+ * is applied correctly after changing the background itself of the view.
+ */
+ @SmallTest
+ public void testBackgroundOpaqueTintingAcrossBackgroundChange() {
+ final @IdRes int textViewId = R.id.text_view_tinted_no_background;
+ final Resources res = getActivity().getResources();
+
+ @ColorInt int lilacDefault = ResourcesCompat.getColor(res, R.color.lilac_default, null);
+ @ColorInt int lilacDisabled = ResourcesCompat.getColor(res, R.color.lilac_disabled, null);
+
+ final AppCompatTextView textView =
+ (AppCompatTextView) mContainer.findViewById(textViewId);
+
+ assertNull("No background after XML loading", textView.getBackground());
+
+ // Set background on our text view
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setBackgroundDrawable(
+ ResourcesCompat.getDrawable(res, R.drawable.test_background_green, null)));
+
+ // Test the default state for tinting set up in the layout XML file.
+ verifyBackgroundIsColoredAs("Default lilac tinting in enabled state on green BG",
+ textView, lilacDefault, 0);
+
+ // Disable the text view and check that the background has switched to the matching entry
+ // in the default color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(false));
+ verifyBackgroundIsColoredAs("Default lilac tinting in disabled state on green BG",
+ textView, lilacDisabled, 0);
+
+ // Enable the text view and check that the background has switched to the matching entry
+ // in the default color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(true));
+ verifyBackgroundIsColoredAs("Default lilac tinting in re-enabled state on green BG",
+ textView, lilacDefault, 0);
+
+ // Set a different background on our view based on resource ID
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setBackgroundResource(
+ R.drawable.test_background_red));
+
+ // Test the default state for tinting set up in the layout XML file.
+ verifyBackgroundIsColoredAs("Default lilac tinting in enabled state on red BG",
+ textView, lilacDefault, 0);
+
+ // Disable the text view and check that the background has switched to the matching entry
+ // in the default color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(false));
+ verifyBackgroundIsColoredAs("Default lilac tinting in disabled state on red BG",
+ textView, lilacDisabled, 0);
+
+ // Enable the text view and check that the background has switched to the matching entry
+ // in the default color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(true));
+ verifyBackgroundIsColoredAs("Default lilac tinting in re-enabled state on red BG",
+ textView, lilacDefault, 0);
+ }
+
+ /**
+ * This method tests that translucent background tinting applied to <code>AppCompatTextView</code>
+ * is applied correctly after changing the background itself of the view.
+ */
+ @SmallTest
+ public void testBackgroundTranslucentTintingAcrossBackgroundChange() {
+ final @IdRes int textViewId = R.id.text_view_untinted_no_background;
+ final Resources res = getActivity().getResources();
+
+ @ColorInt int emeraldDefault = ResourcesCompat.getColor(
+ res, R.color.emerald_translucent_default, null);
+ @ColorInt int emeraldDisabled = ResourcesCompat.getColor(
+ res, R.color.emerald_translucent_disabled, null);
+ // This is the fill color of R.drawable.test_background_green set on our text view
+ // that we'll be testing in this method
+ @ColorInt int backgroundColorGreen = ResourcesCompat.getColor(
+ res, R.color.test_green, null);
+ @ColorInt int backgroundColorRed = ResourcesCompat.getColor(
+ res, R.color.test_red, null);
+
+ final AppCompatTextView textView =
+ (AppCompatTextView) mContainer.findViewById(textViewId);
+
+ assertNull("No background after XML loading", textView.getBackground());
+
+ // Set src_over tint mode on our text view. As the currently set tint list is using
+ // translucent colors, we expect the actual background of the view to be different under
+ // this new mode (unlike src_in and src_over that behave identically when the destination is
+ // a fully filled rectangle and the source is an opaque color).
+ onView(withId(textViewId)).perform(
+ AppCompatTintableViewActions.setBackgroundTintMode(PorterDuff.Mode.SRC_OVER));
+ // Load and set a translucent color state list as the background tint list
+ final ColorStateList emeraldColor = ResourcesCompat.getColorStateList(
+ res, R.color.color_state_list_emerald_translucent, null);
+ onView(withId(textViewId)).perform(
+ AppCompatTintableViewActions.setBackgroundTintList(emeraldColor));
+
+ // Set background on our text view
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setBackgroundDrawable(
+ ResourcesCompat.getDrawable(res, R.drawable.test_background_green, null)));
+
+ // From this point on in this method we're allowing a margin of error in checking the
+ // color of the text view background. This is due to both translucent colors being used
+ // in the color state list and off-by-one discrepancies of SRC_OVER when it's compositing
+ // translucent color on top of solid fill color. This is where the allowed variance
+ // value of 2 comes from - one for compositing and one for color translucency.
+
+ // Test the default state for tinting set up with the just loaded tint list.
+ verifyBackgroundIsColoredAs("Emerald tinting in enabled state on green BG",
+ textView, ColorUtils.compositeColors(emeraldDefault, backgroundColorGreen), 2);
+
+ // Disable the text view and check that the background has switched to the matching entry
+ // in the default color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(false));
+ verifyBackgroundIsColoredAs("Emerald tinting in disabled state on green BG",
+ textView, ColorUtils.compositeColors(emeraldDisabled, backgroundColorGreen), 2);
+
+ // Enable the text view and check that the background has switched to the matching entry
+ // in the default color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(true));
+ verifyBackgroundIsColoredAs("Emerald tinting in re-enabled state on green BG",
+ textView, ColorUtils.compositeColors(emeraldDefault, backgroundColorGreen), 2);
+
+ // Set a different background on our view based on resource ID
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setBackgroundResource(
+ R.drawable.test_background_red));
+
+ // Test the default state for tinting the new background with the same color state list
+ verifyBackgroundIsColoredAs("Emerald tinting in enabled state on red BG",
+ textView, ColorUtils.compositeColors(emeraldDefault, backgroundColorRed), 2);
+
+ // Disable the text view and check that the background has switched to the matching entry
+ // in our current color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(false));
+ verifyBackgroundIsColoredAs("Emerald tinting in disabled state on red BG",
+ textView, ColorUtils.compositeColors(emeraldDisabled, backgroundColorRed), 2);
+
+ // Enable the text view and check that the background has switched to the matching entry
+ // in our current color state list.
+ onView(withId(textViewId)).perform(AppCompatTintableViewActions.setEnabled(true));
+ verifyBackgroundIsColoredAs("Emerald tinting in re-enabled state on red BG",
+ textView, ColorUtils.compositeColors(emeraldDefault, backgroundColorRed), 2);
}
}