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?

halfer
  • 19,824
  • 17
  • 99
  • 186
Emil Adz
  • 40,709
  • 36
  • 140
  • 187

6 Answers6

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.

idunnololz
  • 8,058
  • 5
  • 30
  • 46
  • 2
    What if I'm using actionbarsherlock? – Thuy Trinh Mar 06 '14 at 07:24
  • 2
    @ThuyTrinh i think its `abs__action_bar_container`for actionbarsherlock – Mohammad Ersan May 08 '14 at 22:26
  • @ThuyTrinh you can check my extended answer – Mohammad Ersan May 10 '14 at 03:29
  • 6
    Doesn't work in Android 2.3 with ActionBar Compat, but works with getPackageName() instead of "android". – Philio Jul 15 '14 at 09:36
  • 6
    On `support-library-v7-r21.0.3` using `ActionBarActivity` and `Theme.Appcompat`, `v.findViewById(resId)` returns `null`. `resId` is valid though. Any suggestion. – IronBlossom Mar 03 '15 at 14:36
  • I don't know what's the need to get the decor view when activity.findViewById will do the whole wrap!!! – Mohammad Ersan Mar 05 '15 at 17:20
  • 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 (http://stackoverflow.com/questions/13726214/transparent-actionbar-custom-tabcolor)? – rockhammer Nov 29 '16 at 16:11
  • I find the ActionBarContainer view, but the LongClickListener doesn't work on API 24, any ideas?? – Tano Oct 23 '17 at 09:47
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();
}
android developer
  • 114,585
  • 152
  • 739
  • 1,270
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;
}
Rahmat Rezaei
  • 61
  • 2
  • 5
  • 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. – Benjamin W. Apr 29 '16 at 16:39
  • Good solution to achieve Toolbar instance. – User Aug 25 '16 at 09:46
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;
}
Mohammad Ersan
  • 12,304
  • 8
  • 54
  • 77
  • 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. – IronBlossom Mar 03 '15 at 11:05
  • 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. – Mohammad Ersan Mar 03 '15 at 11:07
  • 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 `ToolBar` – IronBlossom Mar 03 '15 at 11:11
  • let me check google code, maybe they are using different identifier for the actionbar view now. – Mohammad Ersan Mar 03 '15 at 11:12
  • 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 . – Mohammad Ersan Mar 03 '15 at 16:28
  • Thanks, but I wonder how `gen/R.class` gets `action_bar_title` and other related ids. – IronBlossom Mar 04 '15 at 07:11
  • 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? – cV2 Mar 05 '15 at 16:32
  • could you try with this id : R.id.action_bar ?? – Mohammad Ersan Mar 05 '15 at 17:16
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;
}
Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
0

My activity extends AppCompatActivity

Following works:

findViewById(R.id.action_bar)

Amit
  • 173
  • 7