I want to show the "x" button instead of the default back arrow as the "home" button on toolbar. I have searched how to use a custom image and it works and I have searched how to use a specific color for the back arrow and it works. The problem is, when I put both the custom image and the custom color, it shows the image with its default color, black, when I want it to be blue.
This is the xml for the toolbar:
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="#+id/toolbar"
android:theme="#style/ThemeToolbar">
And this is the ThemeToolbar style:
<style name="ThemeToolbarDetails" parent="Theme.AppCompat.Light">
<item name="colorControlNormal">#color/blue</item>
<item name="homeAsUpIndicator">#drawable/close</item>
</style>
I have tried colorControlNormal, android:textColorSecondary but none of this works when using a custom image.
First of all, keep this line on your style: <item name="homeAsUpIndicator">#drawable/close</item>.
Then, you have a couple of ways of solving the color part.
Option 1: If you're working with Vector Drawables, it's easier to just change the color inside the XML file.
Option 2: Alternatively, you can also programmatically tint any menu item. Get the Menu object in the onCreateOptionsMenu() method, and then try the snippet below:
private void tintIcon(#NonNull MenuItem item, int color) {
Drawable drawable = item.getIcon();
if (drawable != null) {
final Drawable wrapped = DrawableCompat.wrap(drawable);
drawable.mutate();
DrawableCompat.setTint(wrapped, color);
item.setIcon(drawable);
}
}
Option 3: Change the drawable and the color programatically.
final Drawable myIcon = ContextCompat.getDrawable(context, R.drawable.your_icon);
myIcon.setColorFilter(ContextCompat.getColor(context, R.color.your_color), PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setHomeAsUpIndicator(myIcon);
I am using appcompat v7 to get the look consistent on Android 5 and less. It works rather well. However I cannot figure out how to change the bottom line color and the accent color for EditTexts. Is it possible?
I have tried to define a custom android:editTextStyle (cf. below) but I only succeeded to change the full background color or text color but not the bottom line nor the accent color. Is there a specific property value to use? do I have to use a custom drawable image through the android:background property? is it not possible to specify a color in hexa?
<style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:editTextStyle">#style/Widget.App.EditText</item>
</style>
<style name="Widget.App.EditText" parent="Widget.AppCompat.EditText">
???
</style>
According to android API 21 sources, EditTexts with material design seem to use colorControlActivated and colorControlNormal. Therefore, I have tried to override these properties in the previous style definition but it has no effect. Probably appcompat does not use it. Unfortunately, I cannot find the sources for the last version of appcompat with material design.
Finally, I have found a solution. It simply consists of overriding the value for colorControlActivated, colorControlHighlight and colorControlNormal in your app theme definition and not your edittext style. Then, think to use this theme for whatever activity you desire. Below is an example:
<style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorControlNormal">#c5c5c5</item>
<item name="colorControlActivated">#color/accent</item>
<item name="colorControlHighlight">#color/accent</item>
</style>
I felt like this needed an answer in case somebody wanted to change just a single edittext. I do it like this:
editText.getBackground().mutate().setColorFilter(ContextCompat.getColor(context, R.color.your_color), PorterDuff.Mode.SRC_ATOP);
While Laurents solution is correct, it comes with some drawbacks as described in the comments since not only the bottom line of the EditText gets tinted but the Back Button of the Toolbar, CheckBoxes etc. as well.
Luckily v22.1 of appcompat-v7 introduced some new possibilities. Now it's possible to assign a specific theme only to one view. Straight from the Changelog:
Deprecated use of app:theme for styling Toolbar. You can now use android:theme for toolbars on all API level 7 and higher devices and android:theme support for all widgets on API level 11 and higher devices.
So instead of setting the desired color in a global theme, we create a new one and assign it only to the EditText.
Example:
<style name="MyEditTextTheme">
<!-- Used for the bottom line when not selected / focused -->
<item name="colorControlNormal">#9e9e9e</item>
<!-- colorControlActivated & colorControlHighlight use the colorAccent color by default -->
</style>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/MyEditTextTheme"/>
This can be changed in XML by using:
For Reference API >= 21 compatibility use:
android:backgroundTint="#color/blue"
For backward API < 21 compatibility use:
app:backgroundTint="#color/blue"
Here is the solution for API < 21 and above
Drawable drawable = yourEditText.getBackground(); // get current EditText drawable
drawable.setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP); // change the drawable color
if(Build.VERSION.SDK_INT > 16) {
yourEditText.setBackground(drawable); // set the new drawable to EditText
}else{
yourEditText.setBackgroundDrawable(drawable); // use setBackgroundDrawable because setBackground required API 16
}
Hope it help
The accepted answer is a bit more per style basis thing, but the most efficient thing to do is to add the colorAccent attribute in your AppTheme style like this:
<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorAccent">#color/colorAccent</item>
<item name="android:editTextStyle">#style/EditTextStyle</item>
</style>
<style name="EditTextStyle" parent="Widget.AppCompat.EditText"/>
The colorAccent attribute is used for widget tinting throughout the app and thus should be used for consistency
If you are using appcompat-v7:22.1.0+ you can use the DrawableCompat to tint your widgets
public static void tintWidget(View view, int color) {
Drawable wrappedDrawable = DrawableCompat.wrap(view.getBackground());
DrawableCompat.setTint(wrappedDrawable.mutate(), getResources().getColor(color));
view.setBackgroundDrawable(wrappedDrawable);
}
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="colorControlNormal">#color/colorAccent</item>
<item name="colorControlActivated">#color/colorAccent</item>
<item name="colorControlHighlight">#color/colorAccent</item>
</style>
Use:
<EditText
app:backgroundTint="#color/blue"/>
This will support pre-Lollipop devices not only +21
One quick solution for your problem is to look in yourappspackage/build/intermediates/exploded-aar/com.android.support/appcompat-v7/res/drawable/ for abc_edit_text_material.xml and copy that xml file in your drawable folder. Then you can change the colour of the 9 patch files from inside this selector, in order to match your preferences.
It's very easy just add android:backgroundTint attribute in your EditText.
android:backgroundTint="#color/blue"
android:backgroundTint="#ffffff"
android:backgroundTint="#color/red"
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#ffffff"/>
Here is a part of source code of TextInputLayout in support design library(UPDATED for version 23.2.0), which changes EditText's bottom line color in a simpler way:
private void updateEditTextBackground() {
ensureBackgroundDrawableStateWorkaround();
final Drawable editTextBackground = mEditText.getBackground();
if (editTextBackground == null) {
return;
}
if (mErrorShown && mErrorView != null) {
// Set a color filter of the error color
editTextBackground.setColorFilter(
AppCompatDrawableManager.getPorterDuffColorFilter(
mErrorView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN));
}
...
}
It seems that all of above code become useless right now in 23.2.0 if you want to change the color programatically.
And if you want to support all platforms, here is my method:
/**
* Set backgroundTint to {#link View} across all targeting platform level.
* #param view the {#link View} to tint.
* #param color color used to tint.
*/
public static void tintView(View view, int color) {
final Drawable d = view.getBackground();
final Drawable nd = d.getConstantState().newDrawable();
nd.setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter(
color, PorterDuff.Mode.SRC_IN));
view.setBackground(nd);
}
I too was stuck on this problem for too long.
I required a solution that worked for versions both above and below v21.
I finally discovered a very simple perhaps not ideal but effective solution: Simply set the background colour to transparent in the EditText properties.
<EditText
android:background="#android:color/transparent"/>
I hope this saves someone some time.
For me I modified both the AppTheme and a value colors.xml Both the colorControlNormal and the colorAccent helped me change the EditText border color. As well as the cursor, and the "|" when inside an EditText.
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorControlNormal">#color/yellow</item>
<item name="colorAccent">#color/yellow</item>
</style>
Here is the colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="yellow">#B7EC2A</color>
</resources>
I took out the android:textCursorDrawable attribute to #null that I placed inside the editText style. When I tried using this, the colors would not change.
You can set background of edittext to a rectangle with minus padding on left, right and top to achieve this. Here is the xml example:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="-1dp"
android:left="-1dp"
android:right="-1dp"
android:bottom="1dp"
>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#6A9A3A"/>
</shape>
</item>
</layer-list>
Replace the shape with a selector if you want to provide different width and color for focused edittext.
I worked out a working solution to this problem after 2 days of struggle, below solution is perfect for them who want to change few edit text only, change/toggle color through java code, and want to overcome the problems of different behavior on OS versions due to use setColorFilter() method.
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatDrawableManager;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import com.newco.cooltv.R;
public class RqubeErrorEditText extends AppCompatEditText {
private int errorUnderlineColor;
private boolean isErrorStateEnabled;
private boolean mHasReconstructedEditTextBackground;
public RqubeErrorEditText(Context context) {
super(context);
initColors();
}
public RqubeErrorEditText(Context context, AttributeSet attrs) {
super(context, attrs);
initColors();
}
public RqubeErrorEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initColors();
}
private void initColors() {
errorUnderlineColor = R.color.et_error_color_rule;
}
public void setErrorColor() {
ensureBackgroundDrawableStateWorkaround();
getBackground().setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter(
ContextCompat.getColor(getContext(), errorUnderlineColor), PorterDuff.Mode.SRC_IN));
}
private void ensureBackgroundDrawableStateWorkaround() {
final Drawable bg = getBackground();
if (bg == null) {
return;
}
if (!mHasReconstructedEditTextBackground) {
// This is gross. There is an issue in the platform which affects container Drawables
// where the first drawable retrieved from resources will propogate any changes
// (like color filter) to all instances from the cache. We'll try to workaround it...
final Drawable newBg = bg.getConstantState().newDrawable();
//if (bg instanceof DrawableContainer) {
// // If we have a Drawable container, we can try and set it's constant state via
// // reflection from the new Drawable
// mHasReconstructedEditTextBackground =
// DrawableUtils.setContainerConstantState(
// (DrawableContainer) bg, newBg.getConstantState());
//}
if (!mHasReconstructedEditTextBackground) {
// If we reach here then we just need to set a brand new instance of the Drawable
// as the background. This has the unfortunate side-effect of wiping out any
// user set padding, but I'd hope that use of custom padding on an EditText
// is limited.
setBackgroundDrawable(newBg);
mHasReconstructedEditTextBackground = true;
}
}
}
public boolean isErrorStateEnabled() {
return isErrorStateEnabled;
}
public void setErrorState(boolean isErrorStateEnabled) {
this.isErrorStateEnabled = isErrorStateEnabled;
if (isErrorStateEnabled) {
setErrorColor();
invalidate();
} else {
getBackground().mutate().clearColorFilter();
invalidate();
}
}
}
Uses in xml
<com.rqube.ui.widget.RqubeErrorEditText
android:id="#+id/f_signup_et_referral_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toEndOf="#+id/referral_iv"
android:layout_toRightOf="#+id/referral_iv"
android:ems="10"
android:hint="#string/lbl_referral_code"
android:imeOptions="actionNext"
android:inputType="textEmailAddress"
android:textSize="#dimen/text_size_sp_16"
android:theme="#style/EditTextStyle"/>
Add lines in style
<style name="EditTextStyle" parent="android:Widget.EditText">
<item name="android:textColor">#color/txt_color_change</item>
<item name="android:textColorHint">#color/et_default_color_text</item>
<item name="colorControlNormal">#color/et_default_color_rule</item>
<item name="colorControlActivated">#color/et_engagged_color_rule</item>
</style>
java code to toggle color
myRqubeEditText.setErrorState(true);
myRqubeEditText.setErrorState(false);
In Activit.XML add the code
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:ems="10"
android:id="#+id/editText"
android:hint="Informe o usuário"
android:backgroundTint="#android:color/transparent"/>
Where BackgroundTint=color for your desired colour
I use this method to change the color of the line with PorterDuff, with no other drawable.
public void changeBottomColorSearchView(int color) {
int searchPlateId = mSearchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
View searchPlate = mSearchView.findViewById(searchPlateId);
searchPlate.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
If you want change bottom line without using app colors, use these lines in your theme:
<item name="android:editTextStyle">#android:style/Widget.EditText</item>
<item name="editTextStyle">#android:style/Widget.EditText</item>
I don't know another solution.
I was absolutely baffled by this problem. I had tried everything in this thread, and in others, but no matter what I did I could not change the color of the underline to anything other than the default blue.
I finally figured out what was going on. I was (incorrectly) using android.widget.EditText when making a new instance (but the rest of my components were from the appcompat library). I should have used android.support.v7.widget.AppCompatEditText. I replaced new EditText(this) with new AppCompatEditText(this)
and the problem was instantly solved. It turns out, if you are actually using AppCompatEditText, it will just respect the accentColor from your theme (as mentioned in several comments above) and no additional configuration is necessary.
This is the easiest and most efficient/reusable/works on all APIs
Create a custom EditText class like so:
public class EditText extends android.widget.EditText {
public EditText(Context context) {
super(context);
init();
}
public EditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public EditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
getBackground().mutate().setColorFilter(ContextCompat.getColor(getContext(), R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
}
}
Then use it like this:
<company.com.app.EditText
android:layout_width="200dp"
android:layout_height="wrap_content"/>
To change the EditText background dynamically, you can use ColorStateList.
int[][] states = new int[][] {
new int[] { android.R.attr.state_enabled}, // enabled
new int[] {-android.R.attr.state_enabled}, // disabled
new int[] {-android.R.attr.state_checked}, // unchecked
new int[] { android.R.attr.state_pressed} // pressed
};
int[] colors = new int[] {
Color.BLACK,
Color.RED,
Color.GREEN,
Color.BLUE
};
ColorStateList colorStateList = new ColorStateList(states, colors);
Credits: This SO answer about ColorStateList is awesome.
You can use just backgroundTint for change bottom line color of edit text
android:backgroundTint="#000000"
example :
<EditText
android:id="#+id/title1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#000000" />
Add app:backgroundTint for below api level 21. Otherwise use android:backgroundTint.
For below api level 21.
<EditText
android:id="#+id/edt_name"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:textColor="#0012ff"
app:backgroundTint="#0012ff"/>
For higher than api level 21.
<EditText
android:id="#+id/edt_name"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:textColor="#0012ff"
android:backgroundTint="#0012ff"/>
Please modify this method according to your need. This worked for me!
private boolean validateMobilenumber() {
if (mobilenumber.getText().toString().trim().isEmpty() || mobilenumber.getText().toString().length() < 10) {
input_layout_mobilenumber.setErrorEnabled(true);
input_layout_mobilenumber.setError(getString(R.string.err_msg_mobilenumber));
// requestFocus(mobilenumber);
return false;
} else {
input_layout_mobilenumber.setError(null);
input_layout_mobilenumber.setErrorEnabled(false);
mobilenumber.setBackground(mobilenumber.getBackground().getConstantState().newDrawable());
}
}
I have this function that works fine on Android 4.4.1, but breaks on 5.0+.
public static SpannableStringBuilder prependImage(Drawable drawable, String text) {
SpannableStringBuilder builder = new SpannableStringBuilder(" " + text);
builder.setSpan(new ImageSpan(drawable), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return builder;
}
And I use it like this:
class MyButton extends Button {
// ... snip ...
setText(
prependImage(
getDrawable(imageResource, color),
getContext().getString(stringResource)),
BufferType.SPANNABLE);
Here is the getDrawable() method referenced above:
private Drawable getDrawable(int resource, int color) {
final Resources resources = getContext().getResources();
Drawable drawable = resources.getDrawable(resource);
if (drawable != null) {
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
}
return drawable;
}
When I debug, everything seems to succeed, but no image is drawn. Any ideas what I might be doing wrong?
By default, in Material buttons are styled to show text in all-caps. However, there is a bug in the AllCapsTransformationMethod used for capitalization that causes it to discard Spannable data.
You can override the default button styling and disable all-caps by specifying android:textAllCaps="false" on your Button.
<Button
...
android:textAllCaps="false" />
have a look here
Your code related to working with Spannables is ok. You can check it by setting text for TextView.
The problem is in material design of button on Android 5.0.
<style name="Widget.Material.Button">
<item name="background">#drawable/btn_default_material</item>
<item name="textAppearance">?attr/textAppearanceButton</item>
<item name="minHeight">48dip</item>
<item name="minWidth">88dip</item>
<item name="stateListAnimator">#anim/button_state_list_anim_material</item>
<item name="focusable">true</item>
<item name="clickable">true</item>
<item name="gravity">center_vertical|center_horizontal</item>
</style>
There are two solution.
The first one is just use TextView as your button and setText with image to it.
For another (and may be more correct) you need to extend button style (Widget.Material.Button) in next way:
<style name="BtnStyle" parent="android:Widget.Material.Button">
<item name="android:textAppearance">#null</item>
</style>
Then in your layout:
<Button
android:id="#+id/test2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Test"
style="#style/BtnStyle"/>
After you'll do it you should see the images in the button.
Don't forget for Android version that is lower than 5.0 you should create BtnStyle too, but in other resource directory (res/values-v14/style.xml).
One thing to note, drawable vectors won't work, you must either have a drawable which is a png or jpeg or pass to ImageSpan bitmap instead
Maybe you need to check the content of that Drawable object, you use the getDrawable() to get the Drawable object, but the API definition seems not match your calling parameters.
For Android 5.0+
Drawable getDrawable(int id) This method was deprecated in API level
22. Use getDrawable(int, Theme) instead.
Drawable getDrawable(int id, Resources.Theme theme) Return a drawable
object associated with a particular resource ID and styled for the
specified theme.
The second parameter looks like to be a Theme, not a color. right ?
try this
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getResources().getDrawable(R.drawable.your_drawable, getTheme());
} else {
getResources().
getDrawable(R.drawable.your_drawable);
}
I have implemented the new CollapsingToolbarLayout from Chris Banes example code.
However, the images for the backdrop image view have all a white background. The toolbar theme is ThemeOverlay.AppCompat.Dark.ActionBar so the icons are white too, thus I can't see the home button when the CollapsingToolbarLayout is fully expanded.
With app:expandedTitleTextAppearance i can set the color for the title field. Is there also a possibility to set the color of the home buttons and menu icons?
Here is the example how I change my drawer and options icons color when layout is expanded and collapsed:
protected void onCreate(Bundle savedInstanceState) {
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int offset)
{
Drawable upArrow = ResourcesCompat.getDrawable(getResources(), R.drawable.drawer_icon, null);
if (offset < -200)
{
upArrow.setColorFilter(Color.parseColor("#000000"), PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setHomeAsUpIndicator(upArrow);
Drawable drawable = ContextCompat.getDrawable(getApplicationContext(),R.drawable.option_menu_icon);
drawable.setColorFilter(Color.parseColor("#000000"), PorterDuff.Mode.SRC_ATOP);
toolbar.setOverflowIcon(drawable);
}
else
{
upArrow.setColorFilter(Color.parseColor("#ffffff"), PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setHomeAsUpIndicator(upArrow);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Drawable drawable = ContextCompat.getDrawable(getApplicationContext(),R.drawable.option_menu_icon);
drawable.setColorFilter(Color.parseColor("#ffffff"), PorterDuff.Mode.SRC_ATOP);
toolbar.setOverflowIcon(drawable);
}
}
});
It is better to use 2 different images in Toolbar. Others may cause some unwanted problems:
Trying to set 2 different Toolbar themes will never work because themes are set only on Activity creation, setting another theme has no effect, you need to re-create the Activity.
Using color filter may not result what exactly you want. You may use shadowed arrow and color filter will also paint that shadow which becomes more like outer glow.
So your Toolbar will look like this:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:contentInsetStart="0dp"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways|snap">
<ImageView
android:id="#+id/imageViewBack"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:scaleType="center"
android:src="#drawable/button_back_white" />
</android.support.v7.widget.Toolbar>
And you will set imageViewBack drawable as your Toolbar collapses:
appBarLayout.addOnOffsetChangedListener((appBarLayout, offset) -> {
final boolean isCollapsed = (offset == (-1 * appBarLayout.getTotalScrollRange()));
imageViewBack.setImageDrawable(ContextCompat.getDrawable(context,
isCollapsed ?
R.drawable.button_back_red :
R.drawable.button_back_white));
});
You can get a nice color transition while scrolling with the following approach using a ColorFilter. Hope you like Kotlin
app_bar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout: AppBarLayout, offset: Int ->
val colorComponent = Math.max(0.3f,offset.toFloat() / -appBarLayout.totalScrollRange)
toolbar.navigationIcon?.colorFilter =
PorterDuffColorFilter(Color.rgb(colorComponent, colorComponent, colorComponent), PorterDuff.Mode.SRC_ATOP)
})
This will give you a dark navigation icon when the CollapsingToolbarLayout is expanded and a white icon in collapsed state.
In my eyes this is only possible if you change the drawables of the home button, the menu icons and the overflow button. Fortunately Google has give us a new API called Tinted Drawables which allows us to set the collor of a drawable or nine-patch image. Here is how it works:
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#android:drawable/ic_menu_camera"
android:tint="#color/menu_icon_color"/>
Now you can use this new defined Drawable like any other in your layout. For the home button and the overflow button you also have to override the style definitions like so:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:homeAsUpIndicator">#drawable/tinted_home_button</item>
<item name="android:actionOverflowButtonStyle">#style/OverFlowButton</item>
</style>
<style name="OverFlowButton" parent="AppTheme">
<item name="android:src">#drawable/tinted_overflow_button</item>
</style>
All these stuff (except the style definitions) is unfortunately only available on API level 21+ and is not included into the support library. If you have to support devices lower then Lollipop I think the best way is to use the Android Assets Studio where you can tint the icons by yourself and download them as a png file.
The home button, overflow button, and some select stock icons from the sdk are affected by colorControlNormal:
<style name="ActionBar" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="colorControlNormal">#color/accent</item>
</style>
If you have other icons, you would need to loop through and manually filter them:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sample_actions, menu);
for(int i = 0; i < menu.size(); i++){
Drawable drawable = menu.getItem(i).getIcon();
if(drawable != null) {
drawable.mutate();
drawable.setColorFilter(getResources().getColor(R.color.accent), PorterDuff.Mode.SRC_ATOP);
}
}
return true;
}
Having the android.support.v7.widget.Toolbar and it's background color is changing based on different cases.
The OverflowButton button (the three vertical dots at right of the toolbar) is always having the same background when press on it.
Saw some posts about how to change statically, like quoted below. But really want is to do it dynamically based the toolbar's background color.
Any idea?
To change statically:
You can change the image used for it using the following style declaration.
<style name="MyCustomTheme" parent="style/Theme.Holo">
<item name="android:actionOverflowButtonStyle">#style/MyCustomTheme.OverFlow</item>
</style>
<style name="MyCustomTheme.OverFlow">
<item name="android:src">#drawable/my_overflow_image</item>
</style>
And if you're using ActionBarSherlock, here's how to do it
<style name="MyCustomTheme" parent="style/Theme.Sherlock">
<item name="android:actionOverflowButtonStyle">#style/MyCustomTheme.OverFlow</item>
<item name="actionOverflowButtonStyle">#style/MyCustomTheme.OverFlow</item>
</style>
<style name="MyCustomTheme.OverFlow">
<item name="android:src">#drawable/my_overflow_image</item>
</style>
Edit-- The answer should be:
It could be achieved by just to set partial transparent background in the style of actionOverflowButtonStyle so that whatever the toolbar's color will be blended in.
one solution might be just disable the press state by making it transparent for all toolbars, but it is no desirable.
Another one found, but feel like a hack.
Not sure if anyone have better way to get access to the overflow button so it's background could be set dynamically with proper drawable.
from this bug report,
it could be done as the following setupOverflowMenuButton().
public boolean setupOverflowMenuButton (Menu menu, Toolbar toolbar) {
Toolbar t = toolbar;
for(int i = 0; i < t.getChildCount(); i++) {
if(t.getChildAt(i) instanceof ActionMenuView) {
ActionMenuView v = (ActionMenuView)t.getChildAt(i);
for(int j = 0; j < v.getChildCount(); j++) {
if(v.getChildAt(j) instanceof TintImageView) {
TintImageView v1 = (TintImageView)v.getChildAt(j);
v1.setBackgroundResource(R.drawable.overflow_bt_bg_selector);
}
}
}
}
return super.onPrepareOptionsMenu(menu);
}