如何获取ActionBar视图?

31
我正在使用Showcase库向用户介绍我的应用程序特性。在某些情况下,我需要将整个ActionBar变暗以向用户展示另一个特性。
为此,我使用了View类的setAlpha(float num)方法。因此,我需要获取我的ActionBar的实际视图实例来完成此操作。
顺便说一句,我正在使用支持旧系统的support-7-appcompat库提供的ActionBar支持。

更新

与此同时,我找到了这个选项:如果你配置了一个自定义视图并将其添加到ActionBar中,可以使用以下代码:
getSupportActionBar().setCustomView(v);

要获取 ActionBarView,您可以执行以下操作:

(View) activity.getSupportActionBar().getCustomView().getParent().getParent()

有没有更简单或更容易的方式来做到这一点?

6个回答

49

没错。你可以使用这个函数来获取视图:

public View getActionBarView() {
    Window window = getWindow();
    View v = window.getDecorView();
    int resId = getResources().getIdentifier("action_bar_container", "id", "android");
    return v.findViewById(resId);
}
基本上这个工作的方式是,ActionBar容器使用ID android.R.id.action_bar_container,但该ID不是公共的。因此,我们使用getIdentifier()方法检索此ID,然后其余部分就很简单了。

大致上它的工作原理是,Actionbar容器使用id android.R.id.action_bar_container,但该id并不是公开的。因此,我们使用getIdentifier()方法来检索此id,剩下的就比较简单了。


2
如果我正在使用actionbarsherlock呢? - Thuy Trinh
2
@ThuyTrinh 我认为它是abs__action_bar_container用于ActionBarSherlock。 - Mohammad Ersan
@ThuyTrinh 你可以查看我的扩展答案。 - Mohammad Ersan
6
在Android 2.3中使用ActionBar Compat无法工作,但使用getPackageName()替代“android”可以解决这个问题。 - Philio
6
在使用ActionBarActivityTheme.Appcompatsupport-library-v7-r21.0.3版本中,v.findViewById(resId)返回了null,但resId是有效的。有什么建议吗? - IronBlossom
显示剩余3条评论

8
我认为这个解决方案更加完整,可以处理普通的Activity和ActionBarActivity两种情况。同时,它也能应对使用工具栏设置的动作栏的情况,但你需要在创建的活动中实现它:
public static View getActionBarView(final Activity activity) {
    if (activity instanceof IToolbarHolder)
        return ((IToolbarHolder) activity).getToolbar();
    final String packageName = activity instanceof ActionBarActivity ? activity.getPackageName() : "android";
    final int resId = activity.getResources().getIdentifier("action_bar_container", "id", packageName);
    final View view = activity.findViewById(resId);
    return view;
}

public interface IToolbarHolder {
    public android.support.v7.widget.Toolbar getToolbar();
}

你可以使用 activity.findViewById 替代 final View v = window.getDecorView();,无需使用前者。 - Mohammad Ersan
@MoshErsan 看起来没问题。也许我从别处得到了它。 - android developer

6

对于support.v7,getActionBarView(ById)不起作用。

这将返回actionBar工具栏:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ViewGroup actionBar = getActionBar(getWindow().getDecorView());
    TextView actionBarTitle = (TextView) actionBar.getChildAt(0);
}

public ViewGroup getActionBar(View view) {
    try {
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;

            if (viewGroup instanceof android.support.v7.widget.Toolbar) {
                return viewGroup;
            }

            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                ViewGroup actionBar = getActionBar(viewGroup.getChildAt(i));

                if (actionBar != null) {
                    return actionBar;
                }
            }
        }
    } catch (Exception e) {
    }

    return null;
}

欢迎来到Stack Overflow!虽然这段代码可能回答了问题,但最好还是包含一些上下文,解释它的工作原理以及何时使用它。仅有代码的答案从长远来看并不实用。 - Benjamin W.
实现Toolbar实例的好方法。 - User

5
我在@idunnololz的代码中做了一点修正,以支持ActionBarSherlock。
private View getActionBarView() {

    int actionViewResId = 0;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        actionViewResId = getResources().getIdentifier(
                "abs__action_bar_container", "id", getPackageName());
    } else {
        actionViewResId = Resources.getSystem().getIdentifier(
                "action_bar_container", "id", "android");
    }
    if (actionViewResId > 0) {
        return this.findViewById(actionViewResId);
    }

    return null;
}

我认为这段代码已经不再需要了,因为您已经可以从工具栏视图访问操作栏视图。 - Mohammad Ersan
让我检查一下Google Code,也许他们现在正在使用不同的标识符来表示ActionBar视图。 - Mohammad Ersan
我认为最好的解决方案是使用工具栏并自定义其标题,因为动作栏新布局没有id。 - Mohammad Ersan
谢谢,但我想知道 gen/R.class 是如何获取 action_bar_title 和其他相关 ID 的。 - IronBlossom
你可以尝试使用这个 id: R.id.action_bar 吗? - Mohammad Ersan
显示剩余3条评论

3

使用本地的ActionBar、appcompat的自定义Toolbar或Lollipop的本地Toolbar,可以获取Toolbar/ActionBar

public static ViewGroup findActionBar(Activity activity) {
    int id = activity.getResources().getIdentifier("action_bar", "id", "android");
    ViewGroup actionBar = null;
    if (id != 0) {
        actionBar = (ViewGroup) activity.findViewById(id);
    }
    if (actionBar == null) {
        actionBar = findToolbar((ViewGroup) activity.findViewById(android.R.id.content)
                .getRootView());
    }
    return actionBar;
}

private static ViewGroup findToolbar(ViewGroup viewGroup) {
    ViewGroup toolbar = null;
    for (int i = 0, len = viewGroup.getChildCount(); i < len; i++) {
        View view = viewGroup.getChildAt(i);
        if (view.getClass().getName().equals("android.support.v7.widget.Toolbar")
                || view.getClass().getName().equals("android.widget.Toolbar")) {
            toolbar = (ViewGroup) view;
        } else if (view instanceof ViewGroup) {
            toolbar = findToolbar((ViewGroup) view);
        }
        if (toolbar != null) {
            break;
        }
    }
    return toolbar;
}

0

我的活动扩展了AppCompatActivity

以下工作正常:

findViewById(R.id.action_bar)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接