I use tint for icons for whole my app.
Example in my ImageView:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="#drawable/ic_account_circle"
android:tint="#color/red_color"/>
I also use some of the icons in EditText as its drawable:
<EditText
android:id="#+id/passwordInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="#drawable/ic_lock"
android:drawablePadding="#dimen/medium_margin_padding"
android:hint="#string/password_text"
android:inputType="textPassword" />
However, I can't find any code that can be used to tint the drawable in EditText. Is it not possible to tint the drawable?
Note:
I use appcompat and design support library, but still can't find any code.
Use the wrap, setTint, setTintMode methods from the DrawableCompat class to set tint for drawable programmatically
Drawable drawable = getyourdrawablehere;
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable, Color.GREEN);
DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_OVER);
And after set the drawable for the editText:
editText.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
Create a drawable with a bitmap tag like this
drawable_with_tint.xml
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/ic_lock"
android:tint="#fff">
</bitmap>
Then you may use the drawable in your edittext
<EditText
android:id="#+id/passwordInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="#drawable/ic_drawable_with_tint"
android:drawablePadding="#dimen/medium_margin_padding"
android:hint="#string/password_text"
android:inputType="textPassword" />
Unfortunately the solution posted by mbelsky needed some very small changes. In order to tint your drawable in your EditText you need to use wrap setTint and setTintMode. The full solution for all API's:
Drawable drawable = getResources().getDrawable(drawableID/mipmapID);
emailDrawable = DrawableCompat.wrap(emailDrawable);
DrawableCompat.setTint(emailDrawable,getResources().getColor(R.color.purple));
DrawableCompat.setTintMode(emailDrawable, PorterDuff.Mode.SRC_IN);
editText.setCompoundDrawablesWithIntrinsicBounds(drawable,null,null,null);
You can use
android:drawableTint="#color/yourcolor"
Note that it only works on Api 23 or higher
In my case the accepted answer is not working on 5.0 devices, tinting through DrawableCompat the background seems to work on Button and others resources but not on EditText.
I discover this sentence on Android docs for androidx.appcompat.widget.AppCompatEditText afters hours struggling with this subject:
A EditText which supports compatible features on older versions of the platform, including:
Allows dynamic tint of its background via the background tint methods in ViewCompat.
So tinting programatically method working for me on API 21, and also for the rest, would be:
ViewCompat.setBackgroundTintList(myEditText, ColorStateList.valueOf(getResources().getColor(R.color.my_color)));
See reference: AppCompatEditText
Related
I want to applying drawable to my android button.
But, background drawable is not working.
This is my drawable code.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#FFEF1D1D" />
</shape>
</item>
</layer-list>
and This is my layout code
<Button
android:id="#+id/booking"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="6.5"
android:text="bokking"
android:textStyle="bold"
android:textColor="#color/white"
android:background="#drawable/booking_btn"
android:layout_marginRight="10dp"/>
Drawable is not applied to Button, but drawable is applied to AppCompatButton. I wonder why too.
When I applied this code, Only backgroundTint applies to buttons.
I spent a week on this issue, but I couldn't solve it.
plz help me
You can't apply the background on the material button.
If you are using Theme.MaterialComponents.*, then the normal button also used as the material button forcefully.
You have two options.
change it to any AppCompat theme.
Still If you need a material theme for some components, then use any material theme with a bridge. like Theme.MaterialComponents.*.Bridge
So, If you will go with option 2, you can use material button as per your need.
use com.google.android.material.button.MaterialButton for material button else use your normal button.
Looks like there is a problem with the Theme since Android Studio 4.1, try changing the base Theme from Theme.MaterialComponents.DayNight.DarkActionBar to Theme.AppCompat.DayNight.DarkActionBar, it works for me.
There is only one chance for that.I think you are using material theme.That's why the background property is not applying for button.If you want use that,change the theme to appcompat varaint.
You didn't use the selector in your XML. Use Selector instead of Layer-List
I have this button:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:theme="#style/AppTheme.Button.Toolbar"/>
And this style:
<style name="AppTheme.Button.Toolbar" parent="Widget.AppCompat.Button.Borderless">
<item name="colorButtonNormal">#color/main</item>
<item name="android:textColor">#color/secondary</item>
</style>
Even though the style inherits from Widget.AppCompat.Button.Borderless, the button still has a border.
Changing Button to android.support.v7.widget.AppCompatButton did not help.
How to remove the border then?
Edit:
Setting background of the button is not an option - by doing so the animation of ripple effect is lost.
Edit 2:
Things become even more interesting.
Tried to change android:theme to style as #cadet suggested.
When button is defined this way:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:theme="#style/ToolbarButton"/>
That's what I get:
The colors apply, but there is distinct border.
If I just change theme to style:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
style="#style/ToolbarButton"/>
I get this:
There is no border, and the style is applied only partially (text is colored, button is not)
Edit 3:
Friends, I'm looking for a way to get borderless, styled button with ripple effects using styling approach. Hacking each and every button separately in layout files might work, but that's not the point.
Try this, hope out of this one may help you
<Button
android:id="#+id/btn_photo_lib"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startPhotoLibAction"
android:src="#drawable/library_blau_2"
style="?android:attr/borderlessButtonStyle"/>
or
android:background="#null"
set background #null. or set own created background
android:background="#null"
You can use a different View instead of Button
<LinearLayout
android:id="#+id/btn_action_alternative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:clickable="true" />
I found a better solution, you'll wanna create a custom drawable and depending on the min version your app supports, you'll need to create two, one for Android versions pre-21(Lollipop) and another for post 21(Lollipop). The two files will need to be named identically so Android can find them and match them appropriatly based on the API level. But in the file drawable file for API 21 and above your file should look like such:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:drawable="#drawable/button_normal"/>
</ripple>
This Drawable file is wrapping another Drawable that is your preferred background image or color with a ripple whose color is defined using "?android:colorControlHighlight", which is simple a reference to a default color from what ever theme the current activity is using.
If you need to support pre-21(Lollipop), your drawable file would simply be a selector, with the preferred drawable. Your preferred drawable should be the same background color, or even a transparent color to make sure you can see your parent layouts background color. Similar to this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/button_normal"/>
</selector>
You can combine this with a style in order to apply the borderless style to all buttons it to all buttons in a layout... I recommend you use a transparent drawable so you can use this style with all buttons regardless if their parent has a different color background. This will prevent you from making several themes with different backgrounds.
To handle versioning support, or even config support if you'd like custom drawables based on various device configurations, you would just create several drawable folders with a configuration specific suffix. So, for example, drawables only for version 21 and above you'd create a folder called 'drawable-21'.
I found a website that better explains what I'm talking about.
This question already has answers here:
Change fill color on vector asset in Android Studio
(18 answers)
Closed 6 months ago.
I'm trying to apply tint for ImageButton that uses vector drawable:
<android.support.v7.widget.AppCompatImageButton
android:id="#+id/flashlight_button"
app:srcCompat="#drawable/ic_flash_off_black_24dp"
android:tint="#color/icon_states_color"
/>
This will work Lollipop +, but will crash on Kitkat.
How should do ColorList tint for Kitkat in app compat world?
hi you can programmatically add tint in your image button and make check if it below lollipop then it work below aternate way.
According to the documentation the related method to android:backgroundTint is setBackgroundTintList(ColorStateList list)
Update
Follow this link to know how create a Color State List Resource.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:color="#your_color_here" />
</selector>
then load it using
setBackgroundTintList(contextInstance.getResources().getColorStateList(R.color.your_xml_name));
where contextInstance is an instance of a Context
using AppCompart
btnTag.setSupportButtonTintList(ContextCompat.getColorStateList(Activity.this, R.color.colorPrimary));
Try this way, hope this will help you.
android:tint within vector drawable with work. So just android:tint in layout should be avoided.
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.
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').
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>
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.
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.
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.
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 -
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.
Just use app:backgroundTint instead of android:backgroundTint
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.
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);
}
Because attribute backgroundTint is only used in API level 21 and higher
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.
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.
you can use backgroundTint <android.support.design.button.MaterialButton with "com.android.support:design:28.0.0-rc01" version
If you are using androidx then adding both prefixed and not prefixed version resolved issue on android 5.1:
<style name="Button_Primary">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:backgroundTint">#color/button_primary_selector</item>
<item name="backgroundTint">#color/button_primary_selector</item><!--needed for android 5-->
</style>
button_primary selector is in color folder with following content:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto">
<item android:state_enabled="true" android:color="#android:color/holo_blue_dark" />
<item android:state_enabled="false" android:color="#android:color/darker_gray" />
</selector>
and apply it on regular button on AppCompatActivity
<Button style="#style/Button_Primary"/>
If you are developing an app that your target sdk is higher than api 21 and your minSdkVersion is 21(Lollipop) instead of
android:backgroundTint="#color/accent"
you can simply say..
android:background="#color/accent"
I've learned how to tint an image when it's pressed by adding an OnTouchListener in which I call setColorFilter on the image.
I've learned how to use nine-patch images as the background for Buttons and ImageButtons.
The problem is, nine-path images don't stretch if they're the src for an ImageButton, and the tint has no effect on the background image.
How can I tint a nine-patch ImageButton when it's pressed? Any suggestions?
I know it's an old question but it seems that it's the only one on this topic.
You can tint nine patch images by creating an xml resource file containing a nine patch node and a tint node. Example :
<?xml version="1.0" encoding="utf-8"?>
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/nine_patch_image"
android:tint="#android:color/black"/>
You may then reference this file in your background attributes :
<LinearLayout
android:id="#+id/some_id"
android:background="#drawable/xml_filename">
Hope this will help someone
So I'm 3 years late but I found a way to do this.
(I'm using Xamarin so excuse any C# formatting I miss)
#Override
protected void onDraw(Canvas canvas)
{
NinePatchDrawable bg = (NinePatchDrawable)getResources().getDrawable(R.Drawable.whatev);
bg.setBounds(0, 0, getWidth(), getHeight());
bg.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
bg.draw(canvas);
base.onDraw(canvas);
}
Another option, is using backgroundTint (available on API21 and above):
<TextView
android:id="#+id/chat_bubble_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/left_bubble"
android:backgroundTint="#color/main_color"
android:gravity="center_vertical"
android:minWidth="200dp"
android:textColor="#android:color/white"
android:visibility="visible"
tools:text="message" />
I found one way you can kinda sorta of do this. Using a purely gray-scale, semi-transparent 9-patch image as your button background, wrap the button in a view group which has your tint color as its background like this:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#F00"
android:orientation="vertical" >
<Button
android:id="#+id/my_butt"
android:background="#drawable/my_semi_transparent_gray_9_patch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I'm a tinted 9-patch button!" />
</LinearLayout>
The main problem is that if your image has transparent edges, the tint color will show through where you don't want it, but if your image edges used a fully opaque color that matched the background of whatever container you put this thing in, it might work well enough. You also might need to write your own selector that changes those background colors for each state you care about. I'm not recommending this approach but maybe it will help someone. I agree that it's a shame that tinting isn't built into the 9-patch design because it feels stupid to maintain a bunch of identical images that differ only in tint, especially when you multiply that by a number of different drawable sizes. Even better would be for Android to natively support SVG. I've modified the open-source "svg-android" library so that with the right art I only need a single image that can be stretched and tinted as needed.
I think you'd have better results by making a separate asset for each button state. For instance, you can make a drawable xml file like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/btn_pressed"
android:state_pressed="true" />
<item android:drawable="#drawable/btn_focused"
android:state_pressed="false"
android:state_focused="true" />
<item android:drawable="#drawable/btn_default"
android:state_focused="false"
android:state_pressed="false" />
</selector>
Then create a style for your buttons like this:
<style name="PushButton">
<item name="android:background">#drawable/btn</item>
</style>
Then you should be able to style your image buttons and set the src to whatever image you want.
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/icon"
style="#style/PushButton" />