Jak zmienić kolor tekstu pozycji menu w systemie Android?

175

Czy mogę zmienić kolor tła elementu menu w systemie Android?

Daj mi znać, jeśli ktoś ma jakieś rozwiązanie tego problemu. Ostatnią opcją będzie oczywiście dostosowanie go, ale czy istnieje sposób na zmianę koloru tekstu bez dostosowywania go.

sunil
źródło
Czy jest ktoś, kto może dać mi znać rozwiązanie tego problemu?
sunil
3
chcesz zmienić kolor tekstu, kolor tła widoku tekstu? lub oba? Obie sprawy są różne. Proszę przeformułować pytanie.
Abhinav Saxena

Odpowiedzi:

335

Jedna prosta linia w Twoim motywie :)

<item name="android:actionMenuTextColor">@color/your_color</item>
Muhammad Alfaifi
źródło
19
UWAGA: MUSI to znaleźć się w głównej definicji motywu dla Twojej aplikacji, a NIE actionBarStylena przykład. To nie zadziała wewnątrz actionBarStyle, nawet jeśli wydaje się to logiczne!
Colin M.
47
Aby obsługiwać niższe wersje API <item name="actionMenuTextColor">@color/your_color</item>, nie używaj przestrzeni nazw Androida
alex.p
5
@ColinM. Ma wchodzić do tematu. Jeśli ustawisz themeatrybut na pasku narzędzi, zadziała.
DariusL
2
Nie działało dla mnie z lub bez android: namespace. Został dodany do głównego motywu aplikacji.
wyścigi
2
Nadal nie mogę zmienić koloru tekstu. Mój ogólny kolor tekstu motywu ma po prostu pierwszeństwo. Jakaś pomoc? Żadna z tych odpowiedzi nie działa.
David P
114

Wygląda na to, że plik

  <item name="android:itemTextAppearance">@style/myCustomMenuTextAppearance</item>

w moim motywie i

   <style name="myCustomMenuTextAppearance" parent="@android:style/TextAppearance.Widget.IconMenu.Item">
        <item name="android:textColor">@android:color/primary_text_dark</item>
    </style>

w styles.xml zmieniają styl elementów listy, ale nie elementów menu.

Marcus Wolschon
źródło
5
Działa to świetnie w przypadku elementów menu kontekstowego (nie elementów menu z przycisku menu), czego szukałem. Znacznie prostsze niż cały bałagan LayoutFactory.
chubbsondubs
android:itemTextAppearanceAtrybut nie może być umieszczony w stylu, którego rodzic jest parent="@android:style/Widget.Holo.ListPopupWindow"od tego nie uczyni prawidłowo. Musi być w stylu najwyższego poziomu, takim jak ten, którego rodzicem jest android:Theme.Holo.Light.DarkActionBar.
toobsco42
Gdzie mam dodać <item name = "android: itemTextAppearance"> @ style / myCustomMenuTextApearance </item>?
Bagusflyer,
@bagusflyer należy dodać, że w stylu głównego motywu, czyli stylu, który jest dzieckiem Theme.Hololub Theme.Holo.Light.DarkActionBarlub podobny.
Tash Pemhiwa
86

Możesz łatwo zmienić kolor MenuItemtekstu, używając SpannableStringzamiast String.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.your_menu, menu);

    int positionOfMenuItem = 0; // or whatever...
    MenuItem item = menu.getItem(positionOfMenuItem);
    SpannableString s = new SpannableString("My red MenuItem");
    s.setSpan(new ForegroundColorSpan(Color.RED), 0, s.length(), 0);
    item.setTitle(s);
}
max.mustermann
źródło
10
To działało dla mnie zarówno w 4.4, jak i 5+ używając menu.findItem(R.id.menu_item_id);zamiastmenu.getItem()
haagmm
1
U mnie też zadziałało [używając findItem (...)].
oszołomiony
6
Rozwiązania pracować tylko dla elementu przelewem .... I wan't aby zmienić kolor elementu, który jest widoczny poprzez ustawienie showAsAction: „Zawsze”
Junaid
56

