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


206

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

我的问题是,如果这里有人可以做一点教程,它说明了如何将一个导航抽屉用于多个活动。

我首先在这个关于多个活动的 Answer 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);

    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);
}
}

在此活动中,我想要导航抽屉,所以我扩展了“ NavigationDrawer”,而在其他一些活动中,我想要使用相同的导航抽屉

  public class SampleActivity extends NavigationDrawer {...}

我不知道该怎么改变...


1
您可以在此处找到示例。
Naddy

Answers:


188

如果需要导航抽屉,则应使用片段。我上周遵循了本教程,效果很好:

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>

编辑:

我自己遇到了一些困难,因此如果您遇到NullPointerExceptions,那么这里是一个解决方案。在BaseActivity中,将onCreate函数更改为protected void onCreateDrawer()。其余的可以保持不变。在扩展BaseActivity的活动中,按以下顺序放置代码:

    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() ;
}

7
我不想在片段上使用活动,我只想使用使用所有相同导航抽屉的不同活动。我想要活动,因为在那里我可以使用不同类型的布局,例如滑动视图,地图视图...
MEX

135
对于任何相当复杂的应用程序来说,只有一个Activity可能是一项艰巨的任务。使用活动可以从系统中获得很多免费的东西-因此使用多个活动是很重要的一点。我无法想象一个Activity处理任意数量的片段组合之间的通信-只是行不通。
老虎机

1
对不起,我花了这么长时间回答。我编辑了答案。我相信这是您正在寻找的教程。希望这可以帮助。
凯文·范·米洛

2
@KevinvanMierlo您能告诉我您的意思吗:R.id.drawer_layout应该在每个活动中具有完全相同的ID。因为我做你告诉正是在这里,我得到的onCreate(一个NullPointerException)扩展此BaseActivity活动的方法..
Loolooii

1
@KevinvanMierlo顺便说一句,我想你忘了这两行吗?super.onCreate(savedInstanceState); setContentView(R.layout.activity_base);
Loolooii 2014年

34

我找到了最好的实现。它在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;

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


我无法弄清楚他们是如何开始新活动的,它的工作原理完美无缺。这是一个大型应用程序。
hitch.united 2015年

@ hitch.united那是因为他们使用了很多片段和少量活动。
Joaquin Iurchuk

@ hitch.united他们可能会使用覆盖活动的动画overridePendingTransitions
EpicPandaForce 2015年

是加载片段而不是子类活动?
Vikas Pandey'7


8

因此,这个答案已经晚了几年,但是有人会很感激。Android为我们提供了一个新的小部件,它使使用一个导航抽屉进行多项活动变得更加容易。

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

  1. Root Layout是一个android.support.v4.widget.DrawerLayout,它包含两个子元素:一个<include ... />用于包装的布局(请参见2)和一个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只是Linear Layout,其方向为Vertical,它是导航抽屉的标题。

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

  1. 应用栏布局通常现在是一个android.support.design.widget.CoordinatorLayout,这将包括两个孩子:一个android.support.design.widget.AppBarLayout(其中包含android.support.v7.widget.Toolbar)和一个<include ... >用于您的实际内容(请参阅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. 内容布局可以是您想要的任何布局。这是包含活动主要内容的布局(不包括导航抽屉或应用程序栏)。

现在,关于这一切的最酷的事情是,您可以将每个活动包装在这两种布局中,但让NavigationView(请参见步骤1)始终指向activity_main_drawer(或其他名称)。这意味着您将在所有活动上使用相同的(*)导航抽屉。

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

stackoverflow切断了一些封闭的xml括号,但是重要的东西就在那里。
jwehrle

但是您如何看待按钮之类的功能?您必须在每个活动中编写相同的代码吗?
Laur89

是的,因为这些是单独的实例。但是,您可以为活动创建超类,以扩展该代码并将其放置在其中一次。
jwehrle

@jwehrle您能写一个为我们的活动制作超类的例子吗?
CDrosos

公共抽象类MyBaseActivity扩展了AppCompatActivity实现的NavigationView.OnNavigationItemSelectedListener {//实现以下内容:重写public boolean onNavigationItemSelected(@NonNull MenuItem item){}}公共类MyActivity扩展了MyBaseActivity {}
jwehrle

7

在一组活动中重用通用导航抽屉的最简单方法

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;
    }
}

您能否提供使用此基本活动的活动示例?
CDrosos

