在不同的活动中使用相同的导航抽屉

212

我制作了一个工作中的导航抽屉,就像在developer.android.com网站上的教程中展示的那样。但现在,我想在我的应用程序中为多个活动使用一个Navigation Drawer,我已经在NavigationDrawer.class中创建了它。

我的问题是,是否有人可以制作一个简单的教程,解释如何为多个活动使用一个Navigation Drawer。

我最初在这个答案中看到它 Android Navigation Drawer on multiple Activities

但在我的项目中它没能正常工作

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 {...}

1
你可以在这里找到示例。 - Naddy
1
你可以在以下链接中找到关于BaseActivity和导航的内容:https://dev59.com/B4_ea4cB1Zd3GeqPUOJT#42533759 - varotariya vajsi
13个回答

189
如果您想要一个导航抽屉,应该使用片段。我上周遵循了这个教程,效果非常好: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);
    }
}

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

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>

编辑:

我自己遇到了一些困难,所以如果你遇到 NullPointerExceptions ,这里有一个解决方案。在 BaseActivity 中将 onCreate 函数改为 protected 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() ;
}

8
我不想在Fragment上使用活动(Activity),我只想使用不同的活动(Activity),它们都使用相同的导航抽屉(Navigation Drawer)。我想使用活动(Activity),因为在那里我可以使用不同类型的布局,比如滑动视图(Swipe View)、地图视图(Map View)等等。 - MEX
138
对于任何相对复杂的应用程序来说,仅有一个活动可能是一项艰巨的任务。使用活动可以从系统中获得许多免费的东西 - 因此如何使用多个活动是一个合理的问题。我无法想象一个活动能够处理任意数量的片段组合之间的通信 - 这只会导致失败。 - slott
2
@KevinvanMierlo,你能告诉我你所说的意思吗:R.id.drawer_layout 应该在每个活动中具有完全相同的ID。因为我按照你在这里所说的做了,但是我在扩展此 BaseActivity 的 Activity 的 onCreate() 方法中遇到了 NullPointerException。 - Loolooii
1
@KevinvanMierlo 顺便说一下,我想你可能忘记了这两行代码?super.onCreate(savedInstanceState); setContentView(R.layout.activity_base); - Loolooii
1
@KevinvanMierlo,我该如何保持我的活动布局并将这个drawerLayout添加到其中?因为两个活动都需要我设置一个contentView。而我的活动布局会覆盖drawer的布局。你能解释一下这部分吗? - Loolooii
显示剩余61条评论

35

我找到了最好的实现方法,它在Google I/O 2014应用程序中。

他们采用了与Kevin相同的方法。如果你可以从I/O应用程序中抽象出所有不必要的东西,你可以提取你需要的一切,并且Google保证这是导航抽屉模式的正确使用方式。 每个活动都可以选择将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;

这与常规的通过片段事务替换当前片段的方法不同。但用户不会注意到视觉上的区别。


这个 ^ 我无法弄清楚他们如何启动新的活动并且它完美地运行。这是一个需要仔细处理的大型应用程序。 - Nick H
@hitch.united 这是因为他们使用了很多片段和只有少数活动。 - Joaquin Iurchuk
@hitch.united 他们可能会使用overridePendingTransitions来覆盖活动的动画。 - EpicPandaForce
正在加载片段而不是子类化活动吗? - Vikas Pandey
这是2014年10月的文件:https://github.com/google/iosched/blob/65ac452d9c722c84480756ba6218d1062c8f2387/android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java - denvercoder9

8
最简单的方法是在一组活动中重复使用常见的导航抽屉。
app_base_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

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

    </FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/menu_test"
        />
</android.support.v4.widget.DrawerLayout>

AppBaseActivity.java

/*
* This is a simple and easy approach to reuse the same 
* navigation drawer on your other activities. Just create
* a base layout that conains a DrawerLayout, the 
* navigation drawer and a FrameLayout to hold your
* content view. All you have to do is to extend your 
* activities from this class to set that navigation 
* drawer. Happy hacking :)
* P.S: You don't need to declare this Activity in the 
* AndroidManifest.xml. This is just a base class.
*/
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

