如何在所有活动中显示导航抽屉?

我有一个Navigation Drawer ,应该出现在我所有的活动中。

我看到很多类似这样的问题,并find一个解决scheme,如用其他活动扩展MainActivity。

所以我把我的主要活动扩展到了第二个活动中,但是抽屉并没有在第二个活动中显示出来

主要活动

 public class MainActivity extends ActionBarActivity { private ListView mDrawerList; private DrawerLayout mDrawer; private CustomActionBarDrawerToggle mDrawerToggle; private String[] menuItems; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR); // getSupportActionBar().hide(); setContentView(R.layout.activity_main_drawer); // enable ActionBar app icon to behave as action to toggle nav drawer getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeButtonEnabled(true); mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout); // set a custom shadow that overlays the main content when the drawer // opens mDrawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); _initMenu(); mDrawerToggle = new CustomActionBarDrawerToggle(this, mDrawer); mDrawer.setDrawerListener(mDrawerToggle); } private void _initMenu() { NsMenuAdapter mAdapter = new NsMenuAdapter(this); // Add Header mAdapter.addHeader(R.string.ns_menu_main_header); // Add first block menuItems = getResources().getStringArray(R.array.ns_menu_items); String[] menuItemsIcon = getResources().getStringArray(R.array.ns_menu_items_icon); int res = 0; for (String item : menuItems) { int id_title = getResources().getIdentifier(item, "string", this.getPackageName()); int id_icon = getResources().getIdentifier(menuItemsIcon[res], "drawable", this.getPackageName()); NsMenuItemModel mItem = new NsMenuItemModel(id_title, id_icon); // if (res==1) mItem.counter=12; //it is just an example... // if (res==3) mItem.counter=3; //it is just an example... mAdapter.addItem(mItem); res++; } mAdapter.addHeader(R.string.ns_menu_main_header2); mDrawerList = (ListView) findViewById(R.id.drawer); if (mDrawerList != null) mDrawerList.setAdapter(mAdapter); mDrawerList.setOnItemClickListener(new DrawerItemClickListener()); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. mDrawerToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mDrawerToggle.onConfigurationChanged(newConfig); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.control_menu, menu); return super.onCreateOptionsMenu(menu); } /* Called whenever we call invalidateOptionsMenu() */ @Override public boolean onPrepareOptionsMenu(Menu menu) { // If the nav drawer is open, hide action items related to the content // view boolean drawerOpen = mDrawer.isDrawerOpen(mDrawerList); menu.findItem(R.id.action_keyboard).setVisible(!drawerOpen); return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { /* * The action bar home/up should open or close the drawer. * ActionBarDrawerToggle will take care of this. */ if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } // Handle your other action bar items... return super.onOptionsItemSelected(item); } private class CustomActionBarDrawerToggle extends ActionBarDrawerToggle { public CustomActionBarDrawerToggle(Activity mActivity, DrawerLayout mDrawerLayout) { super(mActivity, mDrawerLayout, R.drawable.ic_drawer, R.string.ns_menu_open, R.string.ns_menu_close); } @Override public void onDrawerClosed(View view) { getSupportActionBar().setTitle(getString(R.string.ns_menu_close)); supportInvalidateOptionsMenu(); // creates call to // onPrepareOptionsMenu() } @Override public void onDrawerOpened(View drawerView) { getSupportActionBar().setTitle(getString(R.string.ns_menu_open)); supportInvalidateOptionsMenu(); // creates call to // onPrepareOptionsMenu() } } private class DrawerItemClickListener implements ListView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(MainActivity.this, Tutorial.class); startActivity(intent); } } } 

SecondActivity

  public class Tutorial extends MainActivity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.help); } } 

TutorialActivity onCreate ,不要调用setContentView而应该这样做:

 @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); LayoutInflater inflater = (LayoutInflater) this .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View contentView = inflater.inflate(R.layout.help, null, false); mDrawer.addView(contentView, 0); } 

使MainActivity mDrawer受到保护。 并在R.layout.activity_main_drawer只保留抽屉标签和重力元素左(或右)。

这是我的实现..希望它有帮助

首先 ,这个POST是概念。

第二 ,这也是关键之一。

最后 ,这里是所有答案的组合


基地活动

这是所有其他活动的基本活动

您可以根据您的要求扩展Activity或FragmentActivity等。

Navigation Drawer在这里设置一次。

 public class BaseActivity extends FragmentActivity { protected DrawerLayout mDrawer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.base_layout); mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout); //This is about creating custom listview for navigate drawer //Implementation for NavigateDrawer HERE ! ArrayList<DrawerListItem> drawerListItems = new ArrayList<DrawerListItem>(); drawerListItems.add(new DrawerListItem(0,"AIR° DEVICES")); drawerListItems.add(new DrawerListItem(1,"A/C Device [1]")); drawerListItems.add(new DrawerListItem(1,"A/C Device [2]")); drawerListItems.add(new DrawerListItem(1,"A/C Device [3]")); drawerListItems.add(new DrawerListItem(0,"AIR° FEATURES")); drawerListItems.add(new DrawerListItem(2,"SLEEP MODE")); drawerListItems.add(new DrawerListItem(2,"TRACKING MODE")); drawerListItems.add(new DrawerListItem(2,"SETTINGS")); DrawerAdapter mDrawerAdapter = new DrawerAdapter(this, R.layout.drawer_list_header, drawerListItems); ListView mDrawerList = (ListView) findViewById(R.id.left_drawer); mDrawerList.setAdapter(mDrawerAdapter); } } 

