【JetPack】Navigation知识点总结

1、Navigation Graph:

一种新的XML资源文件,包含应用程序所有的页面,以及页面间的关系。

复制代码
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/my_nav_graph"
    app:startDestination="@id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.navigation.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" >
        <action
            android:id="@+id/action_homeFragment_to_detailFragment"
            app:destination="@id/detailFragment" />
    </fragment>
    <fragment
        android:id="@+id/detailFragment"
        android:name="com.example.navigation.DetailFragment"
        android:label="fragment_detail"
        tools:layout="@layout/fragment_detail" >
        <action
            android:id="@+id/action_detailFragment_to_homeFragment"
            app:destination="@id/homeFragment" />
    </fragment>
</navigation>

2、NavHostFragment:

一个特殊的Fragment,可以将它看作是其他Fragment的容器,Navigation Graph中的Fragment正是通过NavHostFragment进行展示的。

复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentContainerView"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="409dp"
        android:layout_height="729dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/my_nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

3、NavController:

用于在代码中完成Navigation Graph中具体的页面切换工作。

复制代码
MainActivity.java
public class MainActivity extends AppCompatActivity {
    NavController navController;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		// 这样写会报错
    	// NavController navController = Navigation.findNavController(this, R.id.fragmentContainerView);
        // 需要先通过id获取到对应的NavHostFragment容器
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
        if (navHostFragment != null) {
       		 // 如果不为空,再获取到的容器对应的NavController
            navController = navHostFragment.getNavController();
        } else {
            throw new RuntimeException("NavHostFragment not found");
        }
        // 该代码的主要目的是将 ActionBar(或 Toolbar)与 NavController 关联起来,以便在使用 Android 导航组件时,ActionBar 可以自动更新其显示内容
        NavigationUI.setupActionBarWithNavController(this, navController);
    }
    
    @Override
    public boolean onSupportNavigateUp() {
        // header上返回按键好用
        return navController.navigateUp();
    }
}
HomeFragment.java
@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Button button = getView().findViewById(R.id.button);
        button.setOnClickListener(view -> {
        	// 由于最外层设置了NavController,所以这里可以通过容器中的view找到NavController
            NavController navController = Navigation.findNavController(view);
            // 通过NavController进行导航,确定目的地
            navController.navigate(R.id.action_homeFragment_to_detailFragment);
        });
    }
DetailFragment.java
@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Button button = getView().findViewById(R.id.button2);
        button.setOnClickListener((v)->{
            // 由于最外层设置了NavController,所以这里可以通过容器中的view找到NavController
            NavController navController = Navigation.findNavController(v);
            // 通过NavController进行导航,确定目的地
            navController.navigate(R.id.action_detailFragment_to_homeFragment);
        });
    }

三者之间的关系

当你想切换Fragment时,使用NavController对象,告诉它你想要去Nlavigation Graph中的哪个Fragment,NavController会将你想去的Fragment展示NavHostFragment中
实现顺序

1.创建Fragment

2.创建navgation_graph,指定fragment切换逻辑

3.在Activity的页面中添加navHostFragmrnt容器进行界面显示

4.在Activity中通过navHostFragmrnt获取到navController,并设置bar和fragment的对应关系,以及bar上返回按键生效

5.在需要触发fragment切换的位置通过获取navController进行导航,设置对应的action,确认触发后目的地
添加页面切换动画

页面之间参数传递

方法一:直接传递bundle对象(接收数据时需要知道对应key值以及value类型,并且需要判空)

复制代码
        Bundle bundle = new Bundle();
        bundle.putString("user_name", "Jay");
        NavController navController = Navigation.findNavController(view);
        navController.navigate(R.id.action_homeFragment_to_detailFragment, bundle);

接收bundle对象

复制代码
		Bundle arguments = getArguments();
		String userName = null;
		if (arguments != null) {
		    userName = arguments.getString("user_name");
		    Log.d("userName", "" + userName);
		}

方法二:引入arg插件

复制代码
		dependencies {
		    // 添加 safe-arg 插件依赖
		    classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.4.0")
		}
		plugins {
		    id 'androidx.navigation.safeargs'
		}

        Bundle bundle = new HomeFragmentArgs.Builder()
                .setUserName("Jay")
                .setAge(20)
                .build().toBundle();
  
        HomeFragmentArgs args = HomeFragmentArgs.fromBundle(getArguments());
        String username = args.getUserName();
        int age = args.getAge();
        Log.d("Test", "userName = " + userName + "age = " + age);

NavigationUI的使用场景

Fragment切换时,设计到AppBar上的内容显示,为了方便统一管理引入NavigationUI

复制代码
public class MainActivity extends AppCompatActivity {
    private NavController navController;
    private AppBarConfiguration appBarConfiguration;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
        if (navHostFragment != null) {
            navController = navHostFragment.getNavController();
        }
        appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
        // 将Appbar与Navigation建立联系
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.menu_settings, menu);
        return true;
    }
    // 响应Meun的点击事件
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        return NavigationUI.onNavDestinationSelected(item, navController) || super.onOptionsItemSelected(item);
    }
    // 响应AppBar的返回按键
    @Override
    public boolean onSupportNavigateUp() {
        return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp();
    }
}

跳转后的假面不显示meun

复制代码
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        setHasOptionsMenu(true);
        return inflater.inflate(R.layout.fragment_setting, container, false);
    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        menu.clear();
        super.onCreateOptionsMenu(menu, inflater);
    }

监听页面切换完成的回调

复制代码
        // 监听界面切换完成
        navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController navController, @NonNull NavDestination navDestination, @Nullable Bundle bundle) {
                Log.d("test","onDestinationChanged");
            }
        });

深层链接DeepLink之PendingIntent

复制代码
private void sendNotifycation() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel myChannel = new NotificationChannel(getActivity().getPackageName(), "MyChannel", NotificationManager.IMPORTANCE_DEFAULT);
            myChannel.setDescription("My NotificationChannel");
            NotificationManager notificationManager = getActivity().getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(myChannel);
        }

        NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity(), getActivity().getPackageName())
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle("Deep Link")
                .setContentText("点我")
                .setPriority(NotificationManager.IMPORTANCE_DEFAULT)
                .setContentIntent(getPendingIntent());
        // 发送通知
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());

        if (ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        notificationManager.notify(notifyId++, builder.build());
    }

    private PendingIntent getPendingIntent() {
        Bundle bundle = new Bundle();
        bundle.putString("name","Jay");
        return Navigation.findNavController(getActivity(),R.id.button)
                .createDeepLink()
                .setGraph(R.navigation.my_nav_graph)
                .setDestination(R.id.detailFragment)
                .setArguments(bundle)
                .createPendingIntent();
    }

深层链接DeepLink之Url

相关推荐
幻雨様5 小时前
UE5多人MOBA+GAS 45、制作冲刺技能
android·ue5
Jerry说前后端7 小时前
Android 数据可视化开发:从技术选型到性能优化
android·信息可视化·性能优化
Meteors.8 小时前
Android约束布局(ConstraintLayout)常用属性
android
alexhilton8 小时前
玩转Shader之学会如何变形画布
android·kotlin·android jetpack
whysqwhw13 小时前
安卓图片性能优化技巧
android
风往哪边走13 小时前
自定义底部筛选弹框
android
Yyyy48214 小时前
MyCAT基础概念
android
Android轮子哥14 小时前
尝试解决 Android 适配最后一公里
android
雨白15 小时前
OkHttp 源码解析:enqueue 非同步流程与 Dispatcher 调度
android
风往哪边走16 小时前
自定义仿日历组件弹框
android