有一个与此相同功能的问题 在Blackberry上,还有几个不同的帖子提到了这个bug(据我所知,这个bug已经被关闭而没有解决),但我没有找到Android特定的帖子。
基于某些状态,我正在调用setEnabled(false)
来禁用某些菜单项,但它们在视觉上看起来都一样。 我想以某种方式将它们偏移,以便用户知道当前选项不可用——有没有任何方法可以做到这一点?
有一个与此相同功能的问题 在Blackberry上,还有几个不同的帖子提到了这个bug(据我所知,这个bug已经被关闭而没有解决),但我没有找到Android特定的帖子。
基于某些状态,我正在调用setEnabled(false)
来禁用某些菜单项,但它们在视觉上看起来都一样。 我想以某种方式将它们偏移,以便用户知道当前选项不可用——有没有任何方法可以做到这一点?
@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);
}
}
我有同样的问题。有两种方法可以使其工作:
现在我使用的方法是,在 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);
}
你可以调用invalidateOptionsMenu()
(或者使用ABS的supportInvalidateOptionsMenu()
) 来重新构建菜单。
编辑: 更新解决方案2我发现了一种使用可绘制选择器XML文件解决这个问题的新方法。您只需创建一个选择器,其中包含您想在菜单项中使用的图标,然后您可以更改位图的色调、透明度或两者都更改:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<bitmap android:src="@drawable/ic_menu_item"
android:tint="@color/enabled_color"
android:alpha="@integer/enabled_alpha"/>
</item>
<item android:state_enabled="false">
<bitmap android:src="@drawable/ic_menu_item"
android:tint="@color/disabled_color"
android:alpha="@integer/disabled_alpha"/>
</item>
</selector>
作为一则旁注,我喜欢将着色设置为"?android:attr/textColorPrimary"
以启用状态,而在禁用状态下设置为"?android:attr/textColorHint"
。这样它就会根据使用的主题进行调整。
<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>
那么当您调用item.setEnabled(enabled)
时,图标的颜色和/或透明度将随状态改变而改变!
<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" />
"@color/menu_text_color"是一个选择器:
<?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>
MenuItem item = mNavigationView.getMenu().findItem(R.id.your_menu_item);
item.setEnabled(isEnable);
完成!
<item name="actionMenuTextColor">@color/blue</item>
,这会覆盖文本颜色,无论该项目是否启用或禁用。解决方法是设置一个颜色状态列表而不是直接设置颜色。<item name="actionMenuTextColor">@color/menu_color_selector</item>
actionMenuTextColor
对我没有任何影响(我将其设置为粉色,但无处可见)。如果仍然有人在使用 Material 组件时遇到问题,请查看我的答案 https://dev59.com/D2kw5IYBdhLWcg3wyNoW#66248473。 - Chrispher我曾经遇到这样的问题:文本和图标都无法在显示上明显改变。其他答案对我不起作用或者不够优雅。下面是一个可以解决最新Material recommendations的答案。
你可以简单地在onPrepareOptionsMenu(menu: Menu)
中调用menu.findItem(R.id.menu_my_item).isEnabled = false
。
如果你需要onPrepareOptionsMenu
再次运行,只需调用invalidateOptionsMenu()
或activity?.invalidateOptionsMenu()
(从片段中调用),应用程序将会将菜单排队以重新创建。或者你可以将菜单项存储在成员变量中,以便稍后修改它,但要小心在onDestroyOptionsMenu
中销毁对它的引用,以避免内存泄漏。
菜单项被禁用就足以自动使文本或图标变灰。困难在于设置样式使其工作。
首先创建一个颜色状态列表my_color_state_list.xml
,你希望你的图标和文本使用它(例如,启用时为黑色,禁用时为灰色)。(查看完整答案以获取示例。)
如果你正在使用com.google.android.material.appbar.MaterialToolbar
,你可以通过提供自定义主题叠加层来告诉它使用这个选择器来为图标和文本着色。在活动的XML中,给工具栏设置属性android:theme="@style/Foo"
,并在某个地方定义该样式:
<style name="Foo">
<item name="colorControlNormal">@color/my_color_state_list</item>
<item name="actionMenuTextColor">@color/my_color_state_list</item>
</style>
现在,当菜单项通过menu.findItem(R.id.menu_my_item).isEnabled = false
启用或禁用时,文本颜色将自动更改,使用颜色?attr/colorControlNormal
的任何图标也将自动更改颜色。
我的菜单项是 Material 工具栏的一部分。这个回答可能对其他类型的工具栏/应用栏有帮助,但效果可能会有所不同。在我的活动中,我有以下内容:
<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"/>
我正在使用的主题大致如下:
<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>
通常情况下,在按钮和菜单项(以及任何地方)使用的图标默认颜色应为?attr/colorControlNormal
。例如,我可能有一个矢量图像,看起来像这样:
<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>
ThemeOverlay.MaterialComponents.Toolbar.Surface
,它被定义为:<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>
这将菜单项的文本颜色和图标颜色设置为@color/material_on_surface_emphasis_medium
,它不受启用或禁用的影响。@color/material_on_surface_emphasis_medium
的外观如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="@dimen/material_emphasis_medium" android:color="?attr/colorOnSurface"/>
</selector>
您可能正在使用ThemeOverlay.MaterialComponents.Toolbar.Primary
,它存在类似的问题 - 它仅使用colorOnPrimary
。
我们需要使用自己的颜色状态列表来响应启用状态。 因此,请创建一个名为res/color/menu_item_selector.xml
的新文件,其内容类似于以下内容:
<?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>
你看,我使用了材料库使用的相同约定来定义alpha值,我使用colorOnSurface
作为我的颜色。如果您在使用ThemeOverlay.MaterialComponents.Toolbar.Primary
,则应改用colorOnPrimary
。当然,您可以在此处使用任何颜色或alpha值,这取决于您。
现在,在res/values/styles.xml
中创建一个指向此选择器的新的ThemeOverlay,继承您正在使用的任何ThemeOverlay:
<!-- 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>
现在我们可以将ThemeOverlay
应用于工具栏:
<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"/>
setEnabled(false)
在 API Level < 14
上运行良好,但在 14
上该项仍然可点击。
请查看此 链接
setEnabled
也可用于 MenuItems
。
fun changeMenuItemColour(enabled: Boolean) {
var menuItem = SpannableString(mCustomToolbar?.menu?.findItem(R.id.some_menu_item)?.title)
var style = activity?.resources?.getColor(R.color.darkGraphite)!!
if (enabled) style = activity?.resources?.getColor(R.color.black)!!
menuItem.setSpan(ForegroundColorSpan(style), 0, menuItem.length, 0)
}