Jeśli używasz nowego paska narzędzi z motywem Theme.AppCompat.Light.NoActionBar, możesz stylizować go w następujący sposób.

 <style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:textColorPrimary">@color/my_color1</item>
    <item name="android:textColorSecondary">@color/my_color2</item>
    <item name="android:textColor">@color/my_color3</item>
 </style>`

Zgodnie z wynikami, które otrzymałem,
android:textColorPrimaryto kolor tekstu wyświetlający nazwę Twojej aktywności, który jest podstawowym tekstem paska narzędzi.

android:textColorSecondaryto kolor tekstu napisów i przycisku więcej opcji (3 kropki). (Tak, zmienił kolor zgodnie z tą właściwością!)

android:textColorJest kolorem wszystkich innych tekstów, w tym menu.

Na koniec ustaw motyw na pasku narzędzi

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:theme="@style/ToolbarTheme"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"/>
Sudara
źródło
Który element zarządza tekstem na przyciskach, które są wyświetlane jako akcje (tekst) na pasku narzędzi? Wydaje się, że ani android: textColorPrimary, android: textColorSecondary, ani android: textColor nie mają na nie wpływu.
LarsH
W odpowiedzi na moje pytanie w poprzednim komentarzu: android:actionMenuTextColor(patrz stackoverflow.com/a/5538709/423105 ).
LarsH
32

Jeśli używasz menu jako, <android.support.design.widget.NavigationView />po prostu dodaj poniższy wiersz NavigationView:

app:itemTextColor="your color"

Dostępny również odcień koloru dla ikony, zastąpi on również kolor ikony. W tym celu musisz dodać poniższy wiersz:

app:itemIconTint="your color"

Przykład:

<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:itemTextColor="@color/color_white"
        app:itemIconTint="@color/color_white"

        android:background="@color/colorPrimary"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer"/>

Mam nadzieję, że to ci pomoże.

Mihir Trivedi
źródło
Zmieniło to elementy zagnieżdżone w innym elemencie, ale nie zmieniło elementu zawierającego inne elementy. Czy wiesz, jak mogłem je zmienić?
Dinu Nicolae,
@DinuNicolae Czy możesz opublikować przykładowy zrzut ekranu? Lub podaj więcej szczegółów.
Mihir Trivedi
Miałem <item> <menu> <elementy wewnętrzne> </menu> </item> i zmienił się tylko kolor elementów wewnątrz
Dinu Nicolae
31

Robiłem to programowo w ten sposób:

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.changeip_card_menu, menu); 
    for(int i = 0; i < menu.size(); i++) {
        MenuItem item = menu.getItem(i);
        SpannableString spanString = new SpannableString(menu.getItem(i).getTitle().toString());
        spanString.setSpan(new ForegroundColorSpan(Color.BLACK), 0,     spanString.length(), 0); //fix the color to white
        item.setTitle(spanString);
    }
    return true;
}
Muralikrishna GS
źródło
2
Twoja odpowiedź pomogła mi ustawić pogrubiony tekst MenuItem. (s.setSpan (new StyleSpan (android.graphics.Typeface.BOLD), 0, s.length (), 0); Dzięki!
Arkadiusz Cieśliński
To rozwiązanie pomogło w moim problemie. Podoba mi się to, ponieważ nie będzie zależało od warunków związanych z tematem.
Tomcat
15

jak widzisz w tym pytaniu powinieneś:

<item name="android:textColorPrimary">yourColor</item>

Powyższy kod zmienia kolor tekstu pozycji czynności menu dla API> = v21.

<item name="actionMenuTextColor">@android:color/holo_green_light</item>

Powyżej znajduje się kod API <v21

Pouya Danesh
źródło
Dziękuję Ci. Należy to zaakceptować. To proste i łatwe
Pooja
10

Użyłem tagu HTML, aby zmienić kolor tekstu pojedynczego elementu, gdy element menu jest zawyżony. Mam nadzieję, że to byłoby pomocne.

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);
    menu.findItem(R.id.main_settings).setTitle(Html.fromHtml("<font color='#ff3824'>Settings</font>"));
    return true;
}
alijandro
źródło
1
To nie działa dla mnie na Marshmallow. Zastosowany zostanie tekst, ale nie kolor.
Ollie C
Jeśli chodzi o piankę Marshmallow, prawdopodobnie nie działa z tego samego powodu, który podano w odpowiedzi max.mustermanna, „rozwiązania działają tylko dla elementu w przepełnieniu”.
Jose_GD
10

NAJPROSTSZY sposób tworzenia niestandardowego koloru menu dla pojedynczego paska narzędzi, a nie dla AppTheme

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay.MenuBlue">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"/>
    </android.support.design.widget.AppBarLayout>

zwykły pasek narzędzi w styles.xml

<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>

nasz niestandardowy styl paska narzędzi

<style name="AppTheme.AppBarOverlay.MenuBlue">
    <item name="actionMenuTextColor">@color/blue</item>
</style>
AndrewS
źródło
Działa świetnie! Najlepsza odpowiedź.
bebe
9

w Kotlinie napisałem te rozszerzenia:

fun MenuItem.setTitleColor(color: Int) {
    val hexColor = Integer.toHexString(color).toUpperCase().substring(2)
    val html = "<font color='#$hexColor'>$title</font>"
    this.title = html.parseAsHtml()
}           



@Suppress("DEPRECATION")                                                                        
fun String.parseAsHtml(): Spanned {                                                             
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {                                
        Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)                                         
    } else {                                                                                    
        Html.fromHtml(this)                                                                     
    }                                                                                           
}  

i używane w ten sposób:

menu.findItem(R.id.main_settings).setTitleColor(Color.RED)
Amir Khorsandi
źródło
Naprawdę lubię to rozwiązanie, bardzo zadbane!
Jamil Nawaz
Dzięki, proste i szybkie rozwiązanie. Dla API> 24 działa bez tej drugiej funkcji ext
laszlo
7

Krótka odpowiedź brzmi: TAK. Szczęściarz!
Aby to zrobić, musisz zastąpić niektóre style domyślnych stylów Androida:

Najpierw spójrz na definicję motywów w systemie Android:

<style name="Theme.IconMenu">
<!-- Menu/item attributes -->
<item name="android:itemTextAppearance">@android:style/TextAppearance.Widget.IconMenu.Item</item>
<item name="android:itemBackground">@android:drawable/menu_selector</item>
<item name="android:itemIconDisabledAlpha">?android:attr/disabledAlpha</item>
<item name="android:horizontalDivider">@android:drawable/divider_horizontal_bright</item>
<item name="android:verticalDivider">@android:drawable/divider_vertical_bright</item>
<item name="android:windowAnimationStyle">@android:style/Animation.OptionsPanel</item>
<item name="android:moreIcon">@android:drawable/ic_menu_more</item>
<item name="android:background">@null</item>
</style>

Tak więc wygląd tekstu w menu znajduje się w @android:style/TextAppearance.Widget.IconMenu.Item
Teraz, w definicji stylów :

<style name="TextAppearance.Widget.IconMenu.Item" parent="TextAppearance.Small">
<item name="android:textColor">?textColorPrimaryInverse</item>
</style>

Więc teraz mamy nazwę danego koloru, jeśli spojrzysz na folder kolorów zasobów systemu:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="@android:color/bright_foreground_light_disabled" /> 
<item android:state_window_focused="false" android:color="@android:color/bright_foreground_light" /> 
<item android:state_pressed="true" android:color="@android:color/bright_foreground_light" /> 
<item android:state_selected="true" android:color="@android:color/bright_foreground_light" /> 
<item android:color="@android:color/bright_foreground_light" /> 
<!--  not selected --> 
</selector>

Wreszcie, oto, co musisz zrobić:

Zastąp „TextAppearance.Widget.IconMenu.Item” i utwórz własny styl. Następnie połącz go z własnym selektorem, aby dostosować go do swoich potrzeb. Mam nadzieję, że to ci pomoże. Powodzenia!

Sephy
źródło
Dzięki za odpowiedź. Zrobiłem to, co zasugerowałeś, ale nie zmieniłem koloru pozycji menu
sunil
Właściwie to właśnie zdałem sobie sprawę, czytając więcej elementów menu, że jest to o wiele bardziej skomplikowane niż myślałem. Jeśli nie chcesz tworzyć własnego pełnego menu niestandardowego ... Będzie to wymagało więcej lektury dla mnie, zatrzymam opublikowałeś tutaj, jeśli znajdę więcej.
Sephy
Nie można zastąpić „TextAppearance.Widget.IconMenu.Item”.
peceps
Ta odpowiedź jest myląca ... więc wniosek jest taki, że nie działa i jest znacznie trudniejszy / długotrwały niż początkowo sądzono?
speedynomads
6

Menu opcji w systemie Android można dostosować, aby ustawić tło lub zmienić wygląd tekstu. Nie można zmienić koloru tła i tekstu w menu za pomocą motywów i stylów. Kod źródłowy Androida (data \ res \ layout \ icon_menu_item_layout.xml) używa niestandardowego elementu klasy „com.android.internal.view.menu.IconMenuItem” widoku dla układu menu. Możemy dokonać zmian w powyższej klasie, aby dostosować menu. Aby osiągnąć to samo, użyj klasy fabrycznej LayoutInflater i ustaw kolor tła i tekstu dla widoku.


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.my_menu, menu);
    getLayoutInflater().setFactory(new Factory() {
        @Override
        public View onCreateView(String name, Context context, AttributeSet attrs) {
            if (name .equalsIgnoreCase(“com.android.internal.view.menu.IconMenuItemView”)) {
                try{
                    LayoutInflater f = getLayoutInflater();
                    final View view = f.createView(name, null, attrs);
                    new Handler().post(new Runnable() {
                        public void run() {
                            // set the background drawable
                            view .setBackgroundResource(R.drawable.my_ac_menu_background);

                            // set the text color
                            ((TextView) view).setTextColor(Color.WHITE);
                        }
                    });
                    return view;
                } catch (InflateException e) {
                    } catch (ClassNotFoundException e) {}
            }
            return null;
        }
    });
    return super.onCreateOptionsMenu(menu);
}


Abhay Kumar
źródło
3
03-23 19:45:25.134: E/AndroidRuntime(26761): java.lang.IllegalStateException: A factory has already been set on this LayoutInflater
Do Kra
Działa to po raz pierwszy. Gdy otworzysz menu po raz drugi, pojawi się wyjątek.
LoveForDroid
6

Dzięki za przykładowy kod. Musiałem go zmodyfikować, aby działał z menu kontekstowym. To jest moje rozwiązanie.

    static final Class<?>[] constructorSignature = new Class[] {Context.class, AttributeSet.class};

class MenuColorFix implements LayoutInflater.Factory {
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        if (name.equalsIgnoreCase("com.android.internal.view.menu.ListMenuItemView")) {
            try {
                Class<? extends ViewGroup> clazz = context.getClassLoader().loadClass(name).asSubclass(ViewGroup.class);
                Constructor<? extends ViewGroup> constructor = clazz.getConstructor(constructorSignature);
                final ViewGroup view = constructor.newInstance(new Object[]{context,attrs});

                new Handler().post(new Runnable() {
                    public void run() {
                        try {
                            view.setBackgroundColor(Color.BLACK);
                            List<View> children = getAllChildren(view);
                            for(int i = 0; i< children.size(); i++) {
                                View child = children.get(i);
                                if ( child instanceof TextView ) {
                                    ((TextView)child).setTextColor(Color.WHITE);
                                }
                            }
                        }
                        catch (Exception e) {
                            Log.i(TAG, "Caught Exception!",e);
                        }

                    }
                });
                return view;
            }
            catch (Exception e) {
                Log.i(TAG, "Caught Exception!",e);
            }
        }
        return null;
    }       
}

public List<View> getAllChildren(ViewGroup vg) {
    ArrayList<View> result = new ArrayList<View>();
    for ( int i = 0; i < vg.getChildCount(); i++ ) {
        View child = vg.getChildAt(i);
        if ( child instanceof ViewGroup) {
            result.addAll(getAllChildren((ViewGroup)child));
        }
        else {
            result.add(child);
        }
    }
    return result;
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    LayoutInflater lInflater = getLayoutInflater();
    if ( lInflater.getFactory() == null ) {
        lInflater.setFactory(new MenuColorFix());
    }
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.myMenu, menu);
}

U mnie to działa z Androidem 1.6, 2.03 i 4.03.

Michael Vogl
źródło
Jeśli robisz powyższe, powinieneś po prostu spojrzeć na użycie rozwiązania Marcus Wolschon. Dużo prostsze.
chubbsondubs
Rozwiązanie xml nie działa dla mnie np. Na 2.3.x, ale działa to jak urok - również na 4.x
sunlock
To rozwiązanie działało najlepiej. Musiałem również przechwycić android.support.v7.internal.view.menu.ListMenuItemView, aby uzyskać style zastosowane na urządzeniach korzystających z biblioteki kompatybilności
Chiatar
Ta poprawka nie będzie działać z Google Maps v2 - super metoda musi być wywoływana 1st, aby mapy były poprawnie renderowane.
Chiatar
5

znalazłem to Eureka !!

w motywie aplikacji:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:actionBarStyle">@style/ActionBarTheme</item>
    <!-- backward compatibility -->          
    <item name="actionBarStyle">@style/ActionBarTheme</item>        
</style>

oto motyw paska akcji:

<style name="ActionBarTheme" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
   <item name="android:background">@color/actionbar_bg_color</item>
   <item name="popupTheme">@style/ActionBarPopupTheme</item
   <!-- backward compatibility -->
   <item name="background">@color/actionbar_bg_color</item>
</style>

a oto motyw wyskakującego okienka:

 <style name="ActionBarPopupTheme">
    <item name="android:textColor">@color/menu_text_color</item>
    <item name="android:background">@color/menu_bg_color</item>
 </style>

Twoje zdrowie ;)

Fareed Alnamrouti
źródło
5

aby zmienić kolor tekstu pozycji menu użyj poniższego kodu

<style name="AppToolbar" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:itemTextAppearance">@style/menu_item_color</item>
</style>

gdzie

<style name="menu_item_color">
<item name="android:textColor">@color/app_font_color</item>
</style>
Muhammad Abdullah
źródło
4

Dzięki max.musterman, oto rozwiązanie, które uzyskałem na poziomie 22:

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    MenuItem searchMenuItem = menu.findItem(R.id.search);
    SearchView searchView = (SearchView) searchMenuItem.getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setSubmitButtonEnabled(true);
    searchView.setOnQueryTextListener(this);
    setMenuTextColor(menu, R.id.displaySummary, R.string.show_summary);
    setMenuTextColor(menu, R.id.about, R.string.text_about);
    setMenuTextColor(menu, R.id.importExport, R.string.import_export);
    setMenuTextColor(menu, R.id.preferences, R.string.settings);
    return true;
}

private void setMenuTextColor(Menu menu, int menuResource, int menuTextResource) {
    MenuItem item = menu.findItem(menuResource);
    SpannableString s = new SpannableString(getString(menuTextResource));
    s.setSpan(new ForegroundColorSpan(Color.BLACK), 0, s.length(), 0);
    item.setTitle(s);
}

Zakodowany na stałe Color.BLACKmógłby stać się dodatkowym parametrem setMenuTextColormetody. Użyłem tego tylko do pozycji menu, które były android:showAsAction="never".

lightkeeper
źródło
Nie działa dla mnie na API 24. Jakieś pomysły? Utknąłem w tym od wielu dni ... śmieszne!
David P
Nie wiem, co ci powiedzieć. To działa dobrze dla mnie w API 25.
lightkeeper
3

Możesz ustawić kolor programowo.

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);
            }

        }
    });
}
Victor Choy
źródło
3

Dodanie tego do mojego styles.xml zadziałało

<item name="android:textColorPrimary">?android:attr/textColorPrimaryInverse</item>
Asim
źródło
2

Po prostu dodaj to do swojego motywu

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:itemTextAppearance">@style/AppTheme.ItemTextStyle</item>
</style>

<style name="AppTheme.ItemTextStyle" parent="@android:style/TextAppearance.Widget.IconMenu.Item">
        <item name="android:textColor">@color/orange_500</item>
</style>

Testowane na API 21

Pham Quan
źródło
2
Lepiej go używać <style name="AppTheme.ItemTextStyle" parent="@android:style/TextAppearance.Widget">, w przeciwnym razie tekst będzie wyglądał za mały w rozszerzonym menu. Pamiętaj również, że ta technika działa tylko w systemie Android 5 i nowszych.
Mr-IDE
2
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.search, menu);


    MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
    SearchView searchView = (SearchView) myActionMenuItem.getActionView();

    EditText searchEditText = (EditText) searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
    searchEditText.setTextColor(Color.WHITE); //You color here
Bäda
źródło
1
wyjaśnij swoją odpowiedź
Coder
1
A jeśli to nie jest widok wyszukiwania?
nasch
2

Moja sytuacja to ustawienia koloru tekstu w menu opcji (główne menu aplikacji pokazane po naciśnięciu przycisku menu).

Testowane w API 16 z biblioteką appcompat-v7-27.0.2 , AppCompatActivitydla MainActivityi AppCompatmotywem dla aplikacji w AndroidManifest.xml .

styles.xml :

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <item name="actionBarPopupTheme">@style/PopupTheme</item>
</style>

<style name="PopupTheme" parent="@style/ThemeOverlay.AppCompat.Light">
  <item name="android:textColorSecondary">#f00</item>
</style>

Nie wiem, czy textColorSecondaryma to wpływ na inne elementy, ale steruje kolorem tekstu menu.


Przeszukałem kilka przykładów na ten temat, ale wszystkie gotowe do użycia fragmenty nie działały.

Dlatego chciałem to zbadać z kodem źródłowym biblioteki appcompat-v7 (szczególnie z folderem res pakietu .aar ).

Chociaż w moim przypadku użyłem Eclipse z eksplodowanymi zależnościami .aar . Mogłem więc zmienić domyślne style i sprawdzić wyniki. Nie wiem, jak rozbić biblioteki, które mają być używane bezpośrednio z Gradle lub Android Studio . Zasługuje na kolejny wątek śledztwa.

Więc moim celem było znalezienie koloru w pliku res / values ​​/ values.xml używanego w tekście menu (byłem prawie pewien, że kolor tam jest).

  1. Otworzyłem ten plik, a następnie zduplikowałem wszystkie kolory, umieściłem je poniżej domyślnych, aby je zastąpić i przypisałem #f00 wartość do wszystkich.
  2. Uruchom aplikację.
  3. Wiele elementów miało czerwone tło lub kolor tekstu. A także pozycje menu. To było to, czego potrzebowałem.
  4. Usuwając dodane przeze mnie kolory blokami po 5-10 linii zakończyłem secondary_text_default_material_lightelementem kolorowym.
  5. Szukając tej nazwy w plikach w folderze res (lub lepiej w res / colors ) znalazłem tylko jedno wystąpienie w pliku color / abc_secondary_text_material_light.xml (użyłem Sublime Text do tych operacji, więc łatwiej jest znaleźć to, czego potrzebuję).
  6. Wracając do values.xml znaleziono 8 zastosowań @color/abc_secondary_text_material_light.
  7. To był lekki motyw, więc pozostały 4 w 2 tematach: Base.ThemeOverlay.AppCompat.LightiPlatform.AppCompat.Light .
  8. Pierwszy motyw był dzieckiem drugiego, więc były tylko 2 atrybuty z tym zasobem koloru: android:textColorSecondaryoraz android:textColorTertiaryw Base.ThemeOverlay.AppCompat.Light.
  9. Zmieniając ich wartości bezpośrednio w values.xml i uruchamiając aplikację stwierdziłem, że ostateczny poprawny atrybut to android:textColorSecondary.
  10. Następnie potrzebowałem motywu lub innego atrybutu, aby móc go zmienić w pliku style.xml mojej aplikacji (ponieważ mój motyw miał jako element nadrzędny, Theme.AppCompat.Lighta nie ThemeOverlay.AppCompat.Light).
  11. Szukałem w tym samym pliku pliku Base.ThemeOverlay.AppCompat.Light. Miał dzieckoThemeOverlay.AppCompat.Light .
  12. Szukając pliku ThemeOverlay.AppCompat.Light, znalazłem jego użycie w Base.Theme.AppCompat.Light.DarkActionBarmotywie jakoactionBarPopupTheme wartość atrybutu.
  13. Motyw mojej aplikacji Theme.AppCompat.Light.DarkActionBarbył potomkiem znalezionego, Base.Theme.AppCompat.Light.DarkActionBarwięc mogłem użyć tego atrybutu w pliku styles.xml bez problemu .
  14. Jak widać na powyższym przykładowym kodzie, utworzyłem motyw potomny ze wspomnianego ThemeOverlay.AppCompat.Lighti zmieniłem android:textColorSecondaryatrybut.

https://i.imgur.com/LNfKdzC.png

mortalis
źródło
1

Rozwiązanie Sephy nie działa. Możliwe jest nadpisanie wyglądu tekstu pozycji menu opcji za pomocą metody opisanej powyżej, ale nie elementu lub menu. Aby to zrobić, istnieją zasadniczo 3 sposoby:

  1. Jak zmienić kolor tła menu opcji?
  2. Napisz swój własny widok, aby wyświetlić i zastąpić onCreateOptionsMenu i onPrepareOptionsMenu, aby uzyskać żądane wyniki. Podaję to ogólnie, ponieważ w tych metodach możesz ogólnie robić, co chcesz, ale prawdopodobnie nie będziesz chciał wywoływać funkcji super ().
  3. Skopiuj kod z pakietu SDK typu open source i dostosuj do swojego zachowania. Domyślna implementacja menu używana przez działanie nie będzie już obowiązywać.

Więcej wskazówek można znaleźć w numerze 4441: Motyw menu opcji niestandardowych .

Wytrwały
źródło
Powtórzę ... Rozwiązanie Sephy działa dla pozycji menu TextAppearance, chociaż to, co zrobiłem, to nadpisanie wartości domyślnej za pomocą pliku themes.xml. Ponadto, # 2 lub # 3 powyżej powinni być świadomi, że wywołanie super # onCreateOptionsMenu / super # onPrepareOptionsMenu jest zaprojektowane do umieszczania elementów menu systemowego ... jak wskazano w javadoc dla Activity # onCreateOptionsMenu (). To może / nie ma znaczenia dla Twojej aplikacji.
Wytrwały
To, co opisuje Sephy, to mieć to w pliku themes.xml: <item name = "android: itemTextAppearance"> @ style / Text_MenuItemText </item> Następnie zdefiniuj coś takiego w swoim styles.xml: <style name = "Text_MenuItemText" > <item name = "android: textSize"> 12dp </item> <item name = "android: textColor"> # FFFFFF </item> </style> To takie proste, jak to tylko możliwe. Czy to miałeś na myśli? Głębsze dostosowywanie menu opcji nie jest wcale łatwe, ale zamierzam wkrótce opublikować artykuł na ten temat na blogu.
Wytrwały
1

wypróbuj ten kod ....

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.my_menu, menu);

        getLayoutInflater().setFactory(new Factory() {
            @Override
            public View onCreateView(String name, Context context,
                    AttributeSet attrs) {

                if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {
                    try {
                        LayoutInflater f = getLayoutInflater();
                        final View view = f.createView(name, null, attrs);

                        new Handler().post(new Runnable() {
                            public void run() {

                                // set the background drawable
                                 view.setBackgroundResource(R.drawable.my_ac_menu_background);

                                // set the text color
                                ((TextView) view).setTextColor(Color.WHITE);
                            }
                        });
                        return view;
                    } catch (InflateException e) {
                    } catch (ClassNotFoundException e) {
                    }
                }
                return null;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }
Anoop
źródło
1
na Androidzie> 4.0 dostaję sięjava.lang.IllegalStateException: A factory has already been set on this LayoutInflater
do Kra
1

Jeśli chcesz ustawić kolor dla pojedynczego elementu menu, dostosowywanie motywu paska narzędzi nie jest właściwym rozwiązaniem. Aby to osiągnąć, możesz skorzystać z android: actionLayout i widoku akcji dla elementu menu.

Najpierw utwórz plik układu XML dla widoku akcji. W tym przykładzie używamy przycisku jako widoku akcji:

menu_button.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/menuButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Done"
        android:textColor="?android:attr/colorAccent"
        style="?android:attr/buttonBarButtonStyle"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

W powyższym fragmencie kodu używamy android:textColor="?android:attr/colorAccent"do dostosowania koloru tekstu przycisku.

Następnie w pliku układu XML dla menu umieść, app:actionLayout="@layout/menu_button"jak pokazano poniżej:

main_menu.xml

<?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/menuItem"
        android:title=""
        app:actionLayout="@layout/menu_button"
        app:showAsAction="always"/>
</menu>

Ostatnia zmiana onCreateOptionsMenu()metody w swoim działaniu:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu, menu);
    MenuItem item = menu.findItem(R.id.menuItem);
    Button saveButton = item.getActionView().findViewById(R.id.menuButton);
    saveButton.setOnClickListener(view -> {
        // Do something
    });
    return true;
}

... lub fragment:

@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater){
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem item = menu.findItem(R.id.menuItem);
    Button saveButton = item.getActionView().findViewById(R.id.menuButton);
    button.setOnClickListener(view -> {
        // Do something
    });
}

Więcej informacji na temat widoków akcji można znaleźć w podręczniku programisty Androida .

Alexander Poleschuk
źródło
0

Oto jak można pokolorować konkretną pozycję menu kolorem, działa na wszystkich poziomach API:

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));
                                }
                            }
                        }
                    }
                });
            }
        }
    }
}

W ten sposób tracisz efekt selektora tła, więc oto kod do zastosowania niestandardowego selektora tła do wszystkich elementów podrzędnych pozycji menu.

public static void setToolbarMenuItemsBackgroundSelector(final Context context,
                                                         final Toolbar toolbar) {
    if (toolbar != null) {
        for (int i = 0; i < toolbar.getChildCount(); i++) {
            final View view = toolbar.getChildAt(i);
            if (view instanceof ImageButton) {
                // left toolbar icon (navigation, hamburger, ...)
                UiHelper.setViewBackgroundSelector(context, view);
            } else 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) {
                                // text item views
                                final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
                                UiHelper.setViewBackgroundSelector(context, itemView);

                                // icon item views
                                for (int k = 0; k < itemView.getCompoundDrawables().length; k++) {
                                    if (itemView.getCompoundDrawables()[k] != null) {
                                        UiHelper.setViewBackgroundSelector(context, itemView);
                                    }
                                }
                            }
                        }
                    }
                });
            }
        }
    }
}

Oto również funkcja pomocnicza:

public static void setViewBackgroundSelector(@NonNull Context context, @NonNull View itemView) {
    int[] attrs = new int[]{R.attr.selectableItemBackgroundBorderless};
    TypedArray ta = context.obtainStyledAttributes(attrs);
    Drawable drawable = ta.getDrawable(0);
    ta.recycle();

    ViewCompat.setBackground(itemView, drawable);
}
pudełko
źródło
0

Aby zmienić kolor tekstu, możesz po prostu ustawić widok niestandardowy dla MenuItem, a następnie zdefiniować kolor tekstu.

Przykładowy kod: MenuItem.setActionView ()

wolny czas
źródło
Chociaż ten fragment kodu może rozwiązać problem, dołączenie wyjaśnienia naprawdę pomaga poprawić jakość Twojego posta. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a osoby te mogą nie znać powodów, dla których zaproponowałeś kod.
Mischa