Android MenuItem';s的选中状态未通过其图标正确显示
我对MenuItem的定义如下:Android MenuItem';s的选中状态未通过其图标正确显示,android,menu,menuitem,android-actionbar,Android,Menu,Menuitem,Android Actionbar,我对MenuItem的定义如下: <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_starred" android:icon="@drawable/btn_star" android:title="@string
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_starred"
android:icon="@drawable/btn_star"
android:title="@string/description_star"
android:checkable="true"
android:checked="true"
android:orderInCategory="1"
android:showAsAction="always" />
</menu>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_checked="false"
android:drawable="@drawable/btn_star_off_normal" />
<item
android:state_checked="true"
android:drawable="@drawable/btn_star_on_normal" />
</selector>
但是,当我使用此选项创建选项菜单时,即使MenuItem
的isChecked()
我正在使用控件,但是,如果我只是创建一个普通选项菜单并调用setChecked(true)
,我会得到相同的结果。无论项目的选中状态如何,它仍然显示可绘制的btn\u star\u off
正在正确调用OnOptions ItemSelected()
方法,并且我可以成功更改checked属性:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.isCheckable()) {
item.setChecked(!item.isChecked());
}
return super.onOptionsItemSelected(item);
}
在此处设置断点会显示正在更改的isChecked属性,但图标本身不会更新以反映正确的状态
这里有我遗漏的东西吗?我做得不对吗?我不明白为什么这不能正常工作。根据
注意:图标菜单(从选项菜单)中的菜单项不能
显示复选框或单选按钮。如果您选择在
图标菜单可检查,您必须通过
每次状态更改时交换图标和/或文本。
希望它能有所帮助。如果您仍然希望在xml可绘制文件中定义行为(选中,未选中),这是一种可以实现这一点的方法:
if (item.getItemId()==R.id.menu_item){
item.setChecked(!item.isChecked());
StateListDrawable stateListDrawable = (StateListDrawable) getResources().getDrawable(R.drawable.selector_drawable);
int[] state = {item.isChecked()?android.R.attr.state_checked:android.R.attr.state_empty};
stateListDrawable.setState(state);
item.setIcon(stateListDrawable.getCurrent());
}
一种更简单的方法(没有xml状态文件):
//在java中。。。
@凌驾
公共布尔值onOptionsItemSelected(菜单项项){
开关(item.getItemId()){
案例R.id.fav:
布尔值mState=!item.isChecked();
项目设置已检查(mState);
item.setIcon(mState?getResources().getDrawable(R.drawable.ic_favorite_black_selected):getResources().getDrawable(R.drawable.ic_favorite_black_UnSelected));
Toast.makeText(this,“+item.isChecked(),Toast.LENGTH_SHORT.show();
返回true;
案例R.id.share:
返回true;
}
返回super.onOptionsItemSelected(项目);
}
这个问题有点老了,但我最近偶然发现了这个问题
经过一些分析,结果表明菜单项的选中状态并没有被正确地传播到可绘图项。以下是我(在科特林)提出的解决方案
确保您的menuItem
正在使用可绘制的状态列表(如问题中的btn_star.xml
),然后创建一个可绘制的包装类:
/** Fixes checked state being ignored by injecting checked state directly into drawable */
class CheckDrawableWrapper(val menuItem: MenuItem) : DrawableWrapper(menuItem.icon) {
// inject checked state into drawable state set
override fun setState(stateSet: IntArray) = super.setState(
if (menuItem.isChecked) stateSet + android.R.attr.state_checked else stateSet
)
}
/** Wrap icon drawable with [CheckDrawableWrapper]. */
fun MenuItem.fixCheckStateOnIcon() = apply { icon = CheckDrawableWrapper(this) }
最后一步是将菜单项drawable替换为wrapped drawable:
override fun onCreateOptionsMenu(menu: Menu) : Boolean{
menuInflater.inflate(R.menu.menu_main, menu)
menu.findItem(R.id.menu_starred).fixCheckStateOnIcon()
/** ... */
return true
}
此后,当更改菜单项的选中状态时,您无需执行任何操作,图标应具有自我意识,并在选中状态更改时作出反应。啊,我不知道我怎么会错过这一点--我阅读了几次该文档。谢谢让我困惑的是,添加checkable=“true”
确实会在菜单项中添加一个复选框,而且这个警告似乎只适用于图标菜单中的菜单项,而不是所有菜单。谷歌为什么?为什么不能只使用绘图的state_checked?我发现同样的,出于某种原因,state_checked不适用于菜单图标什么是R.drawable.selector_drawable
?包含多个状态(聚焦、按下等)的xml绘图。在上面的示例中,它将是btn_star.xml
为什么变量configChecked
是必需的,因为每次单击checkboxDrawableWrapper类需要API级别时,都必须将其更改为相反的值23@A.Petrov我认为您可以使用androidx.appcompat.graphics.drawable.drawable包装器
,只需添加@SuppressLint(“RestrictedApi”)
在类的顶部。@SuppressLint
始终是一种糟糕的方法。目前,我最终得到了@Andrei Tudor Diaconu的解决方案,主要是:状态列表drawable可能包含许多状态(>2),但只有两个第一项状态受到影响,可以用于处理工具栏。MenuItem
我认为这是否总是一种糟糕的方法。我猜他们把受限注释放在那个类的顶部,因为它只是一个“粗糙的助手类”,而不是一个公开的api,但我认为忽略它没有问题,因为它只是一个简单的对包装对象的委托(你可以检查源)。>(你可以检查源)-这是关键。目前的消息来源。无法保证在Jetpack的进化过程中该API能够继续存在。
/** Fixes checked state being ignored by injecting checked state directly into drawable */
class CheckDrawableWrapper(val menuItem: MenuItem) : DrawableWrapper(menuItem.icon) {
// inject checked state into drawable state set
override fun setState(stateSet: IntArray) = super.setState(
if (menuItem.isChecked) stateSet + android.R.attr.state_checked else stateSet
)
}
/** Wrap icon drawable with [CheckDrawableWrapper]. */
fun MenuItem.fixCheckStateOnIcon() = apply { icon = CheckDrawableWrapper(this) }
override fun onCreateOptionsMenu(menu: Menu) : Boolean{
menuInflater.inflate(R.menu.menu_main, menu)
menu.findItem(R.id.menu_starred).fixCheckStateOnIcon()
/** ... */
return true
}