可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a Button in my Activity, and I\'d like it to have my theme\'s accent color.
Instead of making my own drawables like we had to do pre-Lollipop, naturally I\'d like to use the new backgroundTint
attribute.
<Button
android:id=\"@+id/btnAddCode\"
android:layout_width=\"match_parent\"
android:layout_height=\"wrap_content\"
android:backgroundTint=\"@color/accent\"
android:text=\"@string/addressInfo_edit_addCode\" />
Unfortunately it has no effect, the button stays gray.
I tried different values for backgroundTintMode
, which didn\'t change anything.
I also tried doing it programmatically in my Activity, which didn\'t change anything.
addCodeView.findViewById(R.id.btnAddCode).setBackgroundTintList(
getResources().getColorStateList(R.color.accent));
Why is my tint ignored?
EDIT:
Just to clarify, I am indeed testing on a Lollipop device.
Other widgets (e.g. EditText) are correctly and automatically tinted.
回答1:
Tested on API 19 through API 27
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<android.support.v7.widget.AppCompatButton
xmlns:android=\"http://schemas.android.com/apk/res/android\"
xmlns:app=\"http://schemas.android.com/apk/res-auto\"
style=\"@style/Widget.AppCompat.Button.Colored\"
android:layout_width=\"wrap_content\"
android:layout_height=\"wrap_content\"
android:text=\"@string/retry\"
android:textColor=\"@android:color/white\"
app:backgroundTint=\"@android:color/holo_red_dark\" />
produces output as -
回答2:
The bad news
Like BoD says, it\'s meaningless to tint a Button\'s background in Lollipop 5.0 (API level 21).
The good news
Lollipop 5.1 (API level 22) seems to have fixed this by changing btn_mtrl_default_shape.xml (among other files): https://android.googlesource.com/platform/frameworks/base/+/6dfa60f33ca6018959ebff1efde82db7d2aed1e3%5E!/#F0
The great news
The new support library (version 22.1+) adds backward-compatible tinting support to lots of components, including AppCompatButton!
Unfortunately, the android:backgroundTint
property still doesn\'t work (maybe I\'m doing something wrong) -- so you have to set the ColorStateList
in code, using setSupportBackgroundTintList()
. It\'d be really nice to see android:backgroundTint
supported in the future. Update: Marcio Granzotto commented that app:backgroundTint
works on AppCompatButton! Note that it\'s app:
, not android:
, because it\'s in the app/library.
<LinearLayout
xmlns:android=\"http://schemas.android.com/apk/res/android\"
xmlns:app=\"http://schemas.android.com/apk/res-auto\"
android:layout_width=\"match_parent\"
android:layout_height=\"match_parent\" >
<AppCompatButton
android:id=\"@+id/mybutton\"
android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\"
android:text=\"Testing, testing\"
app:backgroundTint=\"#ff00ff\"/>
</LinearLayout>
Your activity will automatically inflate an AppCompatButton
instead of the normal Button
if you let it inherit from AppCompatActivity
.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppCompatButton v = (AppCompatButton) findViewById(R.id.mybutton);
ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});
v.setSupportBackgroundTintList(csl);
}
}
You should of course get the ColorStateList
from a color resource, but I was lazy, so...
Oh, and don\'t forget to base your app theme on one of the Theme.AppCompat
themes, or the compat views will be very, very sad... ;)
This worked on both 2.3.7 (Gingerbread MR1) and 5.0 (Lollipop \'Classic\').
回答3:
It seems that tinting a ripple drawable is meaningless (and the default background of a button is a ripple drawable).
In fact, after looking at the platform\'s default button drawable, I found the \"correct\" way to do this:. You have to define this in your theme:
<item name=\"android:colorButtonNormal\">@color/accent</item>
(Of course this is only for level 21+.)
Warning: since this is defined in a theme, this will use the given color for all the buttons (at least all of the buttons in activities using that theme.)
As a bonus, you can also change the ripple color by defining this:
<item name=\"android:colorControlHighlight\">@color/accent_ripple</item>
回答4:
To resolve issues related to tinting on Android 5.0.x I use something like this:
public static void setButtonTint(Button button, ColorStateList tint) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP && button instanceof AppCompatButton) {
((AppCompatButton) button).setSupportBackgroundTintList(tint);
} else {
ViewCompat.setBackgroundTintList(button, tint);
}
}
It uses the support method only for API 21 and the ViewCompat one for all other cases.
回答5:
Just use app:backgroundTint
instead of android:backgroundTint
, the tint will take effect below Lollipop. The reason is AppCompatActivity
use AppCompatViewInflater
to auto change Button or TextView to AppCompatButton or AppCompatTextView, then app:backgroundTint
take effect.
In my project I used it, it worked.
回答6:
I usually do it dynamically by using PorterDuff:
mbutton = (Button) findViewById(R.id.mybutton);
mbutton.getBackground().setColorFilter(anycolor, PorterDuff.Mode.MULTIPLY);
You can check different blending modes here and nice examples here.
回答7:
I think you need to have android:background
set to make android:backgroundTint
work.
To be more accurate, my guess is that you can\'t backgroundTint
the default button background from Material themes, which is defined as a RippleDrawable
.
回答8:
Similar issue was reported on google https://code.google.com/p/android/issues/detail?id=201873
But after release of Android Support Library, revision 23.2.1 (March 2016) This bug is solved.
Issue : FloatingActionButton.setBackgroundTintList(@Nullable ColorStateList tint) no longer changes background color
update Support Library to Android Support Library to 23.2.1
Use design support library(23.2.1) and appcompatwidgets as below
Material Design for Pre-Lollipop Devices :
AppCompat (aka ActionBarCompat) started out as a backport of the
Android 4.0 ActionBar API for devices running on Gingerbread,
providing a common API layer on top of the backported implementation
and the framework implementation. AppCompat v21 delivers an API and
feature-set that is up-to-date with Android 5.0
Android Support Library 22.1 :
The ability to tint widgets automatically when using AppCompat is
incredibly helpful in keeping strong branding and consistency
throughout your app. This is done automatically when inflating layouts
- replacing Button with AppCompatButton, TextView with AppCompatTextView, etc. to ensure that each could support tinting. In
this release, those tint aware widgets are now publicly available,
allowing you to keep tinting support even if you need to subclass one
of the supported widgets.
回答9:
If we look into the source code of Support Library, we see that it tints normally it\'s known buttons, but if we change the shape of our button (I have round button) tint doesn\'t work ok in api<=21.
We can also see that TintManager became public class (appcompat-v7:23.1.1), so we can take ColorStateList from default button shape (which is tinted ok in 5.0) for current theme (so we don\'t have to create the array of colors):
Context c = ...; // activity
AppCompatButton ab = ...; // your button
// works ok in 22+:
if (Build.VERSION.SDK_INT <= 21) {
// default appcompat button, that is tinted ok with current theme colors \"abc_btn_default_mtrl_shape\":
// ColorStateList tint = TintManager.get(c).getTintList(R.drawable.abc_btn_default_mtrl_shape);
// Appcompat 23.2 change:
ColorStateList tint = AppCompatDrawableManager.get().getTintList(c, R.drawable.abc_btn_default_mtrl_shape);
ab.setSupportBackgroundTintList(tint);
}
回答10:
Because attribute backgroundTint
is only used in API level 21 and higher
回答11:
Be aware recyclerview most updated lib can cause this bug as well.
This command
sendBtnView.setBackgroundTintList(colorState)
worked perfectly in the past but stop working for me. after research it turns out the cause is the lib that was addeded to gradle dependencies:
compile \'com.android.support:recyclerview-v7:+\'
So I tried to change it to 23.02.1 as it was recommended here in Amit Vaghela post.
I changed to
compile \'com.android.support:recyclerview-v7:23.02.1\'
But gradle error said recyclerview lib does not have this version (23.02.1) (gradle could not find it in Jcenter raw.github or repo).
Then, becaouse I knew setBackgroundTintList command used to worke well in the past with version 22.02.0\' in all the other libs I have in gradle dependencies.
so I change it to:
compile \'com.android.support:recyclerview-v7:22.02.0\'
And now it works again.
回答12:
I am not sure if this is recommended but you can try this:
Drawable newDrawable = mBtnAction.getBackground(); // obtain Bg drawable from the button as a new drawable
DrawableCompat.setTint(newDrawable, mActivity.getHomeTobBarBGColor()); //set it\'s tint
mBtnAction.setBackground(newDrawable); //apply back to button
In a general sense it works. Tried ViewCompat
but it doesn\'t seem to work properly.
回答13:
Just use app:backgroundTint instead of android:backgroundTint
回答14:
you can use backgroundTint
<android.support.design.button.MaterialButton
with \"com.android.support:design:28.0.0-rc01\"
version