Same Navigation Drawer in different Activities

前端 未结 12 1439
执念已碎
执念已碎 2020-11-22 04:24

I made a working navigation drawer like it\'s shown in the tutorial on the developer.android.com website. But now, I want to use one Navigation Drawer, i created in the Navi

相关标签:
12条回答
  • 2020-11-22 05:17

    If you want a navigation drawer, you should use fragments. I followed this tutorial last week and it works great:

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

    You can also download sample code from this tutorial, to see how you can do this.


    Without fragments:

    This is your BaseActivity Code:

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

    All the other Activities that needs to have a navigation drawer should extend this Activity instead of Activity itself, example:

    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>
    

    Edit:

    I experienced some difficulties myself, so here is a solution if you get NullPointerExceptions. In BaseActivity change the onCreate function to protected void onCreateDrawer(). The rest can stay the same. In the Activities which extend BaseActivity put the code in this order:

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

    This helped me fix my problem, hope it helps!

    This is how you can create a navigation drawer with multiple activities, if you have any questions feel free to ask.


    Edit 2:

    As said by @GregDan your BaseActivity can also override setContentView() and call onCreateDrawer there:

    @Override 
    public void setContentView(@LayoutRes int layoutResID) 
    { 
        super.setContentView(layoutResID); 
        onCreateDrawer() ;
    }
    
    0 讨论(0)
  • 2020-11-22 05:18

    With @Kevin van Mierlo 's answer, you are also capable of implementing several drawers. For instance, the default menu located on the left side (start), and a further optional menu, located on the right side, which is only shown when determinate fragments are loaded.

    I've been able to do that.

    0 讨论(0)
  • 2020-11-22 05:26

    I've found the best implementation. It's in the Google I/O 2014 app.

    They use the same approach as Kevin's. If you can abstract yourself from all unneeded stuff in I/O app, you could extract everything you need and it is assured by Google that it's a correct usage of navigation drawer pattern. Each activity optionally has a DrawerLayout as its main layout. The interesting part is how the navigation to other screens is done. It is implemented in BaseActivity like this:

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

    This differs from the common way of replacing current fragment by a fragment transaction. But the user doesn't spot a visual difference.

    0 讨论(0)
  • 2020-11-22 05:26

    I do it in Kotlin like this:

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

    Activities for drawer must inherit this BaseAppCompatActivity, call super.onCreate after content is set (actually, can be moved to some init method) and have corresponding elements for ids in their layout

    0 讨论(0)
  • 2020-11-22 05:28

    Create Navigation drawer in your MainActivity using fragment.
    Initialize the Navigation Drawer in MainActivity
    now in all other activities you want to use same Navigation Drawer put DrawerLayout as base and fragment as navigation drawer. Just set android:name in your fragment pointing to your fragment Java file. You won't need to initialize the fragment in other Activities.
    You can access Nav Drawer by swipe in other activities like in Google Play Store app

    0 讨论(0)
  • 2020-11-22 05:29

    For anyone else looking to do what the original poster is asking, please consider to use fragments instead the way Kevin said. Here is an excellent tutorial on how to do that:

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

    If you choose to instead use activities instead of fragments you are going to run into the problem of the nav drawer being re-created every time you navigate to a new activity. This results in an ugly/slow rendering of the nav drawer each time.

    0 讨论(0)
提交回复
热议问题