我有这样定义的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/description_star"
android:checkable="true"
android:checked="true"
android:orderInCategory="1"
android:showAsAction="always" />
</menu>
和btn_star.xml
以这种方式定义:
<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
的{{1}}属性为true,图标也不会以其选中状态显示。
我正在使用ActionBarSherlock控件,但是,如果我只是创建一个普通的选项菜单并调用isChecked()
,我会得到相同的结果。无论项目的检查状态如何,它仍然显示setChecked(true)
drawable。
正确调用btn_star_off
方法,我可以成功更改checked属性:
onOptionsItemSelected()
此处设置断点显示isChecked属性已更改,但图标本身未更新以反映正确的状态。
这里有什么我想念的吗?我做错了吗?我无法弄清楚为什么这不能正常工作。
答案 0 :(得分:34)
根据http://developer.android.com/guide/topics/ui/menus.html
的官方文件注意:图标菜单中的菜单项(来自“选项”菜单)不能 显示复选框或单选按钮。如果你选择在中制作物品 图标菜单可选,您必须手动指示已选中状态 每次状态更改时交换图标和/或文本。
希望它有所帮助。
答案 1 :(得分:11)
如果您仍希望在xml drawable中定义行为(已选中,未选中),则可以通过以下方式实现此目的:
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());
}
答案 2 :(得分:5)
更简单的方法(没有xml-states文件):
configChecked = !configChecked;
item.setChecked(configChecked);
item.setIcon(configChecked ? R.drawable.check_on : R.drawable.check_off);
答案 3 :(得分:0)
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/fav"
android:title=""
app:showAsAction="ifRoom"
android:orderInCategory="1"
android:icon="@drawable/ic_favorite_black_unselectd"
android:checked="false" />
<item android:id="@+id/share"
android:title=""
app:showAsAction="ifRoom"
android:orderInCategory="2"
android:icon="@drawable/ic_share_black" />
</menu>
//and in java...
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.fav:
boolean mState = !item.isChecked();
item.setChecked(mState);
item.setIcon(mState ? getResources().getDrawable(R.drawable.ic_favorite_black_selected) : getResources().getDrawable(R.drawable.ic_favorite_black_unselectd));
Toast.makeText(this, "" + item.isChecked(), Toast.LENGTH_SHORT).show();
return true;
case R.id.share:
return true;
}
return super.onOptionsItemSelected(item);
}
答案 4 :(得分:0)
问题有点老了,但最近我偶然发现了这个问题。
经过一些分析,结果表明菜单项的选中状态未正确传播到可绘制对象。这是我想出的解决方案(在Kotlin中)。
确保您的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) }
最后一步是用可包装的可绘制对象替换可绘制菜单项目:
override fun onCreateOptionsMenu(menu: Menu) : Boolean{
menuInflater.inflate(R.menu.menu_main, menu)
menu.findItem(R.id.menu_starred).fixCheckStateOnIcon()
/** ... */
return true
}
此后,在更改菜单项的选中状态时,您无需执行任何操作,图标应具有自觉性,并在选中状态更改时做出反应。