How to get ActionBar view?
Asked Answered
H

6

31

I'm using the Showcase library to explain my application feature to the user. In some point I need to dim the whole ActionBar to present another feature to the user.

For that I'm using the setAlpha(float num) of the View class. And so for doing that I need to get the actual view instance of my ActionBar

By the way, I'm using the support-7-appcompat library that gives ActionBar support for older systems.

Update

In the meantime I found this option, if you configure a custom view and add it to you ActionBar using:

getSupportActionBar().setCustomView(v);

Then to get the View of the ActionBar you could do:

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

Is there a simpler or easier way to do that?

Hemihedral answered 16/11, 2013 at 20:27 Comment(0)
G
49

Yep. You can actually get the view by using this function:

public View getActionBarView() {
    Window window = getWindow();
    View v = window.getDecorView();
    int resId = getResources().getIdentifier("action_bar_container", "id", "android");
    return v.findViewById(resId);
}

Pretty much the way this works is that the actionbar container uses the id android.R.id.action_bar_container, but this id is not public. Therefore we use getIdentifier() to retrieve this id and then the rest is simple.

Glyn answered 14/1, 2014 at 22:45 Comment(8)
What if I'm using actionbarsherlock?Bee
@ThuyTrinh i think its abs__action_bar_containerfor actionbarsherlockSheehan
@ThuyTrinh you can check my extended answerSheehan
Doesn't work in Android 2.3 with ActionBar Compat, but works with getPackageName() instead of "android".Lietuva
On support-library-v7-r21.0.3 using ActionBarActivity and Theme.Appcompat, v.findViewById(resId) returns null. resId is valid though. Any suggestion.Neutralize
I don't know what's the need to get the decor view when activity.findViewById will do the whole wrap!!!Sheehan
Can this be referenced directly in xml? For example, if I want another widget (eg a listView) to align to the bottom of the actionBar when I have made the actionBar float on top of the contents like this (#13726714)?Blastoff
I find the ActionBarContainer view, but the LongClickListener doesn't work on API 24, any ideas??Hassler
N
8

I think this solution is more complete, handling both normal Activity and ActionBarActivity.

It also handles the case that the actionbar was set using a toolbar, but you need to implement it in the activity you've created:

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();
}
Nic answered 8/12, 2014 at 8:38 Comment(2)
there is no need to use final View v = window.getDecorView();, you can use activity.findViewById instead.Sheehan
@MoshErsan Seems correct. maybe I've got it from somewhere else.Nic
B
6

for support.v7 getActionBarView(ById) doesn't work.

this returns actionBar Toolbar :

@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;
}
Balboa answered 29/4, 2016 at 16:13 Comment(2)
Welcome to Stack Overflow! While this code may answer the question, it would be better to include some context, explaining how it works and when to use it. Code-only answers are not useful in the long run.Hush
Good solution to achieve Toolbar instance.Nador
S
5

I made a little fix on @idunnololz code to support 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;
}
Sheehan answered 10/5, 2014 at 3:29 Comment(8)
It returns null if I use action_bar_container though I'm using ActionBarActivity from appcompat-v7 (r21.0.3). I checked and found actionViewResId returns positive value.Neutralize
I don't think there is a need for this code anymore, because you already have access to the actionbar view from the toolbar view.Sheehan
I actually need to add a max line at ActionBar Title TextView but this.findViewById(actionViewResId) returns null. I even used getWindow().getDecorView() instead of this and action_bar_title with no luck, though in both case actionViewResId returns a value. Could you suggest me how do I get that. EDIT Sorry I didn't use ToolBarNeutralize
let me check google code, maybe they are using different identifier for the actionbar view now.Sheehan
I think the best solution for that is using Toolbar and customise the title of it, since the actionbar new layout doesn't have id's .Sheehan
Thanks, but I wonder how gen/R.class gets action_bar_title and other related ids.Neutralize
toolbar definitely some solution, but I'm wanting to achieve some small change to layout and don't want to integrate new toolbar from beginning, any update on this?Excoriate
could you try with this id : R.id.action_bar ??Sheehan
H
3

This will get the Toolbar/ActionBar when using the native ActionBar, your own Toolbar from appcompat, or the native Toolbar on Lollipop:

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;
}
Hackamore answered 13/5, 2015 at 7:57 Comment(0)
D
0

My activity extends AppCompatActivity

Following works:

findViewById(R.id.action_bar)

Diagraph answered 19/10, 2022 at 11:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.