Java 如何在所有活动中显示导航抽屉?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21405958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Display Navigation Drawer in all activities?
提问by AruLNadhaN
I have a Navigation Drawer
which should appear in all my activities.
我有一个Navigation Drawer
应该出现在我所有的活动中。
I saw many questions similar to this & found a solution like Extending the MainActivity with the Other Activities .
我看到了很多与此类似的问题,并找到了一个解决方案,例如用其他活动扩展 MainActivity 。
So i extended My Main Activity to my Second Activity.But the Drawer is not being showed in the Second Activity
所以我将我的主要活动扩展到我的第二个活动。但是第二个活动中没有显示抽屉
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);
}
}
采纳答案by vipul mittal
in onCreate
of TutorialActivity
don't call setContentView
instead do this:
在onCreate
的TutorialActivity
不叫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);
}
make mDrawer
in MainActivity
protected. and in R.layout.activity_main_drawer
just keep drawer tag and the element with gravity left(or right).
使mDrawer
在MainActivity
保护。并且 R.layout.activity_main_drawer
只保留抽屉标签和向左(或向右)重力的元素。
回答by Greg Ennis
You omitted the @Override
from your derived class onCreate
.
您@Override
从派生类中省略了onCreate
。
UPDATE: I'm not sure what the effects are of calling setContentView
twice but that could be the problem. Separate out the code that sets up the drawer, and call that from both of the onCreate
methods.
更新:我不确定调用setContentView
两次的效果是什么,但这可能是问题所在。分离出设置抽屉的代码,并从两个onCreate
方法中调用它。
回答by Daniel Siguero
I made a BaseActivity activity which extends SherlockActivity (or ActionBarActivity if is your case)
我做了一个 BaseActivity 活动,它扩展了 SherlockActivity (或者 ActionBarActivity 如果是你的情况)
public class BaseActivity extends SherlockActivity
Then, make all your activities extends BaseActivity, like:
然后,让您的所有活动都扩展 BaseActivity,例如:
public class GlossaryActivity extends BaseActivity
Later, you must replace the activity layout with the one that correspond to your activity, I made a method in BaseActivity like that:
稍后,您必须将活动布局替换为与您的活动相对应的布局,我在 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);
}
I called this method on the onCreate method in each activity:
我在每个活动的 onCreate 方法上调用了这个方法:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.replaceContentLayout(R.layout.activity_glossary, super.CONTENT_LAYOUT_ID);
}
super.CONTENT_LAYOUT_ID
is the FrameLayout of the BaseActivity, and other param is the layout you want replace with
super.CONTENT_LAYOUT_ID
是 BaseActivity 的 FrameLayout,其他参数是您要替换的布局
回答by Jongz Puangput
Here is my implementation.. hope it help
这是我的实现..希望它有帮助
FIRST, this POSTis concept.
首先,这个帖子是概念。
SECOND, this is also the KEYone.
第二,这也是关键之一。
FINALLY, Here is combination of all answer in one place
最后,这是所有答案的组合在一个地方
BASE ACTIVITY
基础活动
This is a base activity for all other activity
这是所有其他活动的基础活动
You can extends Activity or FragmentActivity or etc. base on your requirement.
您可以根据您的要求扩展 Activity 或 FragmentActivity 等。
Navigation Drawer
setup here for one time.
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
This xml layout is for Navigation Drawer
这个 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>
ALL OTHERS ACTIVITY
所有其他活动
Other Activity
just extends BaseActivity
and define code as below.
其他Activity
只是扩展BaseActivity
和定义代码如下。
The Navigation Drawer
will appear for particular activity.
该Navigation Drawer
会出现特定的活动。
mDrawer
is form BaseActivity
. it's a protected
variable.
mDrawer
是形式BaseActivity
。这是一个protected
变量。
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 SAMPLE
屏幕 1 XML 示例
Design as you wish it each activity. no more Navigation Drawer
Layout !
随心所欲地设计每项活动。没有更多的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>
NOTE
笔记
In this implementation, The Navigation Drawer
doesn't bind with Action Bar. If you wish to do that do it in BaseActivity
.Also, This guide is not cover all requirement. It's just a sample.
在这个实现中, TheNavigation Drawer
不与 Action Bar 绑定。如果您想这样做,请在BaseActivity
.Also 中执行此操作,本指南并未涵盖所有要求。这只是一个样本。
回答by Razvan Cristian Lung
I had this problem too. This is my implementation:
我也有这个问题。这是我的实现:
activity_main.xml- the child at index 1 in the CoordinatorLayoutis the content_main.xml, this I can change in code.
activity_main.xml- CoordinatorLayout中索引 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>
I've created a class that uses inflates the others activities UI:
我创建了一个使用膨胀其他活动 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);
}
}
Now on the other activities all you have to do is extend the MainActivity and call this method and give it the necessary parameters:
现在在其他活动中,您所要做的就是扩展 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());
}
}
回答by Wiktor Wardzichowski
Ok here is hacky way to do this, I use it only for special kind of debug build to set properties of views in realtime (design tool).
好的,这里是一种 hacky 方法,我仅将它用于特殊类型的调试构建以实时设置视图的属性(设计工具)。
It has advantage that you can use your child activities as usualwithout, special behavior that is required in different answers.
它的优点是您可以像往常一样使用您的孩子的活动,而无需在不同的答案中需要特殊的行为。
so in BaseActvity you can add:
所以在 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);
}
and xml for drawer is just:
抽屉的 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>
回答by Mohammed H. Hannoush
Here is a simple and fast way to do it in android studio:
这是在 android studio 中执行此操作的一种简单快捷的方法:
Create a new activity (Navigation drawer activity) from the gallery, and name it whatever you want, android studio will create everything for you (the class and the xml files that you can customize it later)
In other activities you should extend your Navigation drawer activity, and make sure these other activities has "no action bar" in the manifests file (android:theme="@style/AppTheme.NoActionBar")
You should modify your other activities as follows:
public class Mainactivity extends NavActivity { super.onCreate(savedInstanceState); LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); //inflate your activity layout here! View contentView = inflater.inflate(R.layout.activity_main, null, false); drawer.addView(contentView, 0); }
从图库中创建一个新活动(导航抽屉活动),并根据需要命名它,android studio 将为您创建所有内容(您可以稍后自定义的类和 xml 文件)
在其他活动中,您应该扩展您的导航抽屉活动,并确保这些其他活动在清单文件中具有“无操作栏”(android:theme="@style/AppTheme.NoActionBar")
您应该按如下方式修改您的其他活动:
public class Mainactivity extends NavActivity { super.onCreate(savedInstanceState); LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); //inflate your activity layout here! View contentView = inflater.inflate(R.layout.activity_main, null, false); drawer.addView(contentView, 0); }
Note: the mainactivity will extend the action bar of the NavActivity, the NavActivity has a full functional action bar that will call the navigation drawer
注意:mainactivity 会扩展 NavActivity 的 action bar,NavActivity 有一个功能齐全的 action bar 会调用导航抽屉
I hope it will work with you
我希望它能和你一起工作