zoukankan      html  css  js  c++  java
  • Android Jetpack -- Navigation 篇

    Navigation是指允许用户在应用程序中浏览、进入和退出不同内容的Fragment 。Navigation能够实现从简单的按钮单击到更复杂的模式,如应用程序栏和导航抽屉。导航组件还通过遵循一套既定的原则来确保一致和可预测的用户体验。

    Navigation的原则:

    • 固定的起始位置:除去登陆等一次性界面,用户在启动App最先看到的界面需要为一个固定的起始界面。
    • Navigation的表现形式为堆栈形式:Navigation类似于栈,栈顶为用户所看到的界面,界面的切换总是在栈顶进行,导航到目标后,目标位于栈顶。
    • 标题栏的回退应该和返回键的功能一样,但是标题栏不能退出应用:这个也很容易理解,因为两个的定义就存在本质的区别。
    • Deep Link:比如从浏览器跳转到其他App时,用户首先看到的应该还是浏览器的那个页面,没有其他界面的跳转过程。

    Navigation有三个主要的部分:

    • Navigation graph:就是Navigatation的xml文件,包含所有的需要跳转的目标
    • NavHost:一个容器,用于显示
    • NavController:控制跳转流程

    具体实现(简单例子)

    首先新建新建两个Fragment,HomeFragment和DetailFragment

    在其对应生成的xml文件中添加一些控件

    frament_home.xml

     <?xml version="1.0" encoding="utf-8"?>
     <FrameLayout 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=".HomeFragment">
     
         <androidx.constraintlayout.widget.ConstraintLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent">
     
             <androidx.constraintlayout.widget.Guideline
                 android:id="@+id/guideline"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:orientation="horizontal"
                 app:layout_constraintGuide_begin="335dp"
                 app:layout_constraintGuide_percent="0.5" />
     
             <TextView
                 android:id="@+id/textView"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="8dp"
                 android:layout_marginTop="8dp"
                 android:layout_marginEnd="8dp"
                 android:layout_marginBottom="8dp"
                 android:text="Home"
                 android:textSize="36sp"
                 app:layout_constraintBottom_toTopOf="@+id/guideline"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toTopOf="parent"
                 app:layout_constraintVertical_bias="0.8" />
     
             <Button
                 android:id="@+id/button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="8dp"
                 android:layout_marginTop="8dp"
                 android:layout_marginEnd="8dp"
                 android:layout_marginBottom="8dp"
                 android:text="Button"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toTopOf="@+id/guideline"
                 app:layout_constraintVertical_bias="0.2" />
         </androidx.constraintlayout.widget.ConstraintLayout>
     </FrameLayout>

    fragment_detail.xml

     <?xml version="1.0" encoding="utf-8"?>
     <FrameLayout 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=".DetailFragment">
     
         <androidx.constraintlayout.widget.ConstraintLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent">
     
             <androidx.constraintlayout.widget.Guideline
                 android:id="@+id/guideline2"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:orientation="horizontal"
                 app:layout_constraintGuide_begin="348dp"
                 app:layout_constraintGuide_percent="0.5" />
     
             <TextView
                 android:id="@+id/textView2"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="8dp"
                 android:layout_marginTop="8dp"
                 android:layout_marginEnd="8dp"
                 android:layout_marginBottom="8dp"
                 android:text="Detail"
                 android:textSize="36sp"
                 app:layout_constraintBottom_toTopOf="@+id/guideline2"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toTopOf="parent"
                 app:layout_constraintVertical_bias="0.8" />
     
             <Button
                 android:id="@+id/button2"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="8dp"
                 android:layout_marginTop="8dp"
                 android:layout_marginEnd="8dp"
                 android:layout_marginBottom="8dp"
                 android:text="Button"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toTopOf="@+id/guideline2"
                 app:layout_constraintVertical_bias="0.2" />
         </androidx.constraintlayout.widget.ConstraintLayout>
     </FrameLayout>

    接着在activity_main中为Fragment添加NavHost容器

     <?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">
     
         <fragment
             android:id="@+id/fragment"
             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>

    再新建navigation文件夹新建my_nav_graph,添加Fragment到其中

     建立Fragment之间的跳转关系,当然也可以直接在xml文件里写,不过这样会有点麻烦。

    HomeFragment.java

     package com.example.navigationdemo;
     
     
     import android.os.Bundle;
     
     import androidx.fragment.app.Fragment;
     import androidx.navigation.NavController;
     import androidx.navigation.Navigation;
     
     import android.view.LayoutInflater;
     import android.view.View;
     import android.view.ViewGroup;
     import android.widget.Button;
     
     import com.google.android.material.internal.NavigationMenuItemView;
     
     
     /**
      * A simple {@link Fragment} subclass.
      */
     public class HomeFragment extends Fragment {
     
     
         public HomeFragment() {
             // Required empty public constructor
         }
     
     
         @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                  Bundle savedInstanceState) {
             // Inflate the layout for this fragment
             return inflater.inflate(R.layout.fragment_home, container, false);
         }
     
         @Override
         public void onActivityCreated(Bundle savedInstanceState) {
             super.onActivityCreated(savedInstanceState);
             Button button;
             button = getView().findViewById(R.id.button);
             button.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
                     NavController controller = Navigation.findNavController(v);
                     controller.navigate(R.id.action_homeFragment_to_detailFragment);
                 }
             });
         }
     }

    DetaiFragment.java

     package com.example.navigationdemo;
     
     
     import android.os.Bundle;
     
     import androidx.fragment.app.Fragment;
     import androidx.navigation.Navigation;
    
     import android.view.LayoutInflater;
     import android.view.View;
     import android.view.ViewGroup;
     
     
     /**
      * A simple {@link Fragment} subclass.
      */
     public class DetailFragment extends Fragment {
     
     
         public DetailFragment() {
             // Required empty public constructor
         }
     
     
         @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                  Bundle savedInstanceState) {
             // Inflate the layout for this fragment
             return inflater.inflate(R.layout.fragment_detail, container, false);
         }
     
         @Override
         public void onActivityCreated(Bundle savedInstanceState) {
             super.onActivityCreated(savedInstanceState);
             getView().findViewById(R.id.button2).setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_detailFragment_to_homeFragment));
     
         }
     }

    这样就能实现两个界面之间的跳转。

    如果想要实现手机屏幕左上角   的返回功能,则需要在MainActivity中添加代码

     package com.example.navigationdemo;
     
     import androidx.appcompat.app.AppCompatActivity;
     import androidx.navigation.NavController;
     import androidx.navigation.Navigation;
     import androidx.navigation.ui.NavigationUI;
     
     import android.os.Bundle;
     
     public class MainActivity extends AppCompatActivity {
    
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.activity_main);
             NavController controller = Navigation.findNavController(this, R.id.fragment);
             NavigationUI.setupActionBarWithNavController(this, controller);
         }
     
         @Override
         public boolean onSupportNavigateUp() {
             NavController controller = Navigation.findNavController(this, R.id.fragment);
             return controller.navigateUp();
             //return super.onSupportNavigateUp();
         }
     }

     Fragement间数据传递

    这里也没有很大的变化,也是通过Bundle来传递的,然后接收方通过getArguments()来获取到对应的Bundle从而取出数据。

    Fragment转换动画

    是可以直接在Navigation graph中直接设置转换动画,极大减少了工作量。当然如果对自带动画效果不满意,也可以创建Animation资源自己编写xml文件来创建动画。

    但要切记,在实际工程中不要把转换动画设置的太过花哨,以免影响用户的操作体验。

  • 相关阅读:
    关于sizeof表达式作为数组元素个数的编译
    【deque】滑动窗口、双端队列解决数组问题
    【二叉树】重建二叉树
    字符数组与字符串指针
    【STL】C中的qsort与C++中的sort
    对C++不是类型安全语言的理解
    【vector】创建一个二维vector当作二维数组用
    批量处理改变文件名、文件后缀名
    位运算
    关于sqlserver帐号被禁用问题
  • 原文地址:https://www.cnblogs.com/best-hym/p/12213210.html
Copyright © 2011-2022 走看看