BASE ACTIVITY XML

这个XML布局是为Navigation Drawer

 <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout> <!-- The navigation drawer --> <ListView android:id="@+id/left_drawer" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="left" android:scrollingCache="false" android:background="@drawable/drawer_bg" android:divider="@null" android:choiceMode="singleChoice"/> </android.support.v4.widget.DrawerLayout> 

所有其他活动

其他Activity只是扩展了BaseActivity并定义如下的代码。

Navigation Drawer将出现特定的活动。

mDrawer是表单BaseActivity 。 这是一个protectedvariables。

 public class Screen1 extends BaseActivity @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); //inflate your activity layout here! View contentView = inflater.inflate(R.layout.screen1, null, false); mDrawer.addView(contentView, 0); //Do the rest as you want for each activity } 

SCREEN 1 XML示例

按照您的愿望devise每项活动。 没有更多的Navigation Drawer布局!

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> </LinearLayout> 

注意

在这个实现中, Navigation Drawer不会绑定到操作栏。 如果您希望在BaseActivity中做到这BaseActivity ,那么本指南并不能涵盖所有要求。 这只是一个例子。

我做了一个扩展SherlockActivity的BaseActivity活动(或者是你的情况下的ActionBarActivity)

 public class BaseActivity extends SherlockActivity 

然后,使所有活动扩展到BaseActivity,如下所示:

 public class GlossaryActivity extends BaseActivity 

稍后,您必须将活动布局replace为与您的活动对应的活动布局,我在BaseActivity中制作了一个方法:

 protected void replaceContentLayout(int sourceId, int destinationId) { View contentLayout = findViewById(destinationId); ViewGroup parent = (ViewGroup) contentLayout.getParent(); int index = parent.indexOfChild(contentLayout); parent.removeView(contentLayout); contentLayout = getLayoutInflater().inflate(sourceId, parent, false); parent.addView(contentLayout, index); } 

我在每个活动的onCreate方法上调用了这个方法:

 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.replaceContentLayout(R.layout.activity_glossary, super.CONTENT_LAYOUT_ID); } 

super.CONTENT_LAYOUT_IDsuper.CONTENT_LAYOUT_ID的FrameLayout,其他参数是你想要replace的布局

你从派生类onCreate省略了@Override

更新:我不知道两次调用setContentView的效果是什么,但这可能是问题。 分出设置抽屉的代码,并从两个onCreate方法中调用它。

我也有这个问题。 这是我的实现:

activity_main.xmlCoordinatorLayout中索引为1的子项是content_main.xml ,我可以在代码中进行更改。

 <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> <android.support.design.widget.CoordinatorLayout android:id="@+id/coordinator" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> **<include layout="@layout/content_main" />** <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout> <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" /> </android.support.v4.widget.DrawerLayout> 

我创build了一个使用膨胀其他活动UI的类:

 public class MyLayoutInflater { public void inflate(Activity activity, int LayoutResource, android.app.ActionBar getSupportActionBar, Intent getIntent){ CoordinatorLayout coordinatorLayout = (CoordinatorLayout) activity.findViewById(R.id.coordinator); android.view.LayoutInflater inflater = (android.view.LayoutInflater) activity .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View contentView = inflater.inflate(LayoutResource, null, false); //change i so that it suits the child number in you coordinator layout int i = 1; coordinatorLayout.removeViewAt(i); coordinatorLayout.addView(contentView, i); getSupportActionBar.setTitle(actionBarTitle); } public void inflate(Activity activity, int LayoutResource, android.support.v7.app.ActionBar getActionBar, String actionBarTitle){ CoordinatorLayout coordinatorLayout = (CoordinatorLayout) activity.findViewById(R.id.coordinator); android.view.LayoutInflater inflater = (android.view.LayoutInflater) activity .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View contentView = inflater.inflate(LayoutResource, null, false); //change i so that it suits the child number in you coordinator layout int i = 1; coordinatorLayout.removeViewAt(i); coordinatorLayout.addView(contentView, i); getActionBar.setTitle(actionBarTitle); } } 

现在在其他活动中,您只需扩展MainActivity并调用此方法并为其提供必要的参数:

 public class AnotherActivity extends MainActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); new MyLayoutInflater().inflate(this,R.layout.content_activity_another, getSupportActionBar(), getIntent()); } } 

好吧,这里是做这件事的方法,我只用它来进行特殊types的debugging,以实时设置视图属性(devise工具)。

它有一个好处,就是你可以像平常一样使用你的孩子的活动,而不需要特殊的行为。

所以在BaseActvity中可以添加:

 @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // WARNING: Hacky, use carefully!!! ViewGroup androidBaseView = (ViewGroup) findViewById(android.R.id.content); //this one in what child activity has just set in setContentView() ViewGroup childContent = (ViewGroup) androidBaseView.getChildAt(0); View drawerView = LayoutInflater.from(this) .inflate(R.layout.base_activity_drawer, androidBaseView, false); FrameLayout frameLayout = (FrameLayout) drawerView.findViewById(R.id.content); androidBaseView.removeView(childContent); frameLayout.addView(childContent); androidBaseView.addView(drawerView); } 

而抽屉的xml只是:

  <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/nav_drawer" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <FrameLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent"/> <LinearLayout android:id="@+id/drawer_for_components" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="end" android:orientation="vertical" android:fitsSystemWindows="true" /> </android.support.v4.widget.DrawerLayout>