android入门直接学jetpack,即学即用Android Jetpack - Navigation

技术不止,文章有料,加 JiuXinDev 入群,Android 搬砖路上不孤单

前言

即学即用Android Jetpack系列Blog的目的是通过学习Android Jetpack完成一个简单的Demo,本文是即学即用Android Jetpack系列Blog的第一篇。

记得去年第一次参加谷歌开发者大会的时候,就被Navigation的图形导航界面给迷住了,一句卧槽就代表了小王的全部心情~,我们可以看一下来自网络的一张图片:

66b93df4b7a6

来自网络的一张图片

所以,Android Jetpack学习之旅就开始了。

66b93df4b7a6

Android Jetpack

本人打算每周学习一个组件(上图的左上区域),最后将所学的组件组成一个简单的Demo。同时,刚刚过去的2019年谷歌开发者大会宣布亲儿子Kotlin成为开发Android的首选语言,所以本文的Demo也将都会采用Kotlin编写。

本章结束后登录部分完成效果:

66b93df4b7a6

Navigation.gif

语言:Kotlin

Demo地址:https://github.com/mCyp/Hoo

目录

一、简介

1. 定义

Navigation是什么呢?谷歌的介绍视频上说:

Navigation是一个可简化Android导航的库和插件

更确切的来说,Navigation是用来管理Fragment的切换,并且可以通过可视化的方式,看见App的交互流程。这完美的契合了Jake Wharton大神单Activity的建议。

2. 优点

处理Fragment的切换(上文已说过)

默认情况下正确处理Fragment的前进和后退

为过渡和动画提供标准化的资源

实现和处理深层连接

可以绑定Toolbar、BottomNavigationView和ActionBar等

SafeArgs(Gradle插件) 数据传递时提供类型安全性

ViewModel支持

3. 准备

如果想要进行下面的学习,你需要 3.2 或者更高的Android studio。

4. 学习方式

最好的学习方式仍然是通过官方文档,下面是官方的学习地址:

谷歌官方教程:Navigation Codelab

谷歌官方文档:Navigation

官方Demo:Demo地址

二、实战

在实战之前,我们先来了解一下Navigation中最关键的三要素,他们是:

名词

解释

Navigation Graph(New XML resource)

如我们的第一张图所示,这是一个新的资源文件,用户在可视化界面可以看出他能够到达的Destination(用户能够到达的屏幕界面),以及流程关系。

NavHostFragment(Layout XML view)

当前Fragment的容器

NavController(Kotlin/Java object)

导航的控制者

可能我这么解释还是有点抽象,做一个不是那么恰当的比喻,我们可以将Navigation Graph看作一个地图,NavHostFragment看作一个车,以及把NavController看作车中的方向盘,Navigation Graph中可以看出各个地点(Destination)和通往各个地点的路径,NavHostFragment可以到达地图中的各个目的地,但是决定到什么目的地还是方向盘NavController,虽然它取决于开车人(用户)。

第一步 添加依赖

模块层的build.gradle文件需要添加:

ext.navigationVersion = "2.0.0"

dependencies {

//...

implementation "androidx.navigation:navigation-fragment-ktx:$rootProject.navigationVersion"

implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"

}

如果你要使用SafeArgs插件,还要在项目目录下的build.gradle文件添加:

buildscript {

ext.navigationVersion = "2.0.0"

dependencies {

classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"

}

}

以及模块下面的build.gradle文件添加:

apply plugin: 'kotlin-android-extensions'

apply plugin: 'androidx.navigation.safeargs'

第二步 创建navigation导航

创建基础目录:资源文件res目录下创建navigation目录 -> 右击navigation目录New一个Navigation resource file

创建一个Destination,如果说navigation是我们的导航工具,Destination是我们的目的地,在此之前,我已经写好了一个WelcomeFragment、LoginFragment和RegisterFragment,添加Destination的操作完成后如下所示:

66b93df4b7a6

添加Destination

除了可视化界面之外,我们仍然有必要看一下里面的内容组成,login_navigation.xml:

...

android:id="@+id/login_navigation"

app:startDestination="@id/welcome">

android:id="@+id/login"

android:name="com.joe.jetpackdemo.ui.fragment.login.LoginFragment"

android:label="LoginFragment"

tools:layout="@layout/fragment_login"

/>

android:id="@+id/welcome"

android:name="com.joe.jetpackdemo.ui.fragment.login.WelcomeFragment"

android:label="LoginFragment"

tools:layout="@layout/fragment_welcome">

.../>

.../>

android:id="@+id/register"

android:name="com.joe.jetpackdemo.ui.fragment.login.RegisterFragment"

android:label="LoginFragment"

tools:layout="@layout/fragment_register"

>

.../>

我在这里省略了一些不必要的代码。让我们看一下navigation标签的属性:

属性

解释

app:startDestination

默认的起始位置

第三步 建立NavHostFragment

我们创建一个新的LoginActivity,在activity_login.xml文件中:

...>

android:id="@+id/my_nav_host_fragment"

android:name="androidx.navigation.fragment.NavHostFragment"

app:navGraph="@navigation/login_navigation"