实际上我不记得任何细节,我认为只是扩展AppBaseActivity setContentViewind默认方式应该起作用。
Levon Petrosyan

6

对于其他想要按照原始海报要求做的事情的人,请考虑使用片段代替Kevin所说的方式。这是有关如何执行此操作的出色教程:

https://github.com/codepath/android_guides/wiki/Fragment-Navigation-Drawer

如果您选择使用活动而不是片段,则将遇到每次导航到新活动时都会重新创建导航抽屉的问题。这会导致每次打开导航抽屉时都出现难看/缓慢的渲染。


5

我的建议是:完全不使用活动,而使用片段,并在显示第一个片段的容器(例如,线性布局)中替换它们。

您可以自定义Android开发人员教程中的代码。

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

建议您在应用程序中使用越来越多的片段,并且应该在应用程序本地仅存在四个基本活动,除了外部活动(例如,FacebookActivity),您在AndroidManifest.xml中提到了这些活动:

  1. SplashActivity:不使用任何片段,并使用全屏主题。

  2. LoginSignUpActivity:完全不需要NavigationDrawer,也不需要后退按钮,因此只需使用普通的工具栏,但至少需要3或4个片段。使用无动作栏主题

  3. HomeActivity或DashBoard活动:使用无操作栏主题。在这里,您需要导航抽屉,随后的所有屏幕都是片段或嵌套片段,直到具有共享抽屉的叶子视图为止。在此活动中,所有设置,用户配置文件等都将在此处作为片段。此处的片段不会添加到后台堆栈中,而是从抽屉菜单项中打开。对于需要后退按钮而不是抽屉的片段,下面有第四种活动。

  4. 没有抽屉的活动。该活动的顶部有一个后退按钮,其中的片段将共享相同的操作栏。这些片段将添加到后台,因为会有导航历史记录。

[有关更多指导,请参阅:https : //stackoverflow.com/a/51100507/787399 ]

快乐编码!


这是一个较旧的帖子。您可以使用片段来确保始终进行一项活动。您一直将碎片替换在一个专用的容器中。当需要向后导航时,放回堆栈中,或者当需要将片段显示为第一个片段时弹出所有片段。
Abhinav Saxena

@ Cabuxa.Mapache请查看我的答案的附件链接以获得更多帮助。我采用了一个通用的BaseActivity,它有助于在附加到它的所有片段中共享ActionBar ToolBar和NavigatonDrawer以及其他组件。
Abhinav Saxena

1

在baseactivity中更新此代码。并且不要忘记在您的活动xml中包含抽屉_列表_标题。

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

并且不要在活动中使用request()。但在单击图像时,抽屉仍然不可见。通过拖动它,就可以看到没有列表项的抽屉。我尝试了很多但没有成功。为此需要一些锻炼...


1

使用@Kevin van Mierlo的答案,您还可以实现多个抽屉。例如,默认菜单位于左侧(开始),而另一个可选菜单位于右侧,仅在装入确定的片段时才显示。

我已经做到了。


1
package xxxxxx;



import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.widget.SearchView;
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.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;


public class loginhome extends AppCompatActivity {
    private Toolbar toolbar;
    private NavigationView navigationView;
    private DrawerLayout drawerLayout;

    // Make sure to be using android.support.v7.app.ActionBarDrawerToggle version.
    // The android.support.v4.app.ActionBarDrawerToggle has been deprecated.
    private ActionBarDrawerToggle drawerToggle;

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

        // Initializing Toolbar and setting it as the actionbar
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


        //Initializing NavigationView


        navigationView = (NavigationView) findViewById(R.id.nav_view);

        //Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {

            // This method will trigger on item Click of navigation menu

            public boolean onNavigationItemSelected(MenuItem menuItem) {


                //Checking if the item is in checked state or not, if not make it in checked state
                if(menuItem.isChecked()) menuItem.setChecked(false);
                else menuItem.setChecked(true);

                //Closing drawer on item click
                drawerLayout.closeDrawers();

                //Check to see which item was being clicked and perform appropriate action
                switch (menuItem.getItemId()){


                    //Replacing the main content with ContentFragment Which is our Inbox View;
                    case R.id.nav_first_fragment:
                        Toast.makeText(getApplicationContext(),"First fragment",Toast.LENGTH_SHORT).show();
                         FirstFragment fragment = new FirstFragment();
                        android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
                        fragmentTransaction.replace(R.id.frame,fragment);
                        fragmentTransaction.commit();
                        return true;

                    // For rest of the options we just show a toast on click
                    case R.id.nav_second_fragment:
                        Toast.makeText(getApplicationContext(),"Second fragment",Toast.LENGTH_SHORT).show();
                        SecondFragment fragment2 = new SecondFragment();
                        android.support.v4.app.FragmentTransaction fragmentTransaction2 = getSupportFragmentManager().beginTransaction();
                        fragmentTransaction2.replace(R.id.frame,fragment2);
                        fragmentTransaction2.commit();
                        return true;

                    default:
                        Toast.makeText(getApplicationContext(),"Somethings Wrong",Toast.LENGTH_SHORT).show();
                        return true;

                }
            }
        });

        // Initializing Drawer Layout and ActionBarToggle
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.drawer_open, R.string.drawer_close){

            @Override
            public void onDrawerClosed(View drawerView) {
                // Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
                super.onDrawerClosed(drawerView);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                // Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank

                super.onDrawerOpened(drawerView);
            }
        };

        //Setting the actionbarToggle to drawer layout
        drawerLayout.setDrawerListener(actionBarDrawerToggle);

        //calling sync state is necessay or else your hamburger icon wont show up
        actionBarDrawerToggle.syncState();







    }

