Es gibt eine Frage zur gleichen Funktionalität auf Blackberry, und ein paar verschiedene Threads haben sich darauf bezogen Insekt (das, soweit ich das beurteilen kann, ohne Auflösung geschlossen wurde), aber ich habe keine speziell für Android gefunden.
Ich rufe an setEnabled(false)
auf bestimmten MenuItems basierend auf einem bestimmten Zustand, aber sie sehen visuell gleich aus. Ich möchte, dass sie irgendwie versetzt werden, damit der Benutzer weiß, dass die Option derzeit nicht verfügbar ist. Gibt es eine Möglichkeit, dies zu tun?
Auf allen Android-Versionen können Sie dies am einfachsten verwenden, um ein Menüaktionssymbol als deaktiviert ANZUZEIGEN UND es auch als deaktiviert zu FUNKTIONIEREN:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.menu_my_item);
if (myItemShouldBeEnabled) {
item.setEnabled(true);
item.getIcon().setAlpha(255);
} else {
// disabled
item.setEnabled(false);
item.getIcon().setAlpha(130);
}
}
Ich hatte das gleiche Problem. Es gibt zwei Möglichkeiten, dies zum Laufen zu bringen:
- Platzieren Sie Ihre Symbole in einer StateList, sodass beim Deaktivieren ein anderes Symbol verwendet wird
-
Was ich jetzt benutze. Ändern Sie das Symbol selbst mit so etwas in onPrepareOptionsMenu()
:
public boolean onPrepareOptionsMenu(Menu menu) {
boolean menusEnabled = reachedEndOfSlidehow(); // enable or disable?
MenuItem item = menu.findItem(R.id.menu_next_slide);
Drawable resIcon = getResources().getDrawable(R.drawable.ic_next_slide);
if (!menusEnabled)
resIcon.mutate().setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN);
item.setEnabled(menusEnabled); // any text will be automatically disabled
item.setIcon(resIcon);
}
Du kannst anrufen invalidateOptionsMenu()
(oder aus ABS, supportInvalidateOptionsMenu()
), um das Menü neu zu erstellen.
BEARBEITEN: Aktualisierte Lösung 2
Quelle: https://groups.google.com/forum/?fromgroups#!topic/actionbarsherlock/Z8Ic8djq-3o
Ich habe einen neuen Weg gefunden, um dieses Problem mit einer XML-Datei mit einem zeichbaren Selektor zu lösen. Sie erstellen einfach einen Selektor mit dem Symbol, das Sie in Ihrem Menüpunkt verwenden möchten, dann können Sie entweder den Farbton, Alpha oder beides der Bitmap ändern:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<bitmap android:src="https://stackoverflow.com/questions/9642990/@drawable/ic_menu_item"
android:tint="@color/enabled_color"
android:alpha="@integer/enabled_alpha"/>
</item>
<item android:state_enabled="false">
<bitmap android:src="https://stackoverflow.com/questions/9642990/@drawable/ic_menu_item"
android:tint="@color/disabled_color"
android:alpha="@integer/disabled_alpha"/>
</item>
</selector>
Als Anmerkung; Ich stelle die Tönung gerne auf ein "?android:attr/textColorPrimary"
für aktivierten Zustand und "?android:attr/textColorHint"
für behinderten Zustand. Auf diese Weise wird es je nach verwendetem Thema angepasst.
Dann können Sie einfach das Symbol in Ihrer Menü-XML-Datei auf die Auswahlressource setzen:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_action"
android:orderInCategory="0"
android:title="@string/title_menu_action"
android:icon="@drawable/ic_menu_item_selector"
app:showAsAction="ifRoom"/>
</menu>
Dann, wenn Sie anrufen item.setEnabled(enabled)
die Farbe und/oder Alpha des Symbols ändert sich zusammen mit dem Zustand!
Die Art und Weise, wie ich es gemacht habe, ist die Verwendung von “itemIconTint” in NavigationView, Sie können den Text auch ausgrauen, indem Sie “itemTextColor” verwenden.
Dies ist die Navigationsansicht:
<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:itemBackground="@color/white"
android:background="@color/white"
app:itemTextColor="@color/menu_text_color"
app:itemIconTint="@color/menu_text_color"
app:menu="@menu/main_drawer" />
und “@color/menu_text_color” ist ein Selektor:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="@color/primaryColor" />
<item android:state_enabled="false" android:color="@color/disabled_text_color" />
<item android:color="@color/primaryText" />
</selector>
Wenn Sie schließlich einen Menüpunkt deaktivieren möchten,
MenuItem item = mNavigationView.getMenu().findItem(R.id.your_menu_item);
item.setEnabled(isEnable);
Fertig!
Ich hatte ein Problem, bei dem sich weder mein Text noch das Symbol sichtbar änderten. Die anderen Antworten haben bei mir entweder nicht funktioniert oder waren nicht sehr elegant. Hier ist eine Antwort, die für die neuesten funktioniert Materialempfehlungen.
Du sollte einfach anrufen können menu.findItem(R.id.menu_my_item).isEnabled = false
in onPrepareOptionsMenu(menu: Menu)
.
(Wenn Sie brauchen onPrepareOptionsMenu
um wieder zu laufen, kannst du einfach anrufen invalidateOptionsMenu()
oder activity?.invalidateOptionsMenu()
(aus einem Fragment) und die Anwendung stellt das neu zu erstellende Menü in die Warteschlange. Alternativ können Sie das Menüelement in einer Mitgliedsvariablen speichern, um es später zu ändern, aber achten Sie darauf, Ihre Referenz darauf zu zerstören onDestroyOptionsMenu
um ein Speicherleck zu vermeiden.)
Die Tatsache, dass der Menüpunkt deaktiviert ist sollte ausreichen, um den Text oder das Symbol automatisch auszugrauen. Die Schwierigkeit besteht darin, Ihre Stile so einzurichten, dass dies funktioniert.
Kurze Antwort
Erstellen Sie zunächst eine Farbzustandsliste my_color_state_list.xml
die Sie für Ihre Symbole und Ihren Text verwenden möchten (z. B. schwarz, wenn aktiviert, grau, wenn deaktiviert). (Ein Beispiel finden Sie in der vollständigen Antwort.)
Wenn Sie verwenden com.google.android.material.appbar.MaterialToolbar
, können Sie ihm mitteilen, dass dieser Selektor für Symbole und Text verwendet werden soll, indem Sie ein benutzerdefiniertes Design-Overlay bereitstellen. Weisen Sie der Symbolleiste im XML-Code Ihrer Aktivität das Attribut zu android:theme="@style/Foo"
und definiere diesen Stil irgendwo als:
<style name="Foo">
<item name="colorControlNormal">@color/my_color_state_list</item>
<item name="actionMenuTextColor">@color/my_color_state_list</item>
</style>
Jetzt, wenn der Menüpunkt aktiviert oder deaktiviert ist über menu.findItem(R.id.menu_my_item).isEnabled = false
Der Text ändert automatisch die Farbe und alle Symbole, die diese Farbe verwenden ?attr/colorControlNormal
ändert auch automatisch die Farbe.
Vollständige Antwort
Mein Startplatz
Meine Menüpunkte sind Teil einer Materialsymbolleiste. Diese Antwort kann für andere Arten von Symbolleisten/App-Leisten hilfreich sein, aber Ihre Laufleistung kann variieren. In meiner Tätigkeit habe ich so etwas:
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.MaterialComponents.Toolbar.Surface"/>
und das Thema, das ich verwende, sieht in etwa so aus:
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">@color/blue</item>
<item name="colorSecondary">@color/green</item>
<item name="colorSurface">@color/lightGrey</item>
<item name="colorOnSurface">@color/black</item>
[...]
<item name="windowActionModeOverlay">true</item>
</style>
Es ist auch Konvention, dass das Symbol, das Sie in Schaltflächen und Menüelementen (und eigentlich überall) verwenden, ihre Standardfarbe haben sollte ?attr/colorControlNormal
. So könnte ich zum Beispiel ein Vektorbild haben, das so aussieht:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal"
android:tintMode="src_atop">
<path android:pathData="..." android:fillColor="@android:color/white"/>
</vector>
Wenn Sie ein Symbol von herunterladen Materielle Symbole Sie werden sehen, dass sie alle colorControlNormal verwenden.
Was ich tun musste
Wenn Sie sich die Definition meiner Symbolleiste ansehen, werden Sie sehen, dass sie ein ThemeOverlay verwendet ThemeOverlay.MaterialComponents.Toolbar.Surface
was definiert ist als:
<style name="ThemeOverlay.MaterialComponents.Toolbar.Surface" parent="">
<item name="colorControlNormal">@color/material_on_surface_emphasis_medium</item>
<item name="actionMenuTextColor">@color/material_on_surface_emphasis_medium</item>
</style>
Dies stellt die Textfarbe des Menüpunkts und die Symbolfarbe auf ein @color/material_on_surface_emphasis_medium
die nicht darauf reagiert, aktiviert zu werden oder nicht. @color/material_on_surface_emphasis_medium
sieht aus wie:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="@dimen/material_emphasis_medium" android:color="?attr/colorOnSurface"/>
</selector>
(Möglicherweise verwenden Sie ThemeOverlay.MaterialComponents.Toolbar.Primary
stattdessen, das ein ähnliches Problem hat – es verwendet einfach colorOnPrimary
.)
Wir müssen dies durch unsere eigene Farbzustandsliste ersetzen, die auf den aktivierten Zustand reagiert. Erstellen Sie also eine neue Datei res/color/menu_item_selector.xml
das sieht in etwa so aus:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:alpha="@dimen/material_emphasis_medium" android:color="?attr/colorOnSurface"/>
<item android:alpha="@dimen/material_emphasis_disabled" android:color="?attr/colorOnSurface"/>
</selector>
Wie Sie sehen, habe ich dieselben Konventionen verwendet wie die Materialbibliothek, indem ich ihre Konstanten zum Definieren der Alpha-Werte verwendet habe, und ich habe sie verwendet colorOnSurface
als meine Farbe. Wenn Sie verwendet haben ThemeOverlay.MaterialComponents.Toolbar.Primary
Du würdest wollen colorOnPrimary
stattdessen. Natürlich können Sie hier jede Farbe oder Alpha verwenden, es liegt an Ihnen.
Und jetzt machen Sie ein neues ThemeOverlay in res/values/styles.xml
um auf diesen Selektor zu zeigen, der von dem von Ihnen verwendeten ThemeOverlay erbt:
<!-- Toolbar - overrides the menu text color to use a selector that responds to whether it's enabled or not -->
<style name="ThemeOverlay.MyTheme.Toolbar" parent="ThemeOverlay.MaterialComponents.Toolbar.Surface">
<!-- Color used in the icons of menu actions (i.e. non-overflow menu items). This is just convention, this will affect anything that uses ?attr/colorControlNormal) -->
<item name="colorControlNormal">@color/menu_item_color_selector</item>
<!-- Color used in the text of menu actions (i.e. non-overflow menu items) -->
<item name="actionMenuTextColor">@color/menu_item_color_selector</item>
</style>
Und jetzt können wir das endlich anwenden ThemeOverlay
zur Symbolleiste:
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.MyTheme.Toolbar"/>
Ich hatte Schwierigkeiten damit auf einem modernen Android mit MaterialComponents-Design. Mein Problem war, dass ich eingestellt hatte <item name="actionMenuTextColor">@color/blue</item>
in styles.xml
und dies überschreibt die Textfarbe, unabhängig davon, ob das Element aktiviert oder deaktiviert ist. Die Lösung besteht darin, a einzustellen Farbzustandsliste und nicht direkt eine Farbe.
Mein Styles-Attribut sieht jetzt so aus:
<item name="actionMenuTextColor">@color/menu_color_selector</item>