In styles.xml I'm styling the popup theme of the overflow menu in the toolbar:
<style name="ToolbarOverflowMenuStyle" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:backgroundTint">#color/white</item>
</style>
That works as intended but if I do a multi selection in a recycler view (list) the popup theme background color turns from white to yellow (the color of the toolbar). I have no idea why that is since it has the right color if the multi-selection isn't active.
Any ideas what I am doing wrong?
Styling of the toolbar:
<style name="PostToolbarStyle" parent="android:Theme.Material">
<item name="android:backgroundTint">#color/yellow</item>
<item name="android:textColorHint">#color/lightGray2</item>
<item name="android:textColorPrimary">#color/defaultTextColor</item>
<item name="android:textColorSecondary">#color/defaultTextColor</item>
</style>
And this is how I set the toolbar in the layout xml file:
<android.support.v7.widget.Toolbar
android:id="#+id/app_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
android:paddingTop="#dimen/tool_bar_top_padding"
app:popupTheme="#style/ToolbarOverflowMenuStyle"
app:theme="#style/ThemeOverlay.AppCompat.ActionBar"/>
How the popup theme looks like (correctly) when multi-selection is not active:
And here how is being displayed (wrongly) when multi-select is active:
Its Menu -ActionMode you see your default OptionsMenu popUp background is the white, and the default contextual Menu for your app is the Yellow in your case. When you enter into multi-selection a ActionMode is triggered to handle the itemClick and what have you, and since you know how CAB works.
if you want to maintain the same white background in your setMultiChoiceModeListener override onPrepareActionMode(ActionMode mode, Menu menu) and use getCustomView().setBackgroundColor(Color.White);
Edit: addressing comment
This is what i mean in your onPrePareActionMode()
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
//the mode parameter is your CAB, so call that on it
mode.getCustomView().setBackgroundColor(Color.White);
}
Hope its helpful
Can you Try editing you style with this property, selectableItemBackground
<style name="ToolbarOverflowMenuStyle" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:backgroundTint">#color/white</item>
<item name="selectableItemBackground">?android:selectableItemBackground</item></style>
Had a similar problem with SwitchCompat and the solution was in one of the properties itself. Also this blog helped a lot . http://blog.mohitkanwal.com/blog/2015/03/07/styling-material-toolbar-in-android/
Related
I have created a menu and now I want to change the text color of the individual menu titles.
To do this, I first created a style that should contain the corresponding attribute and then called this style in my Activity_home_drawer.xml. However, this only changes the menu TextColor when the corresponding menu title is clicked but is not permanent as I would like it to be.
What do I have to do so that the text color in my menu changes permanently to white and not Black anymore? Is my way of doing it the right way or is there a more elegant way to change the TextColor?
Thanks for any help!
Part of my Activity_home_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view"
android:theme="#style/TextAppearance44">
<group android:id="#+id/category_group">
<item
android:id="#+id/nav_menu"
android:icon="#drawable/ic_store_black_24dp"
android:title="#string/menu_menu"
android:theme="#style/TextAppearance44"
/>
</group>
My TextAppearance44 style
<style name="TextAppearance44">
<item name="android:textColor">#color/colorWhite</item>
<item name="android:actionMenuTextColor">#color/colorWhite</item>
<item name="android:textSize">16sp</item>
<item name="android:titleTextColor">#color/colorWhite</item>
</style>
You need to change your ToolBar style. Check these two tutorials:
Toolbar assigning to activity and styling:
https://android-developers.googleblog.com/2014/10/appcompat-v21-material-design-for-pre.html?m=1
Changing style and items colors in the Toolbar:
https://www.murrayc.com/permalink/2014/10/28/android-changing-the-toolbars-text-color-and-overflow-icon-color/
In your case, you are looking mainly for (code fragment from second tutorial):
<!-- android:actionMenuTextColor is the color of the text of
action (menu) items in the Toolbar, at least in the
Theme.AppCompat theme.
For some reason, they already get the textColorPrimary
when running on API 21, but not on older versions of
Android, so this is only necessary to support older
Android versions.-->
<item name="actionMenuTextColor">#color/abc_primary_text_material_light</item>
I solved it by myself; I added these to lines to my NavigationView in my ActivityHome (where the Menu comes up).
app:itemTextColor="#color/colorWhite"
app:itemIconTint="#color/colorWhite"
Simple mistake, didnot know that there was such a attribute.
Background
I'm trying to theme my app to have more material design look, and as such, I have a toolbar that's being set as the actionBar of the activity.
I have a SearchView in it that allows to search items of the listView below.
The problem
Thing is, you can select the text in the SearchView (to copy, cut, etc...), yet when this happens, the toolbar gets the text-selection toolbar on top of it, making it and the text itself hidden:
Before text selection:
After text selection:
What I've tried
I tried to disable text selection using this code:
final EditText searchTextView=(EditText)searchView.findViewById(R.id.search_src_text);
if(searchTextView!=null&&VERSION.SDK_INT>=VERSION_CODES.HONEYCOMB)
searchTextView.setTextIsSelectable(false);
But it didn't do anything. I've also tried to search for how to listen for the even of text selection (so that I could set the toolbar a marginTop or something), but I didn't find it.
The only thing that I have succeeded is using this code, which tells me when the text-selection toolbar appears (but not when it disappears) :
searchTextView.setOnCreateContextMenuListener(new OnCreateContextMenuListener()
{
#Override
public void onCreateContextMenu(final ContextMenu menu,final View v,final ContextMenuInfo menuInfo)
{
Log.d("AppLog","onCreateContextMenu");
}
});
This doesn't help. I can't even close the menu. I think it can't even help, as some devices might show something else instead of a toolbar (like on LG devices, where they have a small popup).
The code
The layout is basically a vertical LinearLayout, where the first item is the toolbar:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/activity_app_list__toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:colorControlNormal="?attr/colorControlNormal"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
tools:ignore="UnusedAttribute"/>
...
The theme that's used is set to hide the normal action bar:
<style name="AppTheme" parent="#style/Theme.AppCompat.Light.DarkActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
...
The action bar menu's XML is quite basic and has 3 action items, where the first one of them is the searchView:
<item
android:id="#+id/menuItem_search"
android:icon="?attr/app_search_menu_icon"
android:title="#string/search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always|collapseActionView"/>
Handling the SearchView is done via a special class I've made that supports even old Android versions. This is the main function that handles the searchView :
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void init(final MenuItem searchMenuItem,final int hintResId,final OnQueryTextListener onQueryTextListener,final OnActionExpandListener onActionExpandListener)
{
this._searchMenuItem=searchMenuItem;
if(_searchView==null)
{
_searchView=(SearchView)MenuItemCompat.getActionView(searchMenuItem);
if(_searchView==null)
{
MenuItemCompat.setShowAsAction(searchMenuItem,MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW|MenuItem.SHOW_AS_ACTION_ALWAYS);
MenuItemCompat.setActionView(searchMenuItem,_searchView=new SearchView(_context));
}
_searchView.setQueryHint(_context.getString(hintResId));
if(VERSION.SDK_INT<VERSION_CODES.HONEYCOMB)
{
final EditText searchTextView=(EditText)_searchView.findViewById(R.id.search_src_text);
if(searchTextView!=null)
{
searchTextView.setScroller(new Scroller(_context));
searchTextView.setMaxLines(1);
searchTextView.setVerticalScrollBarEnabled(true);
searchTextView.setMovementMethod(new ScrollingMovementMethod());
final int searchTextColorResId=App.getResIdFromAttribute(_context,android.R.attr.textColorPrimary);
if(searchTextColorResId!=0)
searchTextView.setTextColor(_context.getResources().getColor(searchTextColorResId));
else
{
// TODO workaround for some v2.3 devices that can't get the correct color. remove this when stopping the support for v2.3
TextView searchBadge=(TextView)_searchView.findViewById(R.id.search_badge);
if(searchBadge!=null)
searchTextView.setTextColor(searchBadge.getTextColors());
}
}
}
_searchView.setOnQueryTextListener(onQueryTextListener);
MenuItemCompat.setOnActionExpandListener(searchMenuItem,onActionExpandListener);
}
}
The function is called at the end of "onCreateOptionsMenu" of any activity/fragment that is supposed to have a searchView, for example:
_searchHolder.init(menu.findItem(R.id.menuItem_search),R.string.search_for_apps,onQueryTextListener,onActionExpandListener);
The question
How can I solve this issue? Obviously this has happened because the Toolbar is just a view, so the text-selection bar is shown on top of it, but is there any way to fix this?
How do I avoid the extra toolbar become on top of the one I've used?
Is there a way to support all devices in this regard?
Looking at Google's apps, it seems that they usually don't use the official searchView, but one of their own. Only on Youtube it seems like the official one, but there it seems as if they also use the official actionBar (plus it has weird colors when selecting the text).
I found in many apps(Google messenger, Contacts etc) text selection is disabled in search view. You can do that by setting your toolbar theme as.
<style name="toolbarTheme" parent="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="android:autoCompleteTextViewStyle">#style/SearchViewStyle</item>
<item name="android:textColor">#android:color/white</item>
<item name="android:textColorPrimary">#android:color/white</item>
<item name="android:editTextColor">#android:color/white</item>
</style>
<style name="SearchViewStyle" parent="#android:style/Widget.Holo.Light.AutoCompleteTextView">
<item name="android:longClickable">false</item>
</style>
Or if you want it like youtube add this line in your theme
<item name="windowActionModeOverlay">false</item>
Thanks of the Max's answer, I've tried looking the AppCompat style files by clicking on references one after another, I've found Widget.AppCompat.AutoCompleteTextView. Override it in your Toolbar theme with:
<item name="android:autoCompleteTextViewStyle">#style/AppTheme.SearchViewStyle</item>
<style name="AppTheme.SearchViewStyle" parent="Widget.AppCompat.AutoCompleteTextView">
<item name="android:longClickable">false</item>
</style>
It disables the longClick in SearchView. This works on devices from API 14 (didn't try previous versions) to API 22.1.1 at least.
I'm having real difficulty doing anything to the overflow menu in actionbar sherlock.
Ideally, I would like to use a custom TextView for each item in order to set a different font on it and change the colour of the pressed state.
I have tried (all without success):
Changing The Style Of Actionbar Overflow
Actionbar styled overflow menu items
listview as action overflow in sherlock actionbar
https://groups.google.com/forum/#!msg/actionbarsherlock/5lHOKNlXn_4/f9XicMXbFFAJ
My app will have different fragments, all extending BaseFragment with different items in the overflow menu. I'm also using the v4 support package. I'm creating my menu like this:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.activity_borrow, menu);
}
activity_borrow.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu_filter"
android:title="test"
android:orderInCategory="100"
android:showAsAction="never"
/>
</menu>
My app uses a theme that inherits from Theme.Sherlock.
How can I used a custom view inside that menu? Or at the very least, how can I change the default blue pressed state?
To change the colors of the overflow list items, add two items to your application theme which is usually defined in res/values/styles.xml:
<item name="android:dropDownListViewStyle">#style/DropDownListView</item>
<item name="dropDownListViewStyle">#style/DropDownListView</item>
In that same file, add the style that you have just assigned:
<style name="DropDownListView" parent="#style/Widget.Sherlock.ListView.DropDown">
<item name="android:listSelector">#drawable/selectable_background</item>
</style>
And finally create a selector drawable selectable_background.xml in the drawable folder, containing this:
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="#android:integer/config_mediumAnimTime" >
<item android:state_pressed="false" android:state_focused="true" android:drawable="#color/focussed_color" />
<item android:state_pressed="true" android:drawable="#color/pressed_color" />
<item android:drawable="#android:color/transparent" />
</selector>
Finally, define the colors which are usually placed in colors.xml:
<resources>
<color name="pressed_color">#FF8E4067</color> <!-- your purple tone already ;) -->
<color name="focussed_color">#DD8E4067</color>
</resources>
In my app, I used the "ActionBar Style Generator" as baboo suggested, which handles everything for you conveniently. For this answer, I just extracted and simplified the parts that I think make up the overflow menu styling.
I think there is some mystery about the effects of styling three different items:
From my understanding, android:dropDownListViewStyle includes the
overflow menu that hides behind the "three dots" in the ActionBar.
Not to be confused with android:actionDropDownStyle, which is used to the style the app navigation dropdown in case you used actionBar.setNavigationMode(NAVIGATION_MODE_LIST)
However, some Android devices with a hardware menu button (e.g. the Nexus S or Galaxy S3 Mini)
don't display the "three dots" but an overlay menu that slides in from
the bottom of the screen if the hardware menu button is clicked. android:popupMenuStyle is the correct attribute to style this.
Again, this is only as far as I can remember from my own app development.
Also, make sure to check that no other style files (e.g. folders with configuration qualifiers) overwrite the styles that you have just defined.
All in all, I understand that this would only change the background color of the list items. To use a completely custom view in there, you might create a custom spinner view, add a dummy button with a "three dots" icon to your ActionBar and open the spinner on click.
I'm looking for style information on the Contextual Action bar (CAB). I just need to change the colour of the text in fact..
As you can see from the above, this is using the standard Theme.Holo.Light.DarkActionBar theme, so I just need to set the text colour to white!
Can anyone point me in the right direction?
To change the color/etc of the text in a contextual action bar:
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
//mode.setTitle("Contextual Action Bar"); (replace this call)
TextView tv= (TextView)getLayoutInflater().inflate(R.layout.contextual_title, null);
tv.setText("Contextual Action Bar");
mode.setCustomView(tv);
where layout/contextual_title.xml contains a single TextView with your desired color/size/style etc
In fact, almost everything in a contextual action bar can be styled. The only problem is that searching for the word 'contextual' leads nowhere useful. The relevant styling features are all called "actionMode...". Here are some I used (defined in my Theme.)
<item name="android:actionModeCloseDrawable">#drawable/check</item>
<item name="android:actionModeCutDrawable">#drawable/ic_menu_cut_holo_dark</item>
<item name="android:actionModeCopyDrawable">#drawable/ic_menu_copy_holo_dark</item>
<item name="android:actionModePasteDrawable">#drawable/ic_menu_paste_holo_dark</item>
<item name="android:actionModeSelectAllDrawable">#drawable/ic_menu_selectall_holo_dark</item>
<item name="android:actionModeBackground">#drawable/contextual</item>
<item name="android:actionModeCloseButtonStyle">#style/MyCloseButton</item>
<!-- these change the press backgrounds for the vanilla actionBar and for search -->
<item name="android:windowContentOverlay">#null</item>
<item name="android:selectableItemBackground">#drawable/bar_selector</item>
<item name="android:actionBarItemBackground">#drawable/bar_selector</item>
<!-- these were defined in platform/.../data/res/values/... but Eclipse didn't recognize them -->
<!--? item name="android:actionModeShareDrawable">#drawable/icon</item -->
<!--? item name="android:actionModeFindDrawable">#drawable/icon</item -->
<!--? item name="android:actionModeWebSearchDrawable">#drawable/icon</item -->
<!-- item name="android:actionModeBackground">#drawable/red</item -->
<!-- and finally -->
<style name="MyCloseButton" parent="android:style/Widget.ActionButton.CloseMode">
<item name="android:background">#drawable/bar_selector</item>
</style>
You can easily set your own text-editing cut/paste/copy/selectall icons, the bar
background, and the icon background that changes color when you press the icons(bar_selector above). The icons are ImageViews, not buttons, and the edit id's (and the pressable background) are attached to the ImageView's parent (one parent per view) which is an 'internal' type.
It's never clear what goes where in the styles--I found where selectableItemBackground was in the platform Themes.xml, and copied and modified the drawable pointed at.
I posted a comment to my own question, and this is actually a bug in the version of android I was using (Probably an early version of 4.0)
This is the bug described: http://code.google.com/p/android/issues/detail?id=26008
If you're starting the contextual action mode manually, you can call setTheme() with a new theme before launching it (maybe Theme.AppCompat.Light.DarkActionBar if you're trying to avoid the black-on-black text issue). This will not affect the theme of the current activity if you've already set the activity's content view.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity_layout);
// these lines can occur anywhere so long as you've already
// called "setContentView()" on the activity. The theme
// you set here will apply to the action mode, but not to
// the activity.
setTheme(R.style.Theme_AppCompat_Light_DarkActionBar);
startSupportActionMode(myActionModeCallback);
}
it works now, but you have to enter it in values/styles.xml (not values-v#/styles.xml) and enter it in the general (non-API specific tag)
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:actionModeCloseDrawable">#drawable/ic_launcher</item>
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
There's a question for the same functionality on Blackberry, and a few different threads referred to this bug (which has since been closed without resolution as far as I can tell), but I haven't found one specifically for Android.
I'm calling setEnabled(false) on certain MenuItems based on some state, but they visually look the same. I'd like them to be offset in some way, so that the user knows that the option currently isn't available -- is there any way to do that?
On all android versions, easiest way to use this to SHOW a menu action icon as disabled AND make it FUNCTION as disabled as well:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.menu_my_item);
if (myItemShouldBeEnabled) {
item.setEnabled(true);
item.getIcon().setAlpha(255);
} else {
// disabled
item.setEnabled(false);
item.getIcon().setAlpha(130);
}
}
I had the same issue. There are two ways of getting this to work:
Put your icons in a StateList so that a different icon will be used on disable
What I use now. Change the icon yourself with something like this in onPrepareOptionsMenu():
public boolean onPrepareOptionsMenu(Menu menu) {
boolean menusEnabled = reachedEndOfSlidehow(); // enable or disable?
MenuItem item = menu.findItem(R.id.menu_next_slide);
Drawable resIcon = getResources().getDrawable(R.drawable.ic_next_slide);
if (!menusEnabled)
resIcon.mutate().setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN);
item.setEnabled(menusEnabled); // any text will be automatically disabled
item.setIcon(resIcon);
}
You can call invalidateOptionsMenu() (or from ABS, supportInvalidateOptionsMenu()) to rebuild the menu.
EDIT: Updated solution 2
Source: https://groups.google.com/forum/?fromgroups#!topic/actionbarsherlock/Z8Ic8djq-3o
I found a new way to solve this issue using a drawable selector xml file. You just create a selector with the icon you want to use in your menu item, then you can either change the tint, alpha or both of the bitmap:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<bitmap android:src="#drawable/ic_menu_item"
android:tint="#color/enabled_color"
android:alpha="#integer/enabled_alpha"/>
</item>
<item android:state_enabled="false">
<bitmap android:src="#drawable/ic_menu_item"
android:tint="#color/disabled_color"
android:alpha="#integer/disabled_alpha"/>
</item>
</selector>
As a side note; I like to set the tint to "?android:attr/textColorPrimary" for enabled state and "?android:attr/textColorHint" for disabled state. This way it will adjust depending on the theme used.
Then you can just set the icon in your menu xml file to the selector resource:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/menu_action"
android:orderInCategory="0"
android:title="#string/title_menu_action"
android:icon="#drawable/ic_menu_item_selector"
app:showAsAction="ifRoom"/>
</menu>
Then when you call item.setEnabled(enabled) the color and/or alpha of the icon will change along with the state!
The way I did it is by using "itemIconTint" in NavigationView, you can also grey out the text by using "itemTextColor"
This is Navigationview:
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:itemBackground="#color/white"
android:background="#color/white"
app:itemTextColor="#color/menu_text_color"
app:itemIconTint="#color/menu_text_color"
app:menu="#menu/main_drawer" />
and the "#color/menu_text_color" is a selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="#color/primaryColor" />
<item android:state_enabled="false" android:color="#color/disabled_text_color" />
<item android:color="#color/primaryText" />
</selector>
Finally, if you want to disable a menuitem,
MenuItem item = mNavigationView.getMenu().findItem(R.id.your_menu_item);
item.setEnabled(isEnable);
Done!
I was having difficulty with this on modern android with MaterialComponents theme. My problem was I had set <item name="actionMenuTextColor">#color/blue</item> in styles.xml and this overrides the text color whether the item is enabled or disabled. The solution is to set a Color state list and not a color directly.
My styles attribute now looks like:
<item name="actionMenuTextColor">#color/menu_color_selector</item>
I had an issue where neither my the text nor the icon was visibly changing. The other answers either didn't work for me or weren't very elegant. Here's an answer that works for the latest Material recommendations.
You should be able to simply call menu.findItem(R.id.menu_my_item).isEnabled = false in onPrepareOptionsMenu(menu: Menu).
(If you need onPrepareOptionsMenu to run again, you can simply call invalidateOptionsMenu() or activity?.invalidateOptionsMenu() (from a fragment) and the application will queue up the menu to be recreated. Alternatively you can store off the menu item in a member variable to modify it later, but be careful to destroy your reference to it within onDestroyOptionsMenu to avoid a memory leak.)
The fact that the menu item is disabled should be enough to grey out the text or the icon automatically. The difficulty is in setting up your styles to make this work.
Short Answer
First create a color state list my_color_state_list.xml that you want your icons and text to use (e.g. black when enabled, grey when disabled). (See the full answer for an example.)
If you're using com.google.android.material.appbar.MaterialToolbar, you can tell it to use this selector for icons and text by providing a custom theme overlay. In your activity's XML, give the toolbar the attribute android:theme="#style/Foo" and define that style somewhere as:
<style name="Foo">
<item name="colorControlNormal">#color/my_color_state_list</item>
<item name="actionMenuTextColor">#color/my_color_state_list</item>
</style>
Now when the menu item is enabled or disabled via menu.findItem(R.id.menu_my_item).isEnabled = false the text will automatically change color, and any icons which use the color ?attr/colorControlNormal will also automatically change color.
Full answer
My starting place
My menu items are part of a Material toolbar. This answer may help for other kinds of toolbar/app bar, but your mileage may vary. In my activity I have something like this:
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.MaterialComponents.Toolbar.Surface"/>
and the theme I'm using looks something like this:
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">#color/blue</item>
<item name="colorSecondary">#color/green</item>
<item name="colorSurface">#color/lightGrey</item>
<item name="colorOnSurface">#color/black</item>
[...]
<item name="windowActionModeOverlay">true</item>
</style>
It is also convention that the icon you use in buttons and menu items (and everywhere really) should have their default color be ?attr/colorControlNormal. So for example I might have a vector image which looks like:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal"
android:tintMode="src_atop">
<path android:pathData="..." android:fillColor="#android:color/white"/>
</vector>
If you download an icon from Material Icons you will see they all use colorControlNormal.
What I needed to do
If you look back at the definition of my toolbar, you will see it uses a ThemeOverlay ThemeOverlay.MaterialComponents.Toolbar.Surface which is defined as:
<style name="ThemeOverlay.MaterialComponents.Toolbar.Surface" parent="">
<item name="colorControlNormal">#color/material_on_surface_emphasis_medium</item>
<item name="actionMenuTextColor">#color/material_on_surface_emphasis_medium</item>
</style>
This sets the menu item text color and icon color to #color/material_on_surface_emphasis_medium which does not respond to being enabled or not. #color/material_on_surface_emphasis_medium looks like:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="#dimen/material_emphasis_medium" android:color="?attr/colorOnSurface"/>
</selector>
(You may be using ThemeOverlay.MaterialComponents.Toolbar.Primary instead, which has a similar issue - it simply uses colorOnPrimary.)
We need to replace this with our own color state list which responds to enabled state. So, make a new file res/color/menu_item_selector.xml that looks something like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:alpha="#dimen/material_emphasis_medium" android:color="?attr/colorOnSurface"/>
<item android:alpha="#dimen/material_emphasis_disabled" android:color="?attr/colorOnSurface"/>
</selector>
You see I've used the same conventions that the material library does by using their constants to define the alpha values, and I used colorOnSurface as my color. If you were using ThemeOverlay.MaterialComponents.Toolbar.Primary you would want colorOnPrimary instead. Of course you can use any color or alpha here, it's up to you.
And now make a new ThemeOverlay in res/values/styles.xml to point to this selector, inheriting from whatever ThemeOverlay you were using:
<!-- Toolbar - overrides the menu text color to use a selector that responds to whether it's enabled or not -->
<style name="ThemeOverlay.MyTheme.Toolbar" parent="ThemeOverlay.MaterialComponents.Toolbar.Surface">
<!-- Color used in the icons of menu actions (i.e. non-overflow menu items). This is just convention, this will affect anything that uses ?attr/colorControlNormal) -->
<item name="colorControlNormal">#color/menu_item_color_selector</item>
<!-- Color used in the text of menu actions (i.e. non-overflow menu items) -->
<item name="actionMenuTextColor">#color/menu_item_color_selector</item>
</style>
And now finally we can apply this ThemeOverlay to the toolbar:
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.MyTheme.Toolbar"/>
setEnabled(false) works fine on API Level < 14 but on 14 the item still clickable.
Have a look at this link
setEnabled can also be used for MenuItems.
Here's a simple way to do it (using Kotlin):
fun changeMenuItemColour(enabled: Boolean) {
var menuItem = SpannableString(mCustomToolbar?.menu?.findItem(R.id.some_menu_item)?.title)
var style = activity?.resources?.getColor(R.color.darkGraphite)!!
if (enabled) style = activity?.resources?.getColor(R.color.black)!!
menuItem.setSpan(ForegroundColorSpan(style), 0, menuItem.length, 0)
}