I implemented following function to change the color of all items in actionbar. and i use it to change the color of elements smoothly, when expanding or collapsing CollapsingToolbarLayout.
private void setToolbarElementsColor(int color) {
PorterDuffColorFilter colorFilter
= new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP);
toolbar.getNavigationIcon().setColorFilter(colorFilter);
//overflowDrawable is IconicDrawable from com.mikepenz.iconics
if (toolbar.getOverflowIcon() != overflowDrawable){
toolbar.setOverflowIcon(overflowDrawable);
}
overflowDrawable.color(color);
toolbar.setTitleTextColor(color);
for (int i = 0; i< toolbar.getMenu().size(); i++){
Drawable icon = toolbar.getMenu().getItem(i).getIcon();
if (icon !=null) {
// HERE IS THE CODE WITH EXPLAINED PROBLEM
icon.setColorFilter(colorFilter);
}
}
}
And here is code for menu items:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_back"
android:title="#string/add_remove_filter"
app:showAsAction="always" />
<item
android:id="#+id/action_filter"
android:title="#string/add_filter"
app:showAsAction="always" />
<item
android:id="#+id/action_save_report"
app:showAsAction="never"
android:title="#string/action_save_report">
</item>
</menu>
The code works fine. but one strange problem: when i open overflow menu once and close it, the menu icons retain the last color they have before opening overflow menu, and do not change in accordance to other toolbar elements (the new colors i set for all elements).
Example: Elements are black for expanded state with light toolbar, and white for collapsed state with dark toolbar. now if i collapse the toolbar and open the overflow menu and close it, after that the icon colors remain white, regardless of toolbar expanded or collapsed state, even thought the piece of [icon.setColorFilter(colorFilter);] is run correctly.
The problem solves when the activity goes to background and resumes again. e.g. pressing home button and returning to the activity using recent app list or opening new activity from that activity and returning.
I changed the code inside for loop to the code below but no luck (I am using IconicDrawables for menu icons)
IconicsDrawable icon = (IconicsDrawable) toolbar.getMenu().getItem(i).getIcon();
if (icon !=null) {
icon.color(color);
}
Replacing the icon drawable from IconicDrawable to PNG drawable inside drawables folder also didn't solve the problem.
Try to change the colors of the icon like this,using drawable mutation:-
if (icon !=null) {
icon.mutate();
icon.setColorFilter(colorFilter);
}
After some search, I solved the problem by adding the code below:
#Override
public boolean onMenuOpened(int featureId, Menu menu) {
invalidateOptionsMenu();
return super.onMenuOpened(featureId, menu);
}
It just redraws icons just after opening the overflow menu. but the reason of above mentioned problem is yet unknown to me.
Related
I've created a menu with a single item.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/syncButton"
android:title="Sync"
android:icon="#drawable/ic_sub_menu"
app:showAsAction="never"/>
</menu>
This is used on some of my activities in the toolbar, when clicked it drops down a menu, currently there is only one option but in the future it may be more.
Everything works well except the icon, it's a vector image of the traditional 3 dots colored white. Depending on what showAsAction" is set as it changes color.
Currently showAsAction is set to never so it displays a menu when clicked, this is what I want, but the icon changes to a dark grey. If i set this option to "always" then the icon changes to white but I lose the drop down menu.
How can I keep the drop down menu while keeping my icon white ?
If you just want to change the 3-Dots-Icon for the DropDownMenu, you can change this in your Styles.xml:
In your Theme Style define
<item name="android:actionOverflowButtonStyle">#style/MyTheme.OverFlow</item>
and then define the Overflow with your Icon you want to show instead the 3DotsIcon (in your case the Icon with 3 white dots)
<style name="MyTheme.OverFlow">
<item name="android:src">#drawable/yourNewIcon</item>
</style>
Try this code
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.menu_confirm, menu);
MenuItem action_done = menu.findItem(R.id.action_done);
action_done.setIcon(R.drawable.ic_filter);
menuIconColor(action_done, Color.WHITE);
super.onCreateOptionsMenu(menu, menuInflater);
}
public void menuIconColor(MenuItem menuItem, int color) {
Drawable drawable = menuItem.getIcon();
if (drawable != null) {
drawable.mutate();
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
}
}
I forked a GitHub project from https://github.com/nglauber/playground/tree/master/android/DemoSearch
I would like to set the color of the search icon to be pure white. At the moment, the search icon is gray in color, and is obviously different from the white text of "Demo Search".
Edit:
Based on some suggestions, I created a new icon using pure white (to be exact, RGB=255,255,255), and use it in place of the android:ic_menu_search. Android will tint it with a gray tone (verified with color picker tool on the screenshot), even though the original icon is in pure white.
This suggests to me that Android is tinting the icon on purpose. And I hope there is some way I can have the control to set or change the icon color in the Android Toolbar.
I found the answer to my own question. I decided to document it so it will be able to help other Android developers.
The short answer is yes, we can maintain the icon color in the Android Toolbar, and we need to do it by importing the resource through
SVG, or
PNG with icon type as Launcher Icons
The original problem that I encountered was due to
PNG with icon type as Action Bar and Tab Icons
In this setting, Android Studio Image Asset will change the icon color a little for some unknown reason when it saves to the res project folder. And Android will further change the icon color when it is finally displayed on the screen. The end result was what I described in the question, where the originally pure white icon will turn and become gray in color.
If we use SVG or PNG with icon type as Launcher Icons, there will be NO color change to the icon. The icon will be able to retain its original color. This makes me believe it is a bug in Android Studio rather than a design guideline assistance.
Similar observation is reported in this Stack Overflow post. #markj reported "the resulting images are just useless gray shapes".
The resulting Android environment screenshots
Color maintained
(SVG)
(PNG as Launcher Icons)
Color changed
(PNG as Action Bar and Tab Icons)
You have to make white icon and add it in menu_search.xmlin res/menu` file.
Currently its android:icon="#android:drawable/ic_menu_search". But you can use your own icon here. You can then write it as android:icon="#drawable/ic_menu_search" in res/menu file.
You have to use menu. Add searchView as an item in menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_search"
android:title="Search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom"
android:orderInCategory="1"
android:menuCategory="secondary"
android:visible="true"
/>
</menu>
And in your activity Override this method
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
menuItem = menu.findItem(R.id.menu_search);
searchView = (SearchView) MenuItemCompat.getActionView(menuItem);
searchView.setIconifiedByDefault(true);
//get search icon View and set your drawable
ImageView icon = (ImageView)searchView.findViewById(R.id.search_button);
icon.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_search_white_24dp));
return true;
}
You just need to change to using SearchView class from support library
<item
android:id="#+id/action_search"
android:icon="#drawable/ic_search_white_24dp"
android:orderInCategory="2"
android:title="Search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always" />
I have a menu with groups that contain items. These items change color, including their icon, like visited links in HTML. I never specified this behavior or color (which I can't find in my resources at all).
Its applying a tint to the whole item, including the icon after I click on it. Here is my XML.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="none">
<item
android:id="#+id/action_one"
android:icon="#drawable/ic_one"
android:title="#string/one"/>
<item
android:id="#+id/action_two"
android:icon="#drawable/two"
android:title="#string/two" />
</group>
</menu>
I also don't see any attribute to stop this behavior? Do I have to modify an app theme or something to disable this? I want all of my items to have the same color, even after they are clicked on.
The issue was that the menu item was being selected programmatically, which I didn't realize was happening.
...
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// menuItem.setChecked(true); <-- was changing the color
...
Commenting out this line leaves the color as the default color.
I need to change the background of menu items only. When I tried with actionBarItemBackground, it changes the background of application logo [As u can see in the attachment] also. Any help or link will be appreciated.
You can use a custom layout for your actionbar item like so:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#id/item_text"
android:showAsAction="always"
android:actionLayout="#layout/action_text"/>
</menu>
This is styleable as you wish. Another possibility would be adding only the ID (item_text in the example) and set the background like so:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.item_text);
item.getActionView().setBackgroundDrawable(new ColorDrawable(/* your color */));
return super.onPrepareOptionsMenu(menu);
}
On a Galaxy S3, I have an issue where a button in the ActionBar is configured as showAsAction="always" and being shown on both the hardware overflow menu and the Action buttons. I would like it to not be shown on the hardware overflow menu and only on the Action buttons. I can disable the menuitem in the onCreateOptionsMenu but it will hide the button on both places.
Something to note: if I force the "3 dots" Action Overflow menu to show, the refresh button gets properly hidden from the hardware overflow menu but still doesn't get hidden from the hardware overflow menu.
Something else to note: if I call menu.size() in either onCreateOptionsMenu or onPrepareOptionsMenu, it doesn't reflect the extra button. For example, I have four buttons and the first button is being shown in both the Action buttons and the overflow menu. menu.size() still returns 4 and doesn't seem to realize that it is showing an extra button.
I can't post a screenshot because this is an app for a client but here is my actionbar.xml file. The refresh button shows in both the overflow and the action bar at the top.
actionbar.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#+id/refreshmenuitem"
android:icon="#drawable/refreshicon"
android:title="Refresh"
android:showAsAction="ifRoom"
android:visible="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<item android:id="#+id/helpbutton"
android:title="Help"
android:showAsAction="collapseActionView"
android:icon="#drawable/ic_action_helpbutton" />
<item android:id="#+id/settingbutton"
android:title="Settings"
android:icon="#drawable/ic_action_settingbutton"
android:showAsAction="collapseActionView" />
<item android:id="#+id/importbutton"
android:title="Import file"
android:icon="#drawable/ic_action_importbutton"
android:showAsAction="collapseActionView" />
</menu>
So I figured it out but it is kind of a hack. So if you have a phone such as the Samsung Galaxy S3 that has a hardware menu button, the onCreateOptionsMenu function actually gets called twice. Once for when the Activity gets loaded to load any menu items that should display in the top right and another time when the user presses the hardware menu button. All I did was create a variable called _firstTimeOnCreateOptionsMenu that is set to false after the first time it is onCreateOptionsMenu method:
public boolean onCreateOptionsMenu(Menu menu)
{
// Populates the actionbar/Menu
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.actionbarmenu, menu);
boolean hardware = false;
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
{
hardware = ViewConfiguration.get(context).hasPermanentMenuKey();
}
MenuItem b1 = menu.findItem(R.id.refreshmenuitem);
if(!hardware || _firstTimeOnCreateOptionsMenu)
{
b1.setVisible(true);
_firstTimeOnCreateOptionsMenu = false;
}
else
{
b1.setVisible(false);
_firstTimeOnCreateOptionsMenu = true;
}
}
Hopefully this helps anyone else who is having this issue.
Is your targetSdkVersion set to 14?
http://android-developers.blogspot.com/2012/01/say-goodbye-to-menu-button.html
I'd be a bit surprised if this was the issue, since you'd expect unknown XML to just be ignored, but according to the documentation <item> does not support android:layout_width and android:layout_height.