我做了一个导航抽屉,就像developer.android.com网站上的教程中显示的那样。但是现在,我想使用一个导航抽屉,我在NavigationDrawer.class中创建了多个活动在我的应用程序。

我的问题是,这里是否有人可以做一个小教程,它解释了如何使用一个导航抽屉的多个活动。

我第一次读到这个答案 Android导航抽屉在多个活动

但在我的项目上行不通

public class NavigationDrawer extends Activity {
public DrawerLayout drawerLayout;
public ListView drawerList;
private ActionBarDrawerToggle drawerToggle;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout, R.drawable.ic_drawer, 0, 0) {

        public void onDrawerClosed(View view) {
            getActionBar().setTitle(R.string.app_name);
        }

        public void onDrawerOpened(View drawerView) {
            getActionBar().setTitle(R.string.menu);
        }
    };
    drawerLayout.setDrawerListener(drawerToggle);

    getActionBar().setDisplayHomeAsUpEnabled(true);
    getActionBar().setHomeButtonEnabled(true);

    listItems = getResources().getStringArray(R.array.layers_array);
    drawerList = (ListView) findViewById(R.id.left_drawer);
    drawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, android.R.id.text,
            listItems));
    
    drawerList.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
            drawerClickEvent(pos);
        }
    });
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (drawerToggle.onOptionsItemSelected(item)) {
        return true;
    }
    return super.onOptionsItemSelected(item);

}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    drawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    drawerToggle.onConfigurationChanged(newConfig);
}
}

在这个活动中,我想有导航抽屉,所以我扩展了'NavigationDrawer',在其他一些活动中,我想使用相同的导航抽屉

  public class SampleActivity extends NavigationDrawer {...}

当前回答

我在Kotlin是这样做的:

open class BaseAppCompatActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

protected lateinit var drawerLayout: DrawerLayout
protected lateinit var navigationView: NavigationView
@Inject
lateinit var loginService: LoginService

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Log.d("BaseAppCompatActivity", "onCreate()")
    App.getComponent().inject(this)
    drawerLayout = findViewById(R.id.drawer_layout) as DrawerLayout

    val toolbar = findViewById(R.id.toolbar) as Toolbar
    setSupportActionBar(toolbar)

    navigationView = findViewById(R.id.nav_view) as NavigationView
    navigationView.setNavigationItemSelectedListener(this)

    val toggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)

    drawerLayout.addDrawerListener(toggle)
    toggle.syncState()
    toggle.isDrawerIndicatorEnabled = true

    val navigationViewHeaderView = navigationView.getHeaderView(0)
    navigationViewHeaderView.login_txt.text = SharedKey.username
}
private inline fun <reified T: Activity> launch():Boolean{
    if(this is T) return closeDrawer()
    val intent = Intent(applicationContext, T::class.java)
    startActivity(intent)
    finish()
    return true
}

private fun closeDrawer(): Boolean {
    drawerLayout.closeDrawer(GravityCompat.START)
    return true
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
    val id = item.itemId

    when (id) {
        R.id.action_tasks -> {
            return launch<TasksActivity>()
        }
        R.id.action_contacts -> {
            return launch<ContactActivity>()
        }
        R.id.action_logout -> {
            createExitDialog(loginService, this)
        }
    }
    return false
}
}

抽屉的活动必须继承这个BaseAppCompatActivity,调用super。onCreate在内容设置后(实际上,可以移动到一些init方法),并在布局中有对应的id元素

其他回答

如果你想要一个导航抽屉,你应该使用片段。 上周我学习了这个教程,效果很好:

http://developer.android.com/training/implementing-navigation/nav-drawer.html

您还可以从本教程下载示例代码,以了解如何做到这一点。


没有片段:

这是你的BaseActivity代码:

public class BaseActivity extends Activity
{
    public DrawerLayout drawerLayout;
    public ListView drawerList;
    public String[] layers;
    private ActionBarDrawerToggle drawerToggle;
    private Map map;
    
    protected void onCreate(Bundle savedInstanceState)
    {
        // R.id.drawer_layout should be in every activity with exactly the same id.
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        
        drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout, R.drawable.ic_drawer, 0, 0) 
        {
            public void onDrawerClosed(View view) 
            {
                getActionBar().setTitle(R.string.app_name);
            }
    
            public void onDrawerOpened(View drawerView) 
            {
                getActionBar().setTitle(R.string.menu);
            }
        };
        drawerLayout.setDrawerListener(drawerToggle);
    
        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);
        
        layers = getResources().getStringArray(R.array.layers_array);
        drawerList = (ListView) findViewById(R.id.left_drawer);
        View header = getLayoutInflater().inflate(R.layout.drawer_list_header, null);
        drawerList.addHeaderView(header, null, false);
        drawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, android.R.id.text1,
                layers));
        View footerView = ((LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
                R.layout.drawer_list_footer, null, false);
        drawerList.addFooterView(footerView);
    
        drawerList.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
                map.drawerClickEvent(pos);
            }
        });
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
        if (drawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    
    }
    
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggle.syncState();
    }
    
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }
}

