19

我以这种方式定义了 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'isChecked()属性为 true,图标也不会显示为选中状态。

我正在使用ActionBarSherlock控件,但是,如果我只是创建一个普通的选项菜单并调用setChecked(true). btn_star_off无论项目的选中状态如何,它仍会显示可绘制对象。

onOptionsItemSelected()方法被正确调用,我可以成功更改选中的属性:

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.isCheckable()) {
            item.setChecked(!item.isChecked());
        }
        return super.onOptionsItemSelected(item);
}

在此处设置断点显示 isChecked 属性正在更改,但图标本身并未更新以反映正确的状态。

我在这里缺少什么吗?我做错了吗?我不知道为什么这不能正常工作。

4

5 回答 5

38

根据http://developer.android.com/guide/topics/ui/menus.html的官方文档

注意:图标菜单(来自选项菜单)中的菜单项不能显示复选框或单选按钮。如果您选择将图标菜单中的项目设为可选中,则必须在每次状态更改时通过交换图标和/或文本手动指示选中状态。

希望能帮助到你。

于 2011-08-18T10:42:19.820 回答
12

如果您仍然希望在 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());
}
于 2014-01-21T13:55:32.713 回答
6

更简单的方法(没有 xml-states 文件):

configChecked = !configChecked;
item.setChecked(configChecked);
item.setIcon(configChecked ? R.drawable.check_on : R.drawable.check_off);
于 2014-11-14T13:30:28.450 回答
3

问题有点老了,但我最近偶然发现了这个问题。

经过一些分析,结果发现菜单项的检查状态没有正确传播到可绘制对象。这是我想出的解决方案(在 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) }

最后一步是用包装的drawable替换菜单项drawable:

override fun onCreateOptionsMenu(menu: Menu) : Boolean{
    menuInflater.inflate(R.menu.menu_main, menu)
    menu.findItem(R.id.menu_starred).fixCheckStateOnIcon()
    /** ...  */
    return true
}

之后,在更改菜单项检查状态时您无需执行任何操作,图标应该具有自我意识,并在检查状态更改时做出反应。

于 2019-09-02T11:16:42.293 回答
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);
}
于 2019-05-20T05:48:01.927 回答