NavigationView在toolbar左侧按钮相关实现

本文介绍了在Android开发中,如何实现NavigationView与Toolbar左侧按钮的功能。主要探讨了两种方法:一是通过ActionBarDrawerToggle,适用于简单跳转;二是利用AppBarConfiguration,更适合在含有多个Fragment的Activity中进行有效导航。详细讲解了相关布局设置和代码实现。

一:概述

在学习Google官网demo,sunflower其中用到了NavigationUI的相关实现,在自己实现的过程中顶层导航栏左侧的按钮总是或多或少的出现不同的问题(学的比较渣,于是自己调试了好几天,加之对于API的不熟悉,因此又拖慢了进程)

在我调试的过程中,关于toolbar左侧导航按钮的实现有两种办法。一种是用了ActionBarDrawerToggle的API实现,这个的功能只是实现了打开左侧导航栏然后完成相应的跳转之后在其后的其他活动或者(fragment)中就无作用,这只适合简单的跳转。而对于另一个API是AppBarConfiguration,因为我的demo来说,实现的是一个Activity作为底容器,实现多个fragment的跳转,并用到了Navigation相关组件,AppBarConfiguration配合这个demo实现,可以更有效的组织和导航相应的fragment。

 

二:ActionBarDrawerToggle的使用

在布局中添加ToolBar和NavigationView

<android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <android.support.design.widget.AppBarLayout
                android:id="@+id/appbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="@style/AppTheme.PopupOverlay">

                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:popupTheme="@style/AppTheme.PopupOverlay"/>

            </android.support.design.widget.AppBarLayout>

            <fragment
                android:id="@+id/garden_nav_fragment"
                android:name="androidx.navigation.fragment.NavHostFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:defaultNavHost="true"
                app:navGraph="@navigation/nav_garden"/>

        </LinearLayout>

        <android.support.design.widget.NavigationView
            android:id="@+id/navigation_view"
            style="@style/Widget.MaterialComponents.NavigationView"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header"
            app:menu="@menu/menu_navigation"/>

    </android.support.v4.widget.DrawerLayout>

在MainAcitivity的OnCreate()方法中实现

private Toolbar toolbar;

    private ActivityMainBinding binding;
    private NavController navController;
    private AppBarConfiguration appBarConfiguration;
    private DrawerLayout drawerLayout;
    private NavigationView navView;
    private ActionBarDrawerToggle toggle;

......

toolbar = binding.toolbar;

        drawerLayout = binding.drawerLayout;
        setSupportActionBar(toolbar);

        navView = binding.navigationView;
        toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();
......

@Override
    public void onBackPressed() {
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }
......

实现效果如下:

 

三:AppBarConfiguration的使用

相关API
NavController
AppBarConfiguration
NavigationUI

 

XML布局:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

    </data>

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <android.support.design.widget.AppBarLayout
                android:id="@+id/appbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="@style/AppTheme.PopupOverlay">

                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:popupTheme="@style/AppTheme.PopupOverlay"/>

            </android.support.design.widget.AppBarLayout>

            <fragment
                android:id="@+id/garden_nav_fragment"
                android:name="androidx.navigation.fragment.NavHostFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:defaultNavHost="true"
                app:navGraph="@navigation/nav_garden"/>

        </LinearLayout>

        <android.support.design.widget.NavigationView
            android:id="@+id/navigation_view"
            style="@style/Widget.MaterialComponents.NavigationView"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header"
            app:menu="@menu/menu_navigation"/>

    </android.support.v4.widget.DrawerLayout>

</layout>

截下来就是代码的实现,相关的说明在代码的注释中体现:

package com.example.mysunflower;

import android.databinding.DataBindingUtil;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
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.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;

import com.example.mysunflower.databinding.ActivityMainBinding;

import static androidx.navigation.ui.NavigationUI.setupActionBarWithNavController;

public class MainActivity extends AppCompatActivity {
    /*
    * NavController绑定容纳fragment的容器,实现对于多个Fragment的控制
    *
    * 以下代码涉及到AppBarConfiguration, Toolbar, 左侧导航栏NavigationView
    * 大体过程就是将这几个可视化或自动管理的组件与NavController关联,实现对多个fragment的有效组织管理
    * */

    private ActivityMainBinding binding;

    /*
    * 用Navigation构建项目时,用到的一些API
    * 具体使用方法请参考官方文档
    * */
    private NavController navController;
    private AppBarConfiguration appBarConfiguration;
    private DrawerLayout drawerLayout;

    /*
    * 简单的单界面跳转API,作为测试使用
    * */
    private ActionBarDrawerToggle toggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        /*
        * 实例化
        * */
        drawerLayout = binding.drawerLayout;
        navController = Navigation.findNavController(this, R.id.garden_nav_fragment);

        /*
        * 配置AppBarConfiguration
        * 将其于navController的实现,与主布局绑定,其内部自动实现相应功能
        * */
        appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph())
                .setDrawerLayout(drawerLayout)
                .build();

        /*
        * 添加toolbar的支持
        * */
        setSupportActionBar(binding.toolbar);
        /*setupActionBarWithNavController(this, navController);*/

        /*
        * 用NavigationUI将toolbar与appBarConfiguration,toolbar会自动切换相应fragment的名称
        * */
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);

        /*toggle = new ActionBarDrawerToggle(this, drawerLayout, binding.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();*/

        /*
        * 将左侧导航栏与navController绑定
        * */
        NavigationUI.setupWithNavController(binding.navigationView, navController);

        LoadNavItemSelListener();
    }


    /*
    * 实现程序的后退功能
    * 将AppBarConfiguration与navController,传递到NavigationUI.navigateUp()实现顶部导航栏左侧对于fragment切换的管理
    * */
    @Override
    public boolean onSupportNavigateUp() {
        NavigationUI.navigateUp(navController, appBarConfiguration);

        /*
         * 注意:此注释处调用了其他API下的函数,导致整个功能实现异常
         * 前期也因为自己对API的不熟悉,在此处浪费了大量时间,一定不能调错函数
         * */
/*
        return navController.navigateUp() || super.onSupportNavigateUp();
*/
        return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp();
    }

    /*@Override
    public void onBackPressed() {
        super.onBackPressed();
        if (drawerLayout == null){
            Log.d(String.valueOf(MainActivity.this), "onBackPressed: drawerLayout == null");
        }
        if (drawerLayout.isDrawerOpen(binding.navigationView)){
            drawerLayout.closeDrawer(binding.navigationView);
        }else {
            super.onBackPressed();
        }
    }*/

   @Override
    public void onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    private void LoadNavItemSelListener() {
        binding.navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                switch (menuItem.getItemId()){
                    case R.id.garden_fragment:
                        navController.navigate(R.id.action_gardenFragment_to_plantDetailFragment);
                        break;
                    case R.id.plant_list_fragment:
                        navController.navigate(R.id.action_gardenFragment_to_plantListFragment2);
                        break;
                }

                drawerLayout.closeDrawer(GravityCompat.START);

                return true;
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_toolbar, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return super.onOptionsItemSelected(item);
    }
}

 

笔者只是初入Android开发的小白,若有错误之处请多多包含,当然更希望大家批评指正,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值