public abstract class AppBaseActivity extends AppCompatActivity implements MenuItem.OnMenuItemClickListener {
    private FrameLayout view_stub; //This is the framelayout to keep your content view
    private NavigationView navigation_view; // The new navigation view from Android Design Library. Can inflate menu resources. Easy
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    private Menu drawerMenu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.app_base_layout);// The base layout that contains your navigation drawer.
        view_stub = (FrameLayout) findViewById(R.id.view_stub);
        navigation_view = (NavigationView) findViewById(R.id.navigation_view);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, 0, 0);
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        drawerMenu = navigation_view.getMenu();
        for(int i = 0; i < drawerMenu.size(); i++) {
          drawerMenu.getItem(i).setOnMenuItemClickListener(this);
        }
        // and so on...
    }

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

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

    /* Override all setContentView methods to put the content view to the FrameLayout view_stub
     * so that, we can make other activity implementations looks like normal activity subclasses.
     */
    @Override
    public void setContentView(int layoutResID) {
        if (view_stub != null) {
            LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            View stubView = inflater.inflate(layoutResID, view_stub, false);
            view_stub.addView(stubView, lp);
        }
    }

    @Override
    public void setContentView(View view) {
        if (view_stub != null) {
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            view_stub.addView(view, lp);
        }
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        if (view_stub != null) {
            view_stub.addView(view, params);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        // Handle your other action bar items...

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.item1:
                // handle it
                break;
            case R.id.item2:
                // do whatever
                break;
            // and so on...
        }
        return false;
    }
}

1
你能提供一个使用这个基础活动的示例吗? - CDrosos
实际上我无法记住任何细节,但我认为只需按默认方式扩展 AppBaseActivitysetContentView 应该就可以了。 - Levon Petrosyan

8

虽然这个回答已经晚了几年,但某些人可能会感激它。Android为我们提供了一个新的小部件,使得在多个活动中使用一个导航抽屉变得更加容易。

android.support.design.widget.NavigationView 是模块化的,并且在菜单文件夹中有自己的布局。您使用它的方式是按照以下方式包装xml布局:

  1. 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是您导航抽屉的标题的LinearLayout,其方向为垂直。

activity_main_drawer是您res/menu目录中的菜单xml。它可以包含您选择的项和组。如果您使用AndroidStudio Gallery,向导会为您制作一个基本的菜单,您可以查看您的选项。

  1. 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" />
    

  2. 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解决方案也不可能做到这一点。

