Изменение цвета менюИзменить цвет текста программно
Итак, у меня есть пункт меню, который определяется как:
<item
android:id="@+id/action_live"
android:title="@string/action_live"
android:orderInCategory="1"
app:showAsAction="ifRoom|withText" />
Он отображается как текст, как вы можете видеть ниже:
![Снимок экрана 1]()
И я хочу программно изменить цвет текста "LIVE". Я искал какое-то время, и я нашел метод:
В глобальном определении:
private Menu mOptionsMenu;
и
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mOptionsMenu = menu;
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
Я делаю:
MenuItem liveitem = mOptionsMenu.findItem(R.id.action_live);
SpannableString s = new SpannableString(liveitem.getTitle().toString());
s.setSpan(new ForegroundColorSpan(Color.RED), 0, s.length(), 0);
liveitem.setTitle(s);
Но ничего не происходит!
Если я делаю то же самое для элемента меню переполнения, он работает:
![Снимок экрана 2]()
Есть ли ограничения для приложения: showAsAction = "ifRoom | withText"? Есть ли способ обхода?
Спасибо заранее.
Ответы
Ответ 1
Бит поздно на вечеринку с этим, но я потратил некоторое время на это и нашел решение, которое может быть полезно для всех, кто пытается сделать то же самое. Некоторый кредит принадлежит Харишу Шридхарану за то, что он меня направил в правильном направлении.
Вы можете использовать findViewById(R.id.MY_MENU_ITEM_ID)
, чтобы найти элемент меню (при условии, что меню было создано и подготовлено), и передать его в экземпляр TextView
, как это предложил Хариш, который затем может быть оформлен по мере необходимости.
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;
}
}
Трюк здесь заключается в том, чтобы заставить меню быть недействительным в событии onCreate
(тем самым вызывая onPrepareMenuOptions
называться раньше, чем обычно). Внутри этого метода мы можем найти элемент меню и стиль по мере необходимости.
Ответ 2
@RRP дайте мне ключ, но его решение не работает для меня. И @Box дать другой, но его ответ выглядит немного не так чище. Спасибо им. Поэтому, по их словам, у меня есть полное решение.
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);
}
}
});
}
Ответ 3
Он становится только текстовым видом после проверки, его реальным классом является ActionMenuItemView, на котором мы можем дополнительно установить цвет текста следующим образом:
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));
}
}
}
}
});
}
}
}
}
Ответ 4
MenuItem, как определено в документации, является интерфейсом. Он определенно будет реализован с виджетами вида, прежде чем будет отображаться как меню. В большинстве случаев эти пункты меню реализованы как TextView. Вы можете использовать UiAutomatorViewer для просмотра иерархии представлений или даже использовать иерархический просмотрщик, который будет найден в [sdk-home]/tools/. Прикрепленный к одному образцу скриншот uiautomatorviewer для MenuItem
Таким образом, вы всегда можете придать свой MenuItem и установить цвет.
TextView liveitem = (TextView)mOptionsMenu.findItem(R.id.action_live);
liveitem.setTextColor(Color.RED);
EDIT:
Поскольку у нас был запрос посмотреть, как использовать этот инструмент, я добавляю еще несколько содержимого.
Убедитесь, что вы установили переменную окружения $ANDROID_HOME, указывая на ваш SDK HOME.
В терминале:
cd $ANDROID_HOME
./tools/uiautomatorviewer
Этот инструмент откроется.
Вторая или третья кнопка (см. скриншот) в меню отобразит скриншот вашего подключенного устройства или эмулятора, и вы сможете осмотреть представление и их иерархию. Нажатие на представление будет описывать представление и их информацию. Это инструмент, специально предназначенный для тестирования, и вы можете проверять любое приложение.
Обратитесь к сайту разработчика за дополнительной информацией: uiautomatorviewer
![uiautomatorviewer]()
Ответ 5
Я потратил много часов на это и наконец получил его на работу. Существует легкое решение для Android 6 и 7, но оно не работает на Android 5. Этот код работает на всех из них. Итак, если вы делаете это в Котлине, это мое предложение:
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
setToolbarActionTextColor(menu, R.color.black)
this.menu = menu
return true
}
private fun setToolbarActionTextColor(menu: Menu, color: Int) {
val tb = findViewById<Toolbar>(R.id.toolbar)
tb?.let { toolbar ->
toolbar.post {
val view = findViewById<View>(R.id.my_tag)
if (view is TextView) {
view.setTextColor(ContextCompat.getColor(this, color))
} else {
val mi = menu.findItem(R.id.my_tag)
mi?.let {
val newTitle: Spannable = SpannableString(it.title.toString())
val newColor = ContextCompat.getColor(this, color)
newTitle.setSpan(ForegroundColorSpan(newColor),
0, newTitle.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
it.title = newTitle
}
}
}
}
}
Ответ 6
Есть ли способ изменить цвет заголовка меню ниже уровня API 24, потому что все вышеперечисленное решение работает для меня, но только выше уровня API 24