如何创建单选ActionProvider下拉列表?

时间:2016-02-12 18:37:13

标签: android android-actionbar

我想要一个单选列表作为操作栏的下拉列表。由于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()可以正常工作,因此问题仅限于显示菜单后。

知道我哪里错了吗?

或者,是否有其他工作模式可以从操作栏实现这种单选下拉菜单?

1 个答案:

答案 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>
相关问题