app:defaultNavHost="true"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

有几个属性需要解释一下:

属性

解释

android:name

值必须是androidx.navigation.fragment.NavHostFragment,声明这是一个NavHostFragment

app:navGraph

存放的是第二步建好导航的资源文件,也就是确定了Navigation Graph

app:defaultNavHost="true"

与系统的返回按钮相关联

第四步 界面跳转、参数传递和动画

在WelcomeFragment中,点击登录和注册按钮可以分别跳转到LoginFragment和RegisterFragment中。

66b93df4b7a6

WelcomeFragment.

这里我使用了两种方式实现:

方式一 利用ID导航

目标:WelcomeFragment携带key为name的数据跳转到LoginFragment,LoginFragment接收后显示。

Have a account ? Login按钮的点击事件如下:

btnLogin.setOnClickListener {

// 设置动画参数

val navOption = navOptions {

anim {

enter = R.anim.slide_in_right

exit = R.anim.slide_out_left

popEnter = R.anim.slide_in_left

popExit = R.anim.slide_out_right

}

}

// 参数设置

val bundle = Bundle()

bundle.putString("name","TeaOf")

findNavController().navigate(R.id.login, bundle,navOption)

}

后续LoginFragment的接收代码比较简单,直接获取Fragment中的Bundle即可,这里不再出示代码。最后的效果:

66b93df4b7a6

LoginFragment

方式二 利用Safe Args

目标:WelcomeFragment通过Safe Args将数据传到RegisterFragment,RegisterFragment接收后显示。

再看一下已经展示过的login_navigation.xml:

...>

...

/>

android:id="@+id/welcome"

>

android:id="@+id/action_welcome_to_login"

app:destination="@id/login"/>

android:id="@+id/action_welcome_to_register"

app:enterAnim="@anim/slide_in_right"

app:exitAnim="@anim/slide_out_left"

app:popEnterAnim="@anim/slide_in_left"

app:popExitAnim="@anim/slide_out_right"

app:destination="@id/register"/>

android:id="@+id/register"

...

>

android:name="EMAIL"

android:defaultValue="2005@qq.com"

app:argType="string"/>

细心的同学可能已经观察到navigation目录下的login_navigation.xml资源文件中的action标签和argument标签,这里需要解释一下:

action标签

属性

作用

app:destination

跳转完成到达的fragment的Id

app:popUpTo

将fragment从栈中弹出,直到某个Id的fragment

argument标签

属性

作用

android:name

标签名字

app:argType

标签的类型

android:defaultValue

默认值

点击Android studio中的Make Project按钮,可以发现系统为我们生成了两个类:

66b93df4b7a6

系统生成的类

WelcomeFragment中的JOIN US按钮点击事件:

btnRegister.setOnClickListener {

val action = WelcomeFragmentDirections

.actionWelcomeToRegister()

.setEMAIL("TeaOf1995@Gamil.com")

findNavController().navigate(action)

}

RegisterFragment中的接收:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

super.onViewCreated(view, savedInstanceState)

// ...

val safeArgs:RegisterFragmentArgs by navArgs()

val email = safeArgs.email

mEmailEt.setText(email)

}

以及效果:

66b93df4b7a6

RegisterFragment

需要提及的是,如果不用Safe Args,action可以由Navigation.createNavigateOnClickListener(R.id.next_action, null)方式生成,感兴趣的同学可以自行编写。

三、更多

Navigation可以绑定menus、drawers和bottom navigation,这里我们以bottom navigation为例,我先在navigation目录下新创建了main_navigation.xml,接着新建了MainActivity,下面则是activity_main.xml:

...>

android:id="@+id/my_nav_host_fragment"

android:name="androidx.navigation.fragment.NavHostFragment"

android:layout_width="match_parent"

app:navGraph="@navigation/main_navigation"

app:defaultNavHost="true"

android:layout_height="0dp"

android:layout_weight="1"/>

android:id="@+id/navigation_view"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@android:color/white"

app:itemIconTint="@color/colorAccent"

app:itemTextColor="@color/colorPrimary"

app:menu="@menu/menu_main"/>

MainActivity中的处理也十分简单:

class MainActivity : AppCompatActivity() {

lateinit var bottomNavigationView: BottomNavigationView

override fun onCreate(savedInstanceState: Bundle?) {

//...

val host: NavHostFragment = supportFragmentManager.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment

val navController = host.navController

initWidget()

initBottomNavigationView(bottomNavigationView,navController)

}

private fun initBottomNavigationView(bottomNavigationView: BottomNavigationView, navController: NavController) {

bottomNavigationView.setupWithNavController(navController)

}

private fun initWidget() {

bottomNavigationView = findViewById(R.id.navigation_view)

}

}

效果:

66b93df4b7a6

MainActivity

四、总结

66b93df4b7a6

总结

上图概括了本文的一些知识点,当然还有一些知识点没有涉及,比如深层连接等,其次,本文只是一篇入门型博客,关于更深层次的学习,本人会逐步进行。本人水平有限,文章难免有误,欢迎指正。

Over~

参考文章:

🚀如果觉得本文不错,可以查看Android Jetpack系列的其他文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值