Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change actionbar to overlay from within Fragment

I have a fragment (Fragment 1) that is replaced by another fragment (Fragment 2). Fragment 1 is placed on the stack. I'm using compatibility mode (not ActionBarSherlock).

Here's my problem. I want the actionbar to be displayed as overlay in some fragments, but not in others. Specifically, when Fragment 2 is shown, I want it to appear in overlay and then go back to the normal actionbar once Fragment 2 exits.

Fragment 1 has an regular actionbar that is always visible. But, when I replace Fragment 1 with Fragment 2, I need to hide the actionbar after 5 seconds. If there is a touch event, the actionbar is shown again. This all works fine, but, Fragment 2 is redrawn each time the actionbar is hidden or revealed. Because of this, I want to make the actionbar in Fragment 2 show as an overlay.

I know I can change the actionbar overlay but I don't know how to do that programmatically from within the fragment. I DON'T want to change it for every fragment, just Fragment 2.

Ideas?????

like image 755
JustLearningAgain Avatar asked Jul 24 '14 22:07

JustLearningAgain


1 Answers

This may not be the answer you were hoping for.

Consider a different question: Can we change activity theme after setContentView(...) has been called? The question has been asked many times, and a common solution is to recreate(calling finish() and startActivity(getIntent())) the activity and set the new theme before setContentView(...).

Your question is an extension to this - with added complexity of changing the theme from a fragment. In any case, I don't consider the solution mentioned above a good one.

ActionBar is one of the first components to be initialized when an Activity is created. I don't think you will find a way to somehow 'refresh' it with new attributes. See below how the requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY) method deals with post-setContentView(...) calls:

@Override
public boolean requestFeature(int featureId) {
    if (mContentParent != null) {
        throw new AndroidRuntimeException("requestFeature() must be 
                                                       called before adding content");
    }
    ....
    ....
}

So, if setContentView(...) has already been called for the Activity (which it is, in your case), a runtime-exception will be thrown.

Is it possible that you don't even require this functionality?

Start by setting the ActionBar to be an overlay in your theme:

<item name="android:windowActionBarOverlay">true</item>
<!-- Support library attribute for compatibility -->
<item name="windowActionBarOverlay">true</item>

Here's my problem. I want the actionbar to be displayed as overlay in some fragments...

Okay. We have already provisioned for this above.

... but not in others.

Say you don't want to have the ActionBar as an overlay in Fragment B. Then, in Fragment B's layout, do the following:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="?android:attr/actionBarSize" >  <<<-- ?attr/actionBarSize
                                                                    for compatibility

    ....
    ....
</LinearLayout>

With the top-margin set to ActionBar's size, Fragment B looks as if it has a regular ActionBar - not an overlaid one. Another way to achieve this would be to have a View with android:layout_height="?android:attr/actionBarSize" placed as the first child in the layout above.

In essence:

  • your ActionBar will be an overlay.
  • in the fragments where the ActionBar will auto-hide, the fragments layout will not have any top-margin set.
  • in the fragments where the ActionBar should not be overlaid, the fragments layout will have top-margin set to actionBarSize.

A point of note (thanks to Jelle):

If your ActionBar is semi-transparent, it would be best to use padding instead of margin for a consistent look.

like image 152
Vikram Avatar answered Oct 05 '22 20:10

Vikram