stackoverflow正在截断一些封闭的XML括号,但重要的内容都在那里。 - jwehrle
但是如何处理像按钮这样的功能呢?您必须在每个活动中编写相同的代码吗? - Laur89
是的,因为它们是独立的实例。不过,你可以创建一个超类让你的活动继承它,并将那段代码放在那里。 - jwehrle
@jwehrle,你能否写一个关于为我们的活动创建超类的示例? - CDrosos
公共抽象类 MyBaseActivity 扩展自 AppCompatActivity 并实现 NavigationView.OnNavigationItemSelectedListener 接口 { // 实现以下内容: Override public boolean onNavigationItemSelected(@NonNull MenuItem item) {}}public class MyActivity extends MyBaseActivity {} - jwehrle
评论区的格式都错了。为自己定义一个基类,该基类扩展Activity(在这种情况下,是AppCompatActivity),然后所有常规活动都应扩展您的新基本活动。实质上,您正在将一个类插入到您的活动和Android的活动类之间。 - jwehrle

6
如果有其他人想要实现原帖中所提出的问题,请考虑使用片段(fragments),而不是像Kevin所说的那样。以下是一个关于如何使用片段的优秀教程:https://github.com/codepath/android_guides/wiki/Fragment-Navigation-Drawer
如果您选择使用活动(activities)而不是片段,您将遇到一个问题,即每次导航到新活动时都会重新创建导航抽屉(nav drawer)。这会导致每次都出现丑陋/缓慢的导航抽屉渲染。

5
我的建议是:完全不使用活动,而是使用片段,并将它们替换到您显示第一个片段的容器(例如线性布局)中。[注意:您可以使用导航图来使用此概念。Compose 进一步减少了制作布局 XML 的需要,因此我们也可以在那里应用它。]
代码可在 Android 开发者教程中找到,您只需自定义即可。

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

建议您在应用程序中使用越来越多的片段(fragment),除了外部活动(例如FacebookActivity),在AndroidManifest.xml中提到只有四个基本活动(local to your application):
1. SplashActivity: 不使用片段,使用全屏主题(FullScreen theme)。
2. LoginSignUpActivity: 不需要导航抽屉(NavigationDrawer),也没有返回按钮(back button),因此只需使用普通工具栏(toolbar),但至少需要3或4个片段。使用无操作栏(no-action-bar)主题(theme)。
3. HomeActivity或DashBoard Activity: 使用无操作栏(no-action-bar)主题(theme)。这里需要导航抽屉(Navigation drawer),随后的所有屏幕都将是片段或嵌套片段(nested fragments),直到叶子视图(leaf view),带有共享抽屉(shared drawer)。所有设置、用户档案等都将作为片段出现在此活动中。这里的片段将不会添加到后退栈(back stack),并且将从导航抽屉菜单项打开。对于需要返回按钮而不是抽屉的片段,下面还有第四种类型的活动。
4. 没有导航抽屉的活动。此活动顶部有一个返回按钮,并且内部的片段将共享同一个操作栏(action-bar)。这些片段将被添加到后退栈(back-stack),因为将有导航历史。

[如需进一步指导,请参见:https://dev59.com/yG035IYBdhLWcg3wVud1#51100507]

编程愉快!


这是一篇较旧的文章。您可以使用片段来确保始终有一个活动。您可以将片段替换为专门用于它的一个容器中。当您需要向后导航时,请将其放入返回堆栈中,或者在需要将片段显示为第一个片段时弹出所有片段。 - Abhinav Saxena
@Cabuxa.Mapache 请查看我答案中的附加链接以获取进一步帮助。我已经创建了一个通用的 BaseActivity,可以在附加到它的所有片段中共享 ActionBar 工具栏、导航抽屉和其他组件。 - Abhinav Saxena
我很好奇您是否能就我目前正在构建的应用程序给予一些意见,以及您上面提到的内容是否适用于我的应用程序。请私信我,谢谢。 - DCam
现在有导航图和操作(指向其他片段或活动)的概念,使这一切变得更加容易。它支持子片段。现在,基于具有顶部返回按钮、全屏、带导航抽屉等特性的片段,您可以设计活动并重用您的片段来放置导航抽屉。 - Abhinav Saxena

1

我用 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(实际上可以移动到某个初始化方法中),并在其布局中具有相应的id元素。


我想尝试您的解决方案,但是我遇到了这个错误:“此 Activity 已经由窗口装饰提供了一个操作栏”。我想在 3 个活动之间切换,每个活动都有自己的应用程序栏。您认为这可能吗? - davoid
我认为,在这种情况下,你需要将你的操作栏移动到片段中。在我们的应用程序中,我们使用了NoActionBar主题,并提供了工具栏以实现兼容性,就我所记得的而言。 - Pavlus
@Pavlus,在第二个活动中,代码会是什么样子?类 trackActivity : BaseAppCompatActivity() {? - Craig P

1

请在BaseActivity中更新此代码,并确保在您的活动XML中包含drawer_list_header。

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

请不要在活动中使用request()。但是点击图像时仍然看不到抽屉,拖动时将会显示出来,没有列表项。我尝试了很多次,但没有成功。需要一些解决方案...


1
通过 @Kevin van Mierlo 的回答,您也能够实现几个抽屉。例如,位于左侧(开始)的默认菜单,以及进一步的可选菜单,位于右侧,仅在加载确定片段时显示。
我已经能够做到这一点。

1
我的回答只是一个概念性的回答,没有任何源代码。这可能对像我一样想要理解的一些读者有用。
它取决于您最初的方法如何架构您的应用程序。基本上有两种方法。
1. 您创建一个活动(基本活动),所有其他视图和屏幕都将是片段。该基本活动包含抽屉和协调布局的实现。实际上,这是我做事情的首选方式,因为具有小型自包含片段将使应用程序开发更加容易和流畅。
2. 如果您已经开始使用每个屏幕一个活动的方式进行应用程序开发,则可能会创建基本活动,并且所有其他活动都从其扩展。基本活动将包含抽屉和协调器实现的代码。需要抽屉实现的任何活动都可以从基本活动中扩展。
我个人更喜欢避免混合使用片段和活动而没有任何组织。这使得开发更加困难并最终会让您陷入困境。如果您已经这样做了,请重构您的代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接