我想要一个单选列表作为操作栏的下拉列表。由于ActionProvider
支持开箱即用的子菜单,我认为这很容易。但是,虽然我可以在一开始就更改选中项目的内容(例如,在onPrepareSubMenu()
中),但是在显示子菜单后,我无法更改选中项目的内容。致setChecked()
的电话没有视觉效果。
这是我的ActionProvider
:
/***
Copyright (c) 2016 CommonsWare, LLC
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
by applicable law or agreed to in writing, software distributed under the
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
From _The Busy Coder's Guide to Android Development_
https://commonsware.com/Android
*/
package com.commonsware.android.hurl;
import android.content.Context;
import android.view.ActionProvider;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
import java.util.ArrayList;
public class SingleChoiceActionProvider extends ActionProvider implements
OnMenuItemClickListener {
static final private int[] HTTP_STACKS_ITEM_IDS={
R.id.hurl,
R.id.httpclient,
R.id.httpclient_tor};
final private MenuInflater inflater;
final private ArrayList<MenuItem> httpStacksItems=
new ArrayList<MenuItem>();
public SingleChoiceActionProvider(Context ctxt) {
super(ctxt);
this.inflater=new MenuInflater(ctxt);
}
@Override
public View onCreateActionView() {
return(null);
}
@Override
public boolean hasSubMenu() {
return(true);
}
@Override
public void onPrepareSubMenu(SubMenu submenu) {
submenu.clear();
httpStacksItems.clear();
inflater.inflate(R.menu.http_stacks, submenu);
submenu.setGroupCheckable(R.id.http_stacks, true, true);
for (int itemId : HTTP_STACKS_ITEM_IDS) {
MenuItem item=submenu.findItem(itemId);
httpStacksItems.add(item);
item.setOnMenuItemClickListener(this);
}
}
@Override
public boolean onMenuItemClick(MenuItem item) {
/*
for (MenuItem httpStackItem : httpStacksItems) {
httpStackItem.setChecked(item==httpStackItem);
}
*/
httpStacksItems.get(2).setChecked(true);
return(true);
}
}
我可以毫无问题地控制onMenuItemClick()
。但是,对setChecked()
的调用没有明显的效果 - 无论在检查之前检查了什么项目。我从检查的第一个项目开始:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:id="@+id/http_stacks"
android:checkableBehavior="single">
<item
android:id="@+id/hurl"
android:checkable="true"
android:checked="true"
android:title="@string/menu_hurl"/>
<item
android:id="@+id/httpclient"
android:checkable="true"
android:title="@string/menu_httpclient"/>
<item
android:id="@+id/httpclient_tor"
android:checkable="true"
android:title="@string/menu_httpclient_tor"/>
</group>
</menu>
第一项显示已检查。理论上,在get(2)
给出我的硬编码黑客后,点击之后的任何项目都应该导致第三个(onMenuItemClick()
)被检查。检查isChecked()
的值表示我的更改已被MenuItem
识别。它只是没有改变屏幕上的内容。请注意,在setChecked()
中调用onPrepareSubMenu()
可以正常工作,因此问题仅限于显示菜单后。
知道我哪里错了吗?
或者,是否有其他工作模式可以从操作栏实现这种单选下拉菜单?
答案 0 :(得分:2)
The problem is that onPrepareSubMenu()
is called each time the sub menu is displayed. Setting the checked item is working correctly in the onMenuItemClick
method but the next time the menu is shown the layout is reinflated in onPrepareSubMenu
so the default item is once again selected.
Also, I think you can get similar results without needing a custom ActionProvider
by just inflating an item that has a nested menu like so:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/http_stack"
android:showAsAction="ifRoom"
android:title="HTTP Stack">
<menu>
<group
android:id="@+id/http_stacks"
android:checkableBehavior="single">
<item
android:id="@+id/hurl"
android:checkable="true"
android:checked="true"
android:title="@string/menu_hurl"/>
<item
android:id="@+id/httpclient"
android:checkable="true"
android:title="@string/menu_httpclient"/>
<item
android:id="@+id/httpclient_tor"
android:checkable="true"
android:title="@string/menu_httpclient_tor"/>
</group>
</menu>
</item>
</menu>