将此用于您的toolbar.xml

<?xml version="1.0" encoding="utf-8"?>

    <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:elevation="4dp"
        android:id="@+id/toolbar"
        android:theme="@style/ThemeOverlay.AppCompat.Dark"


        >

    </android.support.v7.widget.Toolbar>

如果要使用,将其用作导航标题

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:background="?attr/colorPrimaryDark"
    android:padding="16dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    android:orientation="vertical"
    android:gravity="bottom">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:id="@+id/navhead"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:textColor="#ffffff"
            android:text="tanya"
            android:textSize="14sp"
            android:textStyle="bold"

            />

        <TextView
            android:id="@+id/email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffff"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="5dp"
            android:text="tanya.com"
            android:textSize="14sp"
            android:textStyle="normal"

            />
    </LinearLayout>
    <de.hdodenhof.circleimageview.CircleImageView
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_below="@+id/imageView"
        android:layout_marginTop="15dp"

        android:src="@drawable/face"
        android:id="@+id/circleView"
        />



</RelativeLayout>

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

抽屉的活动必须继承this BaseAppCompatActivitysuper.onCreate在设置内容后调用(实际上,可以将其移动到某些init方法),并且在其布局中具有ID的相应元素


我想尝试您的解决方案,但出现此错误:“此活动已经具有窗口装饰提供的操作栏”。我想在3个活动之间切换,并且每个活动都有自己的应用程序栏。您认为这可能吗?
davoid

我认为,在这种情况下,您需要将操作栏移动到片段。据我所知,在我们的应用程序中,我们使用了NoActionBar主题并提供了兼容性工具栏。
Pavlus

@Pavlus在第二个活动中代码是什么样的?class TrackActivity:BaseAppCompatActivity(){吗?
Craig P

0

我的回答只是一个概念性的回答,没有任何源代码。对于像我这样的一些读者来说,这可能很有用。

这取决于您最初如何构建应用程序。基本上有两种方法。

  1. 您创建一个活动(基本活动),所有其他视图和屏幕均为片段。该基本活动包含“抽屉和协调器布局”的实现。实际上,这是我的首选方式,因为拥有独立的小片段将使应用程序开发更轻松,更流畅。

  2. 如果您以活动开始您的应用程序开发,每个屏幕一个,那么您可能会创建基础活动,所有其他活动都将以此为基础。基本活动将包含抽屉和协调器实现的代码。需要抽屉实现的任何活动都可以从基本活动扩展。

我个人更希望避免在没有任何组织的情况下混合使用片段和活动。这使开发更加困难,最终使您陷于困境。如果已完成,请重构代码。


-1

使用片段在MainActivity中创建导航抽屉。 现在,在要使用相同导航抽屉的所有其他活动中,
在MainActivity中初始化导航抽屉,
将DrawerLayout作为基础,将片段作为导航抽屉。只需在片段中设置android:name即可指向片段Java文件。您无需在其他活动中初始化该片段。
您可以通过滑动其他活动(例如在Google Play商店应用中)来访问导航抽屉

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.