18

I am developing an application that contains many activities and i created my own menu (i don't want to use the built in menu button) with the Sliding Drawer as the sliding drawer is at the bottom of the screen and contains my menu buttons

what i need is to make that sliding drawer to appear in all my activities

i tried to create an activity and set it's content view to the xml file that includes the drawer and then extends that activity in all other activities but this solution doesn't work

so any suggestions ?

Zak
  • 571
  • 2
  • 6
  • 13

3 Answers3

42

Extending is the right way. Just override setContentView in the right way. Here's the working example, but instead of drawer, I use a created a custom tabbar:

Define a layout with your drawer like this:

this is act_layout.xml

<LinearLayout
  ...
  android:orientation="vertical"
>
  <YourDrawer
    ...
  />
  <FrameLayout
    android:id="@+id/act_content"
    ...
  >
    // Here will be all activity content placed
  </FrameLayout>
</LinearLayout>

This will be your base layout to contain all other layouts in the act_content frame. Next, create a base activity class, and do the following:

public abstract class DrawerActivity extends Activity {

    protected LinearLayout fullLayout;
    protected FrameLayout actContent;

    @Override
    public void setContentView(final int layoutResID) {
        // Your base layout here
        fullLayout= (LinearLayout) getLayoutInflater().inflate(R.layout.act_layout, null); 
        actContent= (FrameLayout) fullLayout.findViewById(R.id.act_content);

        // Setting the content of layout your provided to the act_content frame
        getLayoutInflater().inflate(layoutResID, actContent, true); 
        super.setContentView(fullLayout);

        // here you can get your drawer buttons and define how they 
        // should behave and what must they do, so you won't be 
        // needing to repeat it in every activity class
    }
}

What we do, is basically intercept all calls to setContentView(int resId), inflate our layout for drawer from xml, inflate our layout for activity (by reId provided in method call), combine them as we need, and set as the contentView of the activity.

EDIT: After you've created the stuff above, just proceed to write an app as usual, create layouts (without any mention of a drawer) create activities, but instead of extending simple activity, extend DrawerActivity, like so:

public abstract class SomeActivity extends DrawerActivity {

    protected void onCreate(Bundle bundle) {
        setContentView(R.layout.some_layout);
    }
}

What happens, is that setContentView(R.layout.some_layout) is intercepted. Your DrawerActivity loads the layout you provided from xml, loads a standart layout for your drawer, combines them and then sets it as contentView for the activity.

Mauker
  • 11,237
  • 7
  • 58
  • 76
Alex Orlov
  • 18,077
  • 7
  • 55
  • 44
  • thanks for your answer but i didn't get the point of it , would you please explain to me more , i did what you told me i created a class to draw the sliding drawer and i extend it to other class the output is that i get the drawer correctly on the screen but i can't set the view of the child activity , how could i do that – Zak Feb 07 '11 at 20:04
  • The most important thing is to combine 2 layouts (of activity and the one where the drawer is) into 1 and only then set it with the setContentView. What I suggest to you, is inflate both layouts from xml (that way no setContentView is yet called) combine them programatically the way you want them and then call setContentView(your_combinet_view). It's what I did when I overrode the setContentView in DrawerActivity. I'll add the example of a simple activity that must extend it. – Alex Orlov Feb 08 '11 at 07:18
  • i tired your suggestion and i combine them as you did in the provided example and from the child class i call the setContentView passing to it the root id of the xml of my new activity public class AlJazeera extends MenuSlider { Context ctx = this ; protected FrameLayout Layout; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.id.idl); } } – Zak Feb 08 '11 at 07:23
  • but i get an error of resources not found it seems that it does not accept the id of the root element of the xml file !!!!!!!!!! – Zak Feb 08 '11 at 07:25
  • i tried the same code you wrote here but there is an error is it working with you ?! – Zak Feb 08 '11 at 07:38
  • Of course there's an error, I wrote a sample to demonstrate the idea. You need to change the id's and layout's names. – Alex Orlov Feb 08 '11 at 07:53
  • I changed couple of id's and added a comment to layout. Hope it makes it easier for you to get the idea. It more or less must work like it is now. – Alex Orlov Feb 08 '11 at 07:56
  • By the end, you should have 2 files for drawe (act_layout.xml - the one I provied above, that is a container for drawer and your other activities, DrawerActivity class- that will be the base class for all your activities that use drawer). Then just proceed as you normally do, but extend DrawerActivity instead of simple Activity. – Alex Orlov Feb 08 '11 at 07:59
  • of course i created my own classes and xmls !!! i mean i tried the same idea as yours and i get resource not found error .. but i have a question to you shouldn't u pass in the child class in the setContentView method an integer id not a layout ?!! – Zak Feb 08 '11 at 08:03
  • You can pass both. All right. I'll create a blog post where I'll explain how to do it step by step. Just wait a little bit. – Alex Orlov Feb 08 '11 at 08:59
  • hi there .. did u write the blog post ? ,, what i reached now is when i run the program the drawer appears but the xml layout of the child activity doesn't appear – Zak Feb 08 '11 at 11:11
  • @AlexOrlov nice idea, in my case I need to use this with a MapActivity and a ListActivity so I can't extend from a common base class. – aromero Dec 21 '11 at 22:07
  • Thanks, I used similar implementation for my project but I have [this issue](http://stackoverflow.com/q/11522798/840669). Please answer if you can figure out what is the problem. – Rajkiran Jul 17 '12 at 12:51
  • 1
    After doing it I can see the navigation drawer icon in action bar but can't interact with it. Any idea why ? – Shridutt Kothari Feb 16 '14 at 16:45
  • @aromero just use MapFragments and ListFragments embedded in your DrawerActivities – brainmurphy1 Sep 25 '14 at 03:42
13

Finally after 3 years, here's the complete solution to this important question for whom may have not been completely guided by Mr. Orlov's answer.

His method for making a hierarchy view was completely OK but there was some small mistakes that may mislead beginner developers.

  1. As Gabe also mentioned, you can get rid of abstract in declaration.
  2. There's no need to wrap both child with a FrameLayout. The parent could be anything RelativeLayout, LinearLayout, etc. But the most important part is that you must declare the FrameLayout before the Slider.

So the 100% working soloution would be like this :

activity_drawer.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<FrameLayout
    android:id="@+id/drawer_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<YourDrawer
    android:id="@+id/drawer_drawer"
    android:layout_width="match_parent"
    android:layout_height="fill_parent" >

</YourDrawer>

</RelativeLayout>

DrawerActivity.java

public class DrawerActivity extends Activity {

protected RelativeLayout fullLayout;
protected FrameLayout frameLayout;

@Override
public void setContentView(int layoutResID) {

    fullLayout = (RelativeLayout) getLayoutInflater().inflate(R.layout.activity_drawer, null);
    frameLayout = (FrameLayout) fullLayout.findViewById(R.id.drawer_frame);

    getLayoutInflater().inflate(layoutResID, frameLayout, true);

    super.setContentView(fullLayout);

    //Your drawer content...

}

}

MainActivity.java

public class MainActivity extends DrawerActivity {

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

}

}

Don't forget to declare DrawerActivity in manifest.

Hope it helped.

The Great MA
  • 131
  • 1
  • 2
  • I don't have the drawer activity in my manifest file and it still works fine. Mind you I'm on 23.0.1 now. – Stephane Sep 27 '15 at 16:01
2

I know this is two years late but for those who would like an answer here it is. Mr Orlov had an appropriate response, just a few adjustments needed.

  • delete the abstract after public. (this is what causes an error)
  • wrap BOTH your sliding drawer and FrameLayout with another FrameLayout and set the width and height to match_parent. (This allows BOTH layouts to appear).

ALSO: If you want your sliding drawer to appear on top of your layout (duh!) then place the frameLayout that is after the slidingDrawer before the slidingDrawer.

Gabe
  • 21
  • 2