Android:navigation 用法
Google 在2018年推出了 Android Jetpack,在Jetpack里有一种管理fragment的新架构模式,那就是navigation. 字面意思是导航,但是除了做APP引导页面以外.也可以使用在App主页分tab的情况.. 甚至可以一个功能模块就一个activity大部分页面UI都使用fragment来实现,而navigation就成了管理fragment至关重要的架构.
但是,它不单单只能管理fragment也可以管理activity.这点你格外注意.
你的Android studio 必需升级到3.2版本以上,此博客正在写的时候Android studio已经到达3.5,所以升级到最新版本即可.
一、使用流程
1、创建 navigation 资源文件
[1]创建 navigation 目录
选中项目资源文件夹 res ,右击新建资源目录,Resource type 选 navigation(注意 navigation 类型只有在Android studio3.2版本以上才能出现)。
[2]创建 navigation 文件
选中项目资源文件夹 navigation,右击,新建 Navigation Resource File
2、配置 navigation.xml 来管理 fragment
[1]打开 navigation.xml,使用视图手动配置。
[2]切换到Design模式后,我们可以在左上角点击添加图标。
第一个 Create new destinattion,字面意思创建一个新目标。
第二个 placeholder,这个就是重点了. 这是一个管理fragment跳转的节点,我们点击后可以创建它.为了了解它的使用方式,点击3次创建三个节点创建的 navigation.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/navigation"
app:startDestination="@id/first">
<fragment android:id="@+id/first"
android:name="com.bhs.navigationdemo.fragments.FirstFragment"
android:label="BlankFragment"
tools:layout="@layout/fragment_first">
<action
android:id="@+id/action_one_to_two"
app:destination="@id/second" />
</fragment>
<fragment android:id="@+id/second"
android:name="com.bhs.navigationdemo.fragments.SecondFragment"
android:label="BlankFragment"
tools:layout="@layout/fragment_second">
<action
android:id="@+id/action_two_to_three"
app:destination="@id/third" />
</fragment>
<fragment android:id="@+id/third"
android:name="com.bhs.navigationdemo.fragments.ThirdFragment"
android:label="BlankFragment"
tools:layout="@layout/fragment_third"/>
</navigation>
3、navigation 相关知识
[1]在 <navigation> 里的属性:
1.android:id="@+id/demo_nav" 这个属性是你这个xml文件navigation的id,很重要,我们需要在activity的xml布局里引用,记得写上不要忘记
2.app:startDestination="@id/one" 这个属性是你首次加载的第一个页面,很重要,一般就是第一个fragment
[2]在 <fragment> 里的属性:
其实就是一个节点你也可以理解成一个fragment
1.android:id="@+id/one" 每一个fragment节点都需要有自己的id,很重要. 我们需要在后面的节点上使用这些id指定跳转目标
2.android:name="demo.yt.com.demo.fragment.BlankFragment" 这个属性是你这个节点所对应的fragment(需要你导入指定的fragment文件路径),这个很重要
3.android:label="BlankFragment" 一个标签名称,用于记录这个节点的标签信息(大概可能是在代码里的Intent里获取来知晓此次是那个fragment节点在跳转,没深究了)
4.tools:layout="@layout/fragment_blank" 这个属性不是重要的,设置它后你可以在切换到Design模式后看到,视图页面的fragment的预览图(就在上面的图片里,可以直接看到fragment效果)
[3]在 <action> 里的属性:
action 负责编写跳转动作
1. android:id="@+id/action_one_to_two" 这个很重要,它是这个跳转动作的id, 这个id我们将在后面的代码中调用,用于执行fragment的跳转
2. app:destination="@id/two" 跳转的目标fragment,这个很重要
4、让navigation与Activity关联起来
现在我们已经创建了 navigation ,但是使用它还需要一个根 Activity,它毕竟还是需要依托 Activity 的。
[1]创建 MainActivity
<?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/demo_fragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/navigation"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
[2]fragment的一些属性
1.android:name="androidx.navigation.fragment.NavHostFragment" 这个非常重要,这是你告知fragment需要使用navigation模式的关键属性,另外它是固定死的.你必需写.
2. app:defaultNavHost="true" 这是你实现物理按键(比如返回键),是按一下退出一个fragment 还是直接退出这个Activity的关键属性
3.app:navGraph="@navigation/demo_nav" 很重要,这就是我们前面创建的navigation的xml文件
[3]创建三个 Fragment,布局代码如下:
fragment_first.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.FirstFragment">
<!-- TODO: Update blank fragment layout -->
<Button
android:id="@+id/btn_goto_second"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="go to second" />
</LinearLayout>
fragment_second.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".fragments.SecondFragment">
<!-- TODO: Update blank fragment layout -->
<Button
android:id="@+id/btn_goto_third"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="go to third" />
<Button
android:id="@+id/btn_back"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="back" />
</LinearLayout>
fragment_third.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.ThirdFragment">
<!-- TODO: Update blank fragment layout -->
<Button
android:id="@+id/btn_back"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="back" />
</LinearLayout>
5、实现fragment跳转与返回
进入到 MainActivity后,首先会自动加载到第一个fragment. 然后我们看看如何跳转到其他fragment中
[1]从第一个碎片跳转到第二个碎片,代码如下:
public class FirstFragment extends Fragment {
private Button mBtnInputFragment2;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_first, container, false);
;
mBtnInputFragment2 = view.findViewById(R.id.btn_goto_second);
mBtnInputFragment2.setOnClickListener((View v) -> {
Navigation.findNavController(getView()).navigate(R.id.action_one_to_two);//这个id就是navigation里的action的id
});
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onDetach() {
super.onDetach();
}
}
[2]从第二个碎片可跳转到第三个碎片,也可返回到第一个碎片,代码如下:
public class SecondFragment extends Fragment {
private Button mBtnGo, mBtnBack;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_second, container, false);
mBtnGo = view.findViewById(R.id.btn_goto_third);
mBtnBack = view.findViewById(R.id.btn_back);
mBtnGo.setOnClickListener((View v) -> {
Navigation.findNavController(getView()).navigate(R.id.action_two_to_three); //进入第三个碎片
});
mBtnBack.setOnClickListener((View v) -> {
Navigation.findNavController(getView()).popBackStack(); //返回上一个碎片
});
return view;
}
}
[3]从第三个碎片可返回到第二个碎片,代码如下:
public class ThirdFragment extends Fragment {
private Button mBtnBack;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_third, container, false);
mBtnBack = view.findViewById(R.id.btn_back);
mBtnBack.setOnClickListener((View v) -> {
Navigation.findNavController(getView()).popBackStack(); //返回上一个碎片
});
return view;
}
}