7

When using the drawer layout is there a way to overlay the drawer view over the action bar? I do not want to hide the action bar when the drawer is shown. I want the action bar to simply stay put, but be sent to the background. An example of this is the iOS Play Music app...

enter image description here

My current implementation hides and shows the action bar when the drawer state changes, but I do not like this user experience.

        public void onDrawerClosed(View view) {
            getActionBar().show();
            invalidateOptionsMenu(); 
        }

        public void onDrawerOpened(View drawerView) {
            getActionBar().hide();
            invalidateOptionsMenu();
        }
MCR
  • 1,633
  • 3
  • 21
  • 36

6 Answers6

3

I searched the web in order to find any good solution for this problem and haven't found. So I did a trick that did this.

First of all we need to request action bar overlay feature. So in onCreate() of your activity, before setContntView() call: requestWindowFeature(com.actionbarsherlock.view.Window.FEATURE_ACTION_BAR_OVERLAY);

It will make everything including navigation drawer draw behind action bar. We don't need this, so we need to set the top margin of our FrameLayout which hosts our fragments in the activity with the exact height of the action bar. In the layout file of the activity we need to do the following:

<!-- Framelayout to display Fragments -->

    <FrameLayout
        android:id="@+id/frame_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="?attr/actionBarSize" />

It will make only navigation drawer appear behind the action bar. Now we will hide the action bar when the navigation drawer is opened on half, and will show it when the drawer is nearly closed. To do this we need to make the following in the activity:

@Override
    public void onDrawerSlide(View drawerView, float slideOffset) {
        super.onDrawerSlide(drawerView, slideOffset);

        if(slideOffset > 0.5){
            actionBar.setBackgroundDrawable(null);
            actionBar.hide();
        } else {
            actionBar.show();

            if(slideOffset < 0.1){
                actionBar.setBackgroundDrawable(layerDrawable);
            }
        }       
    }

As you can see I also change the background drawable of the action bar to make it transparent when before I begin to hide it, and change it back with my custom background when I show it back.

My custom background is a layerListDrawable which is all transparent but have a divider in bottom with some shadow.

And to achieve this I have defined the following layer-list in XML:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:top="0dp" android:left="0dp" android:bottom="0dp" android:right="0dp">
        <shape android:shape="rectangle">
            <solid android:color="@android:color/transparent"/>
        </shape>
    </item>

    <item android:top="0dp" android:left="0dp" android:bottom="0dp" android:right="0dp">
        <shape android:shape="rectangle">
            <solid android:color="#afafaf"/>
        </shape>
    </item>

    <item android:top="0dp" android:left="0dp" android:bottom="0dp" android:right="0dp">
        <shape android:shape="rectangle">
            <gradient
                android:angle="270"
                android:startColor="#88afafaf" 
                android:endColor="#33afafaf"
            />
        </shape>
    </item>    
</layer-list>

And to get the background I need from this XML I do the following in the activity:

final ActionBar actionBar = getSupportActionBar();
        final LayerDrawable layerDrawable = (LayerDrawable) getResources()
                .getDrawable(R.drawable.shadow_divider);

        final TypedArray styledAttributes = getTheme().obtainStyledAttributes(
                new int[] { R.attr.actionBarSize });
        int topOffset = (int) (styledAttributes.getDimension(0, 0));
        styledAttributes.recycle();

        layerDrawable.setLayerInset(1, 0, topOffset - 3, 0, 2);
        layerDrawable.setLayerInset(2, 0, topOffset - 2, 0, 0);

        actionBar.setBackgroundDrawable(layerDrawable);

where R.drawable.shadow_divider is the XML layer-list I have defined earlier.

It looks really great! Hope it can help someone.

EDIT

I had a small bug here which can be a reason of a crush sometimes. Here is the fixed code: `

    <FrameLayout
        android:id="@+id/frame_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        **android:paddingTop="?attr/actionBarSize"**  />`

It should be paddingTop not layout_marginTop!

Andranik
  • 2,729
  • 1
  • 29
  • 45
1

That's the proper effect in Android defaults. If you want to emulate the iOS effect, you'll probably have to do it yourself, because AFAIK the drawer component of the support library doesn't allow such type of configurations.

Anyway, every time a programmer codes a lot just to emulate some fancy (and much probably not worthy) iOS effect in Android, a little cat dies...

thelawnmowerman
  • 11,956
  • 2
  • 23
  • 36
  • I agree with you with you entirely, but the customer wants the same experience on iOS and Android. Looks like I'm going custom. Thanks. – MCR Feb 19 '14 at 15:31
  • 1
    I understand... I've experienced that before, lots of clients want the Android version exactly the same as the iOS one, but trust me, it usually takes much less effort to convince them of how bad is that than actually recoding all iOS effects on Android. – thelawnmowerman Feb 19 '14 at 15:37
  • 1
    Imho that "effect" is nothing that breaks the UX. The "little cat dies" argument is stupid and polemic... – WarrenFaith Feb 19 '14 at 15:53
  • 1
    First of all, I am a professional Android developer. Doing it full time in an agancy which proud of the quality it creates. That being said, I agree that there are patterns that shouldnt cross platforms but not every non common effect is bad by definition. If you dont test your app when doing something custom, it is your fault! Saying that I release untested low quality apps is just rude. If the customer wants something and pays for it and it is such a minor non important effect, than it is more than justified! – WarrenFaith Feb 19 '14 at 17:55
1

I don't think you'll be able to do this with Android's provided Navigation Drawer (without doing something really hacky), since doing this really goes against Android design patterns. If you want a library that does what you're looking for, I've used this library before Android came out with it's own widget, and it does what you're looking for.

Submersed
  • 8,810
  • 2
  • 30
  • 38
  • thanks for the link to sliding menu. I've looked at that before and ruled it out. Now, it seems it may be a good option. – MCR Feb 19 '14 at 15:54
1

I found the answer in my question, also added an example project for reference. You can take a look to see if it works for you. Android Navigation Drawer on top ActionBar

Community
  • 1
  • 1
lemycanh
  • 827
  • 1
  • 11
  • 14
0

You can achieve this with ActionBarSherlock.

http://actionbarsherlock.com/

mass441
  • 126
  • 1
  • 8
  • 4
    Using ActionBarSherlock nowadays is a bad idea. – thelawnmowerman Feb 19 '14 at 15:39
  • 1
    It's not a bad idea , just not the best idea. – mass441 Feb 19 '14 at 15:41
  • 3
    Using a third party library that provides nearly the same functionality as the official support library given by Google only to achieve an animation is definetely a bad idea, sorry – thelawnmowerman Feb 19 '14 at 15:45
  • 1
    @thelawnmowerman It's not. ABS and ABC are basically doing the same, just taking a different approach. And to be honest I like the approach ABS is taking a lot better than ABC. – Ahmad Feb 19 '14 at 15:45
  • 1
    ABS is a nearly standard when it comes to backwards compatibility. There are quite some libraries available which are better than the original features provided by the OS (not only true for Android...). (countervoted!) – WarrenFaith Feb 19 '14 at 15:48
  • using sherlock when you have app compat lib is really a bad idea – vishal dharankar Jun 18 '15 at 11:05
0

You will be able to do it but the drawer will look so awkward that you will not like it. I had the same requirement and I ended up using Radio Buttons customized to appear as tabs. You can also try hiding the tabs when the drawer opens and vice versa, but that certainly is not what you want here.

You can try to use ViewPager, tabbed indicator such PagerTabStrip and/or TabPageIndicator.

Source.

Community
  • 1
  • 1
Atul O Holic
  • 6,692
  • 4
  • 39
  • 74