4

我想要实现的是禁用 ActionBar 上的所有项目,除了一个。我有一个来自 ListNavigationActionBarMenu、几个TextViews、一个Button和一个的自定义。SpinnerSpinner 是因为bar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);这样创建的:

    SpinnerAdapter spinnerAdapter = new ArrayAdapter<String>(this.getActivity(), R.layout.action_bar_spinner, names);
    // "listener" for spinner
    bar.setListNavigationCallbacks(spinnerAdapter, new OnNavigationListener() {
        @Override
        public boolean onNavigationItemSelected(int position, long itemId) {
            // do some stuff

            return true;
        }
    });

我想禁用Spinner, 使其处于非活动状态,但在禁用它之前选择最后一个项目仍然可见。简而言之,bar.getNavigationSpinner.setEnabled(false)如果它存在,我需要类似的东西。问题是:是否有某种解决方法?如果没有,有没有办法禁用整个ActionBar,但保持可见?

注意:我想在片段中实现它。

4

3 回答 3

6

是的,可以禁用Spinner在列表导航中使用的ActionBar。但这不是一个简单的解决方案,而是一个 hack。ActionBar 不提供对Spinner视图的直接访问。不幸的Spinner是,它是在没有任何 id 的私有代码中创建的。

那么如何访问Spinner实例呢?一种解决方案是通过 Java 反射 API 访问它,但我不建议这样做。

更好的解决方案是获取Activity当前Spinner. 由于Spinnerin action bar大概是您自己没有创建的唯一一个,因此您应该能够将其与其他栏区分开来。

这个 SO questionView中描述了获取根目录。

遍历相当简单,请记住,如果您使用的是ActionBarSherlock,则必须寻找IcsSpinner而不是Spinner(IcsSpinner不扩展自Spinner)。

private View findActionBarSpinner() {
    View rootView = findViewById(android.R.id.content).getRootView();
    List<View> spinners = traverseViewChildren( (ViewGroup) rootView );
    return findListNavigationSpinner(spinners); // implement according to your layouts
}

private List<View> traverseViewChildren(ViewGroup parent) {
    List<View> spinners = new ArrayList<View>();
    for (int i = 0; i < parent.getChildCount(); i++) {
        View child = parent.getChildAt(i);
        if (child instanceof Spinner) {
            spinners.add( child );
        } else if (child instanceof IcsSpinner) { // add this if you are using ActionBarSherlock
            spinners.add( child );
        } else if (child instanceof ViewGroup) {
            spinners.addAll( traverseViewChildren( (ViewGroup) child ) );
        }
    }
    return spinners;
}

该功能findListNavigationSpinner应该以您能够区分其他微调器的方式实现。如果您不使用任何Spinner(或任何从它派生的视图),则返回的列表应仅包含一项。

上面的代码描述了如何SpinnerActivity. 当然,SpinnerFragment. 片段具有对其活动的引用,因此活动可以通过某些接口将代码公开给片段。

于 2012-11-12T23:45:06.997 回答
1

上面的代码不适用于Action Bar compat (v7 support library)。我需要使用此支持库启用/禁用我的应用程序(API 2.2)的操作栏微调器,但我注意到该类的名称SpinnerICS改为Spinner.

完整的包名是

android.support.v7.internal.widget.SpinnerICS

由于此类不可见且无法在我的代码中导入,因此无法使用:

if (child instanceof SpinnerICS) ...

所以最后我用getClass().getName. 因此,使用 Action Bar 兼容支持库 (v7) 启用/禁用微调器的代码将是:

private List<View> traverseViewChildren(ViewGroup parent) {
    List<View> spinners = new ArrayList<View>();
    for (int i = 0; i < parent.getChildCount(); i++) {
        View child = parent.getChildAt(i);

        String className = child.getClass().getName();
        if (child instanceof Spinner || className.equals("android.support.v7.internal.widget.SpinnerICS")) {
            spinners.add( child );
        } else if (child instanceof ViewGroup) {
            spinners.addAll( traverseViewChildren( (ViewGroup) child ) );
        }
    }
    return spinners;
}

另外,我修改了我的 findListNavigationSpinner 方法来检查微调器列表是否有要阻止的元素ArrayIndexOutOfBoundsException。因为我的应用程序中只有一个微调器(在操作栏兼容中),所以我的代码是这样的(如果你有多个微调器,你应该调整它):

private View findListNavigationSpinner(List<View> spinners) {
    // We only have one spinner in the app
    View result = null;
    if (spinners != null && spinners.size() > 0) {
         result = spinners.get(0);
    }
    return result;
}
于 2013-10-31T10:25:44.247 回答
1

这可以通过注意 ActionBar(和 Spinner)位于根视图和内容(id == android.R.id.content)之间来简化。因此,您可以实现广度优先搜索并返回您找到的第一个 Spinner,一旦您点击 id == android.R.id.content 的视图,就不再添加到队列中。

或者进行深度优先搜索,但是当您使用 id == android.R.id.content 访问视图时停止递归,因为 Spinner 不包含在其中。

所以不需要维护任何列表,只需返回找到的第一个 Spinner。

于 2015-07-08T02:56:29.400 回答