所有其他需要有导航抽屉的活动都应该扩展这个活动,而不是活动本身,例如:

public class AnyActivity extends BaseActivity
{
    //Because this activity extends BaseActivity it automatically has the navigation drawer
    //You can just write your normal Activity code and you don't need to add anything for the navigation drawer
}

XML

<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">
    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <!-- Put what you want as your normal screen in here, you can also choose for a linear layout or any other layout, whatever you prefer -->
    </FrameLayout>
    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111"/>
</android.support.v4.widget.DrawerLayout>

编辑:

我自己也遇到过一些困难,所以如果你得到nullpointerexception,这里有一个解决方案。在BaseActivity中将onCreate函数更改为受保护的void onCreateDrawer()。其余的可以保持不变。在扩展BaseActivity的Activities中,将代码按以下顺序放置:

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);
    super.onCreateDrawer();

这就是如何创建具有多个活动的导航抽屉,如果您有任何问题,请随时询问。


编辑2:

正如@GregDan所说,你的BaseActivity也可以覆盖setContentView()并调用onCreateDrawer:

@Override 
public void setContentView(@LayoutRes int layoutResID) 
{ 
    super.setContentView(layoutResID); 
    onCreateDrawer() ;
}

在baseactivity中更新此代码。不要忘记在你的activity xml中包含drawer_list_header。

super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
setContentView(R.layout.drawer_list_header);

并且不要在你的活动中使用request()。但仍然是抽屉不可见点击图像..和拖动它将可见没有列表项。我尝试了很多,但没有成功。需要一些锻炼…

我已经找到了最好的实现。在谷歌I/O 2014应用程序中。

他们使用和凯文一样的方法。如果你可以把自己从I/O应用程序中所有不需要的东西中抽象出来,你可以提取你需要的一切,谷歌保证它是导航抽屉模式的正确使用。 每个活动都有一个可选的DrawerLayout作为其主布局。有趣的部分是如何导航到其他屏幕。它在BaseActivity中是这样实现的:

private void goToNavDrawerItem(int item) {
        Intent intent;
        switch (item) {
            case NAVDRAWER_ITEM_MY_SCHEDULE:
                intent = new Intent(this, MyScheduleActivity.class);
                startActivity(intent);
                finish();
                break;

这与用片段事务替换当前片段的常见方法不同。但用户并没有发现视觉上的差异。

所以这个答案晚了几年,但有人可能会欣赏它。Android为我们提供了一个新的小部件,可以更容易地使用一个导航抽屉和几个活动。

navigationview是模块化的,在菜单文件夹中有自己的布局。你使用它的方式是以下方式包装xml布局:

Root Layout is a android.support.v4.widget.DrawerLayout that contains two children: an <include ... /> for the layout that is being wrapped (see 2) and a android.support.design.widget.NavigationView. <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"> <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" /> <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" />

nav_header_main只是一个线性布局的方向=垂直为你的导航图纸的头部。

Activity_main_drawer是res/menu目录中的一个菜单XML。它可以包含您选择的项目和组。如果你使用AndroidStudio Gallery,向导会为你创建一个基本的Gallery,你可以看到你有哪些选项。

App bar layout is usually now a android.support.design.widget.CoordinatorLayout and this will include two children: a android.support.design.widget.AppBarLayout (which contains a android.support.v7.widget.Toolbar) and an <include ... > for your actual content (see 3). <android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent" android:layout_height="match_parent" tools:context="yourpackage.MainActivity"> <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" /> Content layout can be whatever layout you want. This is the layout that contains the main content of the activity (not including the navigation drawer or app bar).

现在,最酷的事情是,你可以在这两个布局中包装每个活动,但你的NavigationView(见步骤1)总是指向activity_main_drawer(或其他什么)。这意味着您将在所有活动上拥有相同的(*)导航抽屉。

它们不会是相同的NavigationView实例,但是,公平地说,即使使用上面概述的BaseActivity解决方案,这也是不可能的。

有了@Kevin van Mierlo的回答,您也可以实现多个抽屉。例如,位于左侧的默认菜单(start),以及位于右侧的进一步可选菜单,仅在加载确定片段时显示。

我已经做到了。