Подтвердить что ты не робот

Изменение цвета менюИзменить цвет текста программно

Итак, у меня есть пункт меню, который определяется как:

<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"? Есть ли способ обхода?

Спасибо заранее.

4b9b3361

Ответ 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