Add AppCompatImageButton + AppCompatImageView
Moved usage of the old ImageView impl to be
implicit through our view inflater functionality.
Also re-ordered the view order so that more common
views are at the top.
BUG: 21715295
Change-Id: I28eedbc1f7d0bd55fbfbdb5aa85b72a8498f790f
diff --git a/v7/appcompat/api/current.txt b/v7/appcompat/api/current.txt
index f8c7754..f0e90e1 100644
--- a/v7/appcompat/api/current.txt
+++ b/v7/appcompat/api/current.txt
@@ -436,6 +436,7 @@
field public static int homeLayout;
field public static int icon;
field public static int iconifiedByDefault;
+ field public static int imageButtonStyle;
field public static int indeterminateProgressStyle;
field public static int initialActivityCount;
field public static int isLightTheme;
@@ -1066,6 +1067,7 @@
field public static int Base_Widget_AppCompat_DrawerArrowToggle_Common;
field public static int Base_Widget_AppCompat_DropDownItem_Spinner;
field public static int Base_Widget_AppCompat_EditText;
+ field public static int Base_Widget_AppCompat_ImageButton;
field public static int Base_Widget_AppCompat_Light_ActionBar;
field public static int Base_Widget_AppCompat_Light_ActionBar_Solid;
field public static int Base_Widget_AppCompat_Light_ActionBar_TabBar;
@@ -1211,6 +1213,7 @@
field public static int Widget_AppCompat_DrawerArrowToggle;
field public static int Widget_AppCompat_DropDownItem_Spinner;
field public static int Widget_AppCompat_EditText;
+ field public static int Widget_AppCompat_ImageButton;
field public static int Widget_AppCompat_Light_ActionBar;
field public static int Widget_AppCompat_Light_ActionBar_Solid;
field public static int Widget_AppCompat_Light_ActionBar_Solid_Inverse;
@@ -1493,6 +1496,7 @@
field public static int Theme_editTextColor;
field public static int Theme_editTextStyle;
field public static int Theme_homeAsUpIndicator;
+ field public static int Theme_imageButtonStyle;
field public static int Theme_listChoiceBackgroundIndicator;
field public static int Theme_listDividerAlertDialog;
field public static int Theme_listPopupWindowStyle;
@@ -1718,6 +1722,18 @@
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet, int);
}
+ public class AppCompatImageButton extends android.widget.ImageButton {
+ ctor public AppCompatImageButton(android.content.Context);
+ ctor public AppCompatImageButton(android.content.Context, android.util.AttributeSet);
+ ctor public AppCompatImageButton(android.content.Context, android.util.AttributeSet, int);
+ }
+
+ public class AppCompatImageView extends android.widget.ImageView {
+ ctor public AppCompatImageView(android.content.Context);
+ ctor public AppCompatImageView(android.content.Context, android.util.AttributeSet);
+ ctor public AppCompatImageView(android.content.Context, android.util.AttributeSet, int);
+ }
+
public class AppCompatMultiAutoCompleteTextView extends android.widget.MultiAutoCompleteTextView {
ctor public AppCompatMultiAutoCompleteTextView(android.content.Context);
ctor public AppCompatMultiAutoCompleteTextView(android.content.Context, android.util.AttributeSet);
diff --git a/v7/appcompat/res-public/values/public_attrs.xml b/v7/appcompat/res-public/values/public_attrs.xml
index f8fae53..58f0152 100644
--- a/v7/appcompat/res-public/values/public_attrs.xml
+++ b/v7/appcompat/res-public/values/public_attrs.xml
@@ -115,6 +115,7 @@
<public type="attr" name="iconifiedByDefault"/>
<public type="attr" name="indeterminateProgressStyle"/>
<public type="attr" name="isLightTheme"/>
+ <public type="attr" name="imageButtonStyle"/>
<public type="attr" name="itemPadding"/>
<public type="attr" name="layout"/>
<public type="attr" name="listChoiceBackgroundIndicator"/>
diff --git a/v7/appcompat/res-public/values/public_styles.xml b/v7/appcompat/res-public/values/public_styles.xml
index 083fbc6..991ab54 100644
--- a/v7/appcompat/res-public/values/public_styles.xml
+++ b/v7/appcompat/res-public/values/public_styles.xml
@@ -102,6 +102,7 @@
<public type="style" name="Widget.AppCompat.DrawerArrowToggle"/>
<public type="style" name="Widget.AppCompat.DropDownItem.Spinner"/>
<public type="style" name="Widget.AppCompat.EditText"/>
+ <public type="style" name="Widget.AppCompat.ImageButton"/>
<public type="style" name="Widget.AppCompat.Light.ActionBar"/>
<public type="style" name="Widget.AppCompat.Light.ActionBar.Solid"/>
<public type="style" name="Widget.AppCompat.Light.ActionBar.Solid.Inverse"/>
diff --git a/v7/appcompat/res/layout/abc_action_mode_close_item_material.xml b/v7/appcompat/res/layout/abc_action_mode_close_item_material.xml
index dfc4deb..2944d983 100644
--- a/v7/appcompat/res/layout/abc_action_mode_close_item_material.xml
+++ b/v7/appcompat/res/layout/abc_action_mode_close_item_material.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
-<android.support.v7.internal.widget.TintImageView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/action_mode_close_button"
- android:contentDescription="@string/abc_action_mode_done"
- android:focusable="true"
- android:clickable="true"
- android:src="?attr/actionModeCloseDrawable"
- style="?attr/actionModeCloseButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="match_parent" />
\ No newline at end of file
+<ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/action_mode_close_button"
+ android:contentDescription="@string/abc_action_mode_done"
+ android:focusable="true"
+ android:clickable="true"
+ android:src="?attr/actionModeCloseDrawable"
+ style="?attr/actionModeCloseButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"/>
\ No newline at end of file
diff --git a/v7/appcompat/res/layout/abc_search_dropdown_item_icons_2line.xml b/v7/appcompat/res/layout/abc_search_dropdown_item_icons_2line.xml
index 7407498..b81d5d8 100644
--- a/v7/appcompat/res/layout/abc_search_dropdown_item_icons_2line.xml
+++ b/v7/appcompat/res/layout/abc_search_dropdown_item_icons_2line.xml
@@ -24,7 +24,7 @@
<!-- Icons come first in the layout, since their placement doesn't depend on
the placement of the text views. -->
- <android.support.v7.internal.widget.TintImageView
+ <ImageView
android:id="@android:id/icon1"
android:layout_width="@dimen/abc_dropdownitem_icon_width"
android:layout_height="48dip"
@@ -34,7 +34,7 @@
android:visibility="invisible"
style="@style/RtlOverlay.Widget.AppCompat.Search.DropDown.Icon1" />
- <android.support.v7.internal.widget.TintImageView
+ <ImageView
android:id="@+id/edit_query"
android:layout_width="48dip"
android:layout_height="48dip"
@@ -45,7 +45,7 @@
android:visibility="gone"
style="@style/RtlOverlay.Widget.AppCompat.Search.DropDown.Query" />
- <android.support.v7.internal.widget.TintImageView
+ <ImageView
android:id="@id/android:icon2"
android:layout_width="48dip"
android:layout_height="48dip"
diff --git a/v7/appcompat/res/layout/abc_search_view.xml b/v7/appcompat/res/layout/abc_search_view.xml
index ff9361dc..a7446e3 100644
--- a/v7/appcompat/res/layout/abc_search_view.xml
+++ b/v7/appcompat/res/layout/abc_search_view.xml
@@ -35,7 +35,7 @@
android:textColor="?android:attr/textColorPrimary"
android:visibility="gone" />
- <android.support.v7.internal.widget.TintImageView
+ <ImageView
android:id="@+id/search_button"
style="?attr/actionButtonStyle"
android:layout_width="wrap_content"
@@ -57,7 +57,7 @@
android:orientation="horizontal"
android:layoutDirection="locale">
- <android.support.v7.internal.widget.TintImageView
+ <ImageView
android:id="@+id/search_mag_icon"
android:layout_width="@dimen/abc_dropdownitem_icon_width"
android:layout_height="wrap_content"
@@ -94,7 +94,7 @@
android:dropDownVerticalOffset="0dip"
android:dropDownHorizontalOffset="0dip" />
- <android.support.v7.internal.widget.TintImageView
+ <ImageView
android:id="@+id/search_close_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
@@ -113,7 +113,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent">
- <android.support.v7.internal.widget.TintImageView
+ <ImageView
android:id="@+id/search_go_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
@@ -125,7 +125,7 @@
android:focusable="true"
android:contentDescription="@string/abc_searchview_description_submit" />
- <android.support.v7.internal.widget.TintImageView
+ <ImageView
android:id="@+id/search_voice_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
diff --git a/v7/appcompat/res/values-v21/styles_base.xml b/v7/appcompat/res/values-v21/styles_base.xml
index f0c783e..4f11ace 100644
--- a/v7/appcompat/res/values-v21/styles_base.xml
+++ b/v7/appcompat/res/values-v21/styles_base.xml
@@ -188,6 +188,8 @@
<style name="Base.Widget.AppCompat.CompoundButton.RadioButton" parent="android:Widget.Material.CompoundButton.RadioButton" />
+ <style name="Base.Widget.AppCompat.ImageButton" parent="android:Widget.Material.ImageButton" />
+
<!-- Progress Bar -->
<style name="Base.Widget.AppCompat.ProgressBar.Horizontal"
diff --git a/v7/appcompat/res/values/attrs.xml b/v7/appcompat/res/values/attrs.xml
index c5c4244..3300564 100644
--- a/v7/appcompat/res/values/attrs.xml
+++ b/v7/appcompat/res/values/attrs.xml
@@ -239,6 +239,9 @@
<!-- EditText background drawable. -->
<attr name="editTextBackground" format="reference" />
+ <!-- ImageButton background drawable. -->
+ <attr name="imageButtonStyle" format="reference" />
+
<!-- ============================ -->
<!-- SearchView styles and assets -->
<!-- ============================ -->
diff --git a/v7/appcompat/res/values/styles.xml b/v7/appcompat/res/values/styles.xml
index 9453944..95d9483 100644
--- a/v7/appcompat/res/values/styles.xml
+++ b/v7/appcompat/res/values/styles.xml
@@ -218,6 +218,8 @@
<style name="Widget.AppCompat.ButtonBar.AlertDialog" parent="Base.Widget.AppCompat.ButtonBar.AlertDialog" />
+ <style name="Widget.AppCompat.ImageButton" parent="Base.Widget.AppCompat.ImageButton" />
+
<style name="Widget.AppCompat.TextView.SpinnerItem" parent="Base.Widget.AppCompat.TextView.SpinnerItem" />
<style name="AlertDialog.AppCompat" parent="Base.AlertDialog.AppCompat" />
diff --git a/v7/appcompat/res/values/styles_base.xml b/v7/appcompat/res/values/styles_base.xml
index 0c3c056..3017e6f 100644
--- a/v7/appcompat/res/values/styles_base.xml
+++ b/v7/appcompat/res/values/styles_base.xml
@@ -446,6 +446,10 @@
<item name="android:minHeight">@dimen/abc_alert_dialog_button_bar_height</item>
</style>
+ <style name="Base.Widget.AppCompat.ImageButton" parent="android:Widget.ImageButton">
+ <item name="android:background">@drawable/abc_btn_default_mtrl_shape</item>
+ </style>
+
<style name="Base.Widget.AppCompat.TextView.SpinnerItem" parent="android:Widget.TextView.SpinnerItem">
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Widget.TextView.SpinnerItem</item>
<item name="android:paddingLeft">8dp</item>
diff --git a/v7/appcompat/res/values/themes_base.xml b/v7/appcompat/res/values/themes_base.xml
index bb4d308..c946918 100644
--- a/v7/appcompat/res/values/themes_base.xml
+++ b/v7/appcompat/res/values/themes_base.xml
@@ -238,6 +238,8 @@
<item name="buttonStyleSmall">@style/Widget.AppCompat.Button.Small</item>
<item name="android:textAppearanceButton">@style/TextAppearance.AppCompat.Widget.Button</item>
+ <item name="imageButtonStyle">@style/Widget.AppCompat.ImageButton</item>
+
<item name="buttonBarStyle">@style/Widget.AppCompat.ButtonBar</item>
<item name="buttonBarButtonStyle">@style/Widget.AppCompat.Button.ButtonBar.AlertDialog</item>
<item name="buttonBarPositiveButtonStyle">?attr/buttonBarButtonStyle</item>
@@ -391,6 +393,8 @@
<item name="buttonStyleSmall">@style/Widget.AppCompat.Button.Small</item>
<item name="android:textAppearanceButton">@style/TextAppearance.AppCompat.Widget.Button</item>
+ <item name="imageButtonStyle">@style/Widget.AppCompat.ImageButton</item>
+
<item name="buttonBarStyle">@style/Widget.AppCompat.ButtonBar</item>
<item name="buttonBarButtonStyle">@style/Widget.AppCompat.Button.ButtonBar.AlertDialog</item>
<item name="buttonBarPositiveButtonStyle">?attr/buttonBarButtonStyle</item>
diff --git a/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java b/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java
index 7cf3e2d..0eea40b 100644
--- a/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java
+++ b/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java
@@ -31,6 +31,8 @@
import android.support.v7.widget.AppCompatCheckBox;
import android.support.v7.widget.AppCompatCheckedTextView;
import android.support.v7.widget.AppCompatEditText;
+import android.support.v7.widget.AppCompatImageButton;
+import android.support.v7.widget.AppCompatImageView;
import android.support.v7.widget.AppCompatMultiAutoCompleteTextView;
import android.support.v7.widget.AppCompatRadioButton;
import android.support.v7.widget.AppCompatRatingBar;
@@ -89,12 +91,24 @@
// We need to 'inject' our tint aware Views in place of the standard framework versions
switch (name) {
+ case "TextView":
+ view = new AppCompatTextView(context, attrs);
+ break;
+ case "ImageView":
+ view = new AppCompatImageView(context, attrs);
+ break;
+ case "Button":
+ view = new AppCompatButton(context, attrs);
+ break;
case "EditText":
view = new AppCompatEditText(context, attrs);
break;
case "Spinner":
view = new AppCompatSpinner(context, attrs);
break;
+ case "ImageButton":
+ view = new AppCompatImageButton(context, attrs);
+ break;
case "CheckBox":
view = new AppCompatCheckBox(context, attrs);
break;
@@ -113,12 +127,6 @@
case "RatingBar":
view = new AppCompatRatingBar(context, attrs);
break;
- case "Button":
- view = new AppCompatButton(context, attrs);
- break;
- case "TextView":
- view = new AppCompatTextView(context, attrs);
- break;
case "SeekBar":
view = new AppCompatSeekBar(context, attrs);
break;
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/TintImageView.java b/v7/appcompat/src/android/support/v7/internal/widget/TintImageView.java
deleted file mode 100644
index 17dd557..0000000
--- a/v7/appcompat/src/android/support/v7/internal/widget/TintImageView.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v7.internal.widget;
-
-import android.content.Context;
-import android.support.annotation.DrawableRes;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-/**
- * An tint aware {@link android.widget.ImageView}
- *
- * @hide
- */
-public class TintImageView extends ImageView {
-
- private static final int[] TINT_ATTRS = {
- android.R.attr.background,
- android.R.attr.src
- };
-
- private final TintManager mTintManager;
-
- public TintImageView(Context context) {
- this(context, null);
- }
-
- public TintImageView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TintImageView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
-
- TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs, TINT_ATTRS,
- defStyleAttr, 0);
- if (a.length() > 0) {
- if (a.hasValue(0)) {
- setBackgroundDrawable(a.getDrawable(0));
- }
- if (a.hasValue(1)) {
- setImageDrawable(a.getDrawable(1));
- }
- }
- a.recycle();
-
- // Keep the TintManager in case we need it later
- mTintManager = a.getTintManager();
- }
-
- @Override
- public void setImageResource(@DrawableRes int resId) {
- // Intercept this call and instead retrieve the Drawable via the tint manager
- setImageDrawable(mTintManager.getDrawable(resId));
- }
-}
diff --git a/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java b/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java
index 7b68805..e3d04e1 100644
--- a/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java
+++ b/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java
@@ -35,7 +35,6 @@
import android.support.v7.internal.view.menu.MenuPopupHelper;
import android.support.v7.internal.view.menu.MenuView;
import android.support.v7.internal.view.menu.SubMenuBuilder;
-import android.support.v7.internal.widget.TintImageView;
import android.util.SparseBooleanArray;
import android.view.MenuItem;
import android.view.SoundEffectConstants;
@@ -606,7 +605,8 @@
};
}
- private class OverflowMenuButton extends TintImageView implements ActionMenuView.ActionMenuChildView {
+ private class OverflowMenuButton extends AppCompatImageView
+ implements ActionMenuView.ActionMenuChildView {
private final float[] mTempPts = new float[2];
public OverflowMenuButton(Context context) {
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatImageButton.java b/v7/appcompat/src/android/support/v7/widget/AppCompatImageButton.java
new file mode 100644
index 0000000..20c5402
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatImageButton.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v7.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.support.v4.view.TintableBackgroundView;
+import android.support.v7.appcompat.R;
+import android.support.v7.internal.widget.TintManager;
+import android.util.AttributeSet;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+
+/**
+ * A {@link ImageButton} which supports compatible features on older version of the platform,
+ * including:
+ * <ul>
+ * <li>Allows dynamic tint of it background via the background tint methods in
+ * {@link android.support.v4.view.ViewCompat}.</li>
+ * <li>Allows setting of the background tint using {@link R.attr#backgroundTint} and
+ * {@link R.attr#backgroundTintMode}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link android.widget.ImageButton} in your
+ * layouts. You should only need to manually use this class when writing custom views.</p>
+ */
+public class AppCompatImageButton extends ImageButton implements TintableBackgroundView {
+
+ private AppCompatBackgroundHelper mBackgroundTintHelper;
+ private AppCompatImageHelper mImageHelper;
+
+ public AppCompatImageButton(Context context) {
+ this(context, null);
+ }
+
+ public AppCompatImageButton(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.imageButtonStyle);
+ }
+
+ public AppCompatImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ final TintManager tintManager = TintManager.get(context);
+
+ mBackgroundTintHelper = new AppCompatBackgroundHelper(this, tintManager);
+ mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
+
+ mImageHelper = new AppCompatImageHelper(this, tintManager);
+ mImageHelper.loadFromAttributes(attrs, defStyleAttr);
+ }
+
+ @Override
+ public void setImageResource(@DrawableRes int resId) {
+ // Intercept this call and instead retrieve the Drawable via the image helper
+ mImageHelper.setImageResource(resId);
+ }
+
+ @Override
+ public void setBackgroundResource(@DrawableRes int resId) {
+ super.setBackgroundResource(resId);
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.onSetBackgroundResource(resId);
+ }
+ }
+
+ @Override
+ public void setBackgroundDrawable(Drawable background) {
+ super.setBackgroundDrawable(background);
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.onSetBackgroundDrawable(background);
+ }
+ }
+
+ /**
+ * This should be accessed via
+ * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
+ *
+ * @hide
+ */
+ @Override
+ public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.setSupportBackgroundTintList(tint);
+ }
+ }
+
+ /**
+ * This should be accessed via
+ * {@link android.support.v4.view.ViewCompat#getBackgroundTintList(android.view.View)}
+ *
+ * @hide
+ */
+ @Override
+ @Nullable
+ public ColorStateList getSupportBackgroundTintList() {
+ return mBackgroundTintHelper != null
+ ? mBackgroundTintHelper.getSupportBackgroundTintList() : null;
+ }
+
+ /**
+ * This should be accessed via
+ * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
+ *
+ * @hide
+ */
+ @Override
+ public void setSupportBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.setSupportBackgroundTintMode(tintMode);
+ }
+ }
+
+ /**
+ * This should be accessed via
+ * {@link android.support.v4.view.ViewCompat#getBackgroundTintMode(android.view.View)}
+ *
+ * @hide
+ */
+ @Override
+ @Nullable
+ public PorterDuff.Mode getSupportBackgroundTintMode() {
+ return mBackgroundTintHelper != null
+ ? mBackgroundTintHelper.getSupportBackgroundTintMode() : null;
+ }
+
+ @Override
+ protected void drawableStateChanged() {
+ super.drawableStateChanged();
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.applySupportBackgroundTint();
+ }
+ }
+}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatImageHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatImageHelper.java
new file mode 100644
index 0000000..41bda8b
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatImageHelper.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v7.widget;
+
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.internal.widget.TintInfo;
+import android.support.v7.internal.widget.TintManager;
+import android.support.v7.internal.widget.TintTypedArray;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+class AppCompatImageHelper {
+
+ private static final int[] VIEW_ATTRS = {android.R.attr.src};
+
+ private final ImageView mView;
+ private final TintManager mTintManager;
+
+ AppCompatImageHelper(ImageView view, TintManager tintManager) {
+ mView = view;
+ mTintManager = tintManager;
+ }
+
+ void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
+ TintTypedArray a = TintTypedArray.obtainStyledAttributes(mView.getContext(), attrs,
+ VIEW_ATTRS, defStyleAttr, 0);
+ try {
+ if (a.hasValue(0)) {
+ mView.setImageDrawable(a.getDrawable(0));
+ }
+ } finally {
+ a.recycle();
+ }
+ }
+
+ void setImageResource(int resId) {
+ mView.setImageDrawable(mTintManager != null
+ ? mTintManager.getDrawable(resId)
+ : ContextCompat.getDrawable(mView.getContext(), resId));
+ }
+}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatImageView.java b/v7/appcompat/src/android/support/v7/widget/AppCompatImageView.java
new file mode 100644
index 0000000..c289028
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatImageView.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v7.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.support.v4.view.TintableBackgroundView;
+import android.support.v7.appcompat.R;
+import android.support.v7.internal.widget.TintManager;
+import android.support.v7.internal.widget.TintTypedArray;
+import android.util.AttributeSet;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+
+/**
+ * A {@link ImageView} which supports compatible features on older version of the platform,
+ * including:
+ * <ul>
+ * <li>Allows dynamic tint of it background via the background tint methods in
+ * {@link android.support.v4.view.ViewCompat}.</li>
+ * <li>Allows setting of the background tint using {@link R.attr#backgroundTint} and
+ * {@link R.attr#backgroundTintMode}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link android.widget.ImageView} in your
+ * layouts. You should only need to manually use this class when writing custom views.</p>
+ */
+public class AppCompatImageView extends ImageView implements TintableBackgroundView {
+
+ private AppCompatBackgroundHelper mBackgroundTintHelper;
+ private AppCompatImageHelper mImageHelper;
+
+ public AppCompatImageView(Context context) {
+ this(context, null);
+ }
+
+ public AppCompatImageView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AppCompatImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ final TintManager tintManager = TintManager.get(context);
+
+ mBackgroundTintHelper = new AppCompatBackgroundHelper(this, tintManager);
+ mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
+
+ mImageHelper = new AppCompatImageHelper(this, tintManager);
+ mImageHelper.loadFromAttributes(attrs, defStyleAttr);
+ }
+
+ @Override
+ public void setImageResource(@DrawableRes int resId) {
+ // Intercept this call and instead retrieve the Drawable via the image helper
+ mImageHelper.setImageResource(resId);
+ }
+
+ @Override
+ public void setBackgroundResource(@DrawableRes int resId) {
+ super.setBackgroundResource(resId);
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.onSetBackgroundResource(resId);
+ }
+ }
+
+ @Override
+ public void setBackgroundDrawable(Drawable background) {
+ super.setBackgroundDrawable(background);
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.onSetBackgroundDrawable(background);
+ }
+ }
+
+ /**
+ * This should be accessed via
+ * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
+ *
+ * @hide
+ */
+ @Override
+ public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.setSupportBackgroundTintList(tint);
+ }
+ }
+
+ /**
+ * This should be accessed via
+ * {@link android.support.v4.view.ViewCompat#getBackgroundTintList(android.view.View)}
+ *
+ * @hide
+ */
+ @Override
+ @Nullable
+ public ColorStateList getSupportBackgroundTintList() {
+ return mBackgroundTintHelper != null
+ ? mBackgroundTintHelper.getSupportBackgroundTintList() : null;
+ }
+
+ /**
+ * This should be accessed via
+ * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
+ *
+ * @hide
+ */
+ @Override
+ public void setSupportBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.setSupportBackgroundTintMode(tintMode);
+ }
+ }
+
+ /**
+ * This should be accessed via
+ * {@link android.support.v4.view.ViewCompat#getBackgroundTintMode(android.view.View)}
+ *
+ * @hide
+ */
+ @Override
+ @Nullable
+ public PorterDuff.Mode getSupportBackgroundTintMode() {
+ return mBackgroundTintHelper != null
+ ? mBackgroundTintHelper.getSupportBackgroundTintMode() : null;
+ }
+
+ @Override
+ protected void drawableStateChanged() {
+ super.drawableStateChanged();
+ if (mBackgroundTintHelper != null) {
+ mBackgroundTintHelper.applySupportBackgroundTint();
+ }
+ }
+}