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.


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>

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.


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

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"/>

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.


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

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


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

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>

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)

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!


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



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.


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


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>

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".


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

        }
    });
}

3

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

<item name="android:textColorPrimary">?android:attr/textColorPrimaryInverse</item>

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


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

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


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 .


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

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 .


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

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 ()


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.