Change MenuItem text color programmatically
@RRP give me a clue ,but his solution does not work for me. And @Box give a another, but his answer looks a little not so cleaner. Thanks them. So according to them, I have a total solution.
private static void setMenuTextColor(final Context context, final Toolbar toolbar, final int menuResId, final int colorRes) {
toolbar.post(new Runnable() {
@Override
public void run() {
View settingsMenuItem = toolbar.findViewById(menuResId);
if (settingsMenuItem instanceof TextView) {
if (DEBUG) {
Log.i(TAG, "setMenuTextColor textview");
}
TextView tv = (TextView) settingsMenuItem;
tv.setTextColor(ContextCompat.getColor(context, colorRes));
} else { // you can ignore this branch, because usually there is not the situation
Menu menu = toolbar.getMenu();
MenuItem item = menu.findItem(menuResId);
SpannableString s = new SpannableString(item.getTitle());
s.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, colorRes)), 0, s.length(), 0);
item.setTitle(s);
}
}
});
}
In order to change the colour of menu item you can find that item, extract the title from it, put it in a Spannable String and set the foreground colour to it. Try out this code piece
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
MenuItem mColorFullMenuBtn = menu.findItem(R.id.action_submit); // extract the menu item here
String title = mColorFullMenuBtn.getTitle().toString();
if (title != null) {
SpannableString s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(Color.parseColor("#FFFFFF")), 0, s.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); // provide whatever color you want here.
mColorFullMenuBtn.setTitle(s);
}
return super.onCreateOptionsMenu(menu);
}
It only becomes a text view after inspection, its real class is ActionMenuItemView, on which we can further set the text color like this:
public static void setToolbarMenuItemTextColor(final Toolbar toolbar,
final @ColorRes int color,
@IdRes final int resId) {
if (toolbar != null) {
for (int i = 0; i < toolbar.getChildCount(); i++) {
final View view = toolbar.getChildAt(i);
if (view instanceof ActionMenuView) {
final ActionMenuView actionMenuView = (ActionMenuView) view;
// view children are accessible only after layout-ing
actionMenuView.post(new Runnable() {
@Override
public void run() {
for (int j = 0; j < actionMenuView.getChildCount(); j++) {
final View innerView = actionMenuView.getChildAt(j);
if (innerView instanceof ActionMenuItemView) {
final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
if (resId == itemView.getId()) {
itemView.setTextColor(ContextCompat.getColor(toolbar.getContext(), color));
}
}
}
}
});
}
}
}
}
Bit late to the party with this one, but I spent a while working on this and found a solution, which may be of use to anyone else trying to do the same thing. Some credit goes to Harish Sridharan for steering me in the right direction.
You can use findViewById(R.id.MY_MENU_ITEM_ID)
to locate the menu item (provided that the menu had been created and prepared), and cast it to a TextView
instance as suggested by Harish, which can then be styled as required.
public class MyAwesomeActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
super.onCreate(savedInstanceState);
// Force invalidatation of the menu to cause onPrepareOptionMenu to be called
invalidateOptionsMenu();
}
private void styleMenuButton() {
// Find the menu item you want to style
View view = findViewById(R.id.YOUR_MENU_ITEM_ID_HERE);
// Cast to a TextView instance if the menu item was found
if (view != null && view instanceof TextView) {
((TextView) view).setTextColor( Color.BLUE ); // Make text colour blue
((TextView) view).setTextSize(TypedValue.COMPLEX_UNIT_SP, 24); // Increase font size
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean result = super.onPrepareOptionsMenu(menu);
styleMenuButton();
return result;
}
}
The trick here is to force the menu to be invalidated in the activity's onCreate
event (thereby causing the onPrepareMenuOptions
to be called sooner than it would normally). Inside this method, we can locate the menu item and style as required.