Jetpack Compose学习(1)——从登录页开始入门
原文地址:Jetpack Compose学习(1)——从登录页开始入门 | Stars-One的杂货小窝
Jetpack Compose UI在前几天出了1.0正式版,之前一直还在观望,终于是出了正式版 😃 趁着无事,来篇入门教程,希望给各位一点参考
注:由于compose UI使用了kotlin的DSL语言特性,所以需要熟悉Kotlin
Jetpack Compose介绍
Jetpack Compose
是一个用于构建原生Android UI
的现代工具包。Jetpack Compose
用更少的代码、强大的工具和直观的Kotlin API
简化并加速了Android
上的UI
开发。
Jetpack Compose
使用了声明式来编写UI,本质上就是用代码写布局,这里说的代码不是特指,主要是与html
、xml
等标识语言进行区别,在xml
等语言中,我们无法使用if或循环等结构体来构造UI,而JetCompose Compose
而可以实现这点,这样会让我们布局更加灵活
如果之前各位也是接触过Flutter
,就会和我有一样的体会,Jetpack Compose
里面的组件类定义跟Flutter
那边十分一致,我猜测肯定是有借鉴,毕竟那边也是Google公司旗下的团队整的
过多的就不说了,上正文吧 😝
简单Hello World
首先,你需要一台联网的电脑,下载Android Studio最新版(2020.3.1) 🦊,好久没升级了,界面都感觉焕然一新了 😮
之后的环境配置这里不多说了,下SDK,下模拟器,新人来 估计得折腾一天 由于我之前就已经下载过Android Studio,这里直接下载好之后就可以使用了
我们按照官方的教程,直接新建一个Jetpack Compose项目
之后常规操作 ,填写相关的包名即可新建了,之后又是等待下载相关依赖的东西,一切下载完毕就准备OK了
可一看右边,一个红色的背景,顿时人就有点烦了,还好不是什么大问题,它提示我们需要build一下项目
行吧,我build一下,然后,人傻了,直接爆红了💢
一看提示 好家伙,最低的Java环境要11了,我也是服了,百度一搜
原来是Android官方那边的坑,直接把gradle升级到最新版,你说你升级就升级吧,可没想到gradle那边最新版弃用JDK8了
解决方法有两个
- 更改Android Gradle Plugin和Gradle版本
- 使用JDK11环境
更改Android Gradle Plugin和Gradle版本,也就是下图这两个东西,自己参考下之前旧版本项目的版本号改即可
PS: 通过
File
->Project Structure
打开下面的界面
下图是我自己旧项目使用的版本号,各位可以参考下
至于换JDK11,其实也是比较简单,我是环境变量都是用着JDK8,因为还有旧项目需要使用(TornadoFx),所以,我们只改项目里使用的JDK版本即可
进到设置里修改即可,如下图
Android Studio其实内置有个JDK11,我们直接使用这个即可,而且,不会影响其他新开的项目
经过上面的设置后,我们可以重新build下项目,可以发现右侧已经可以预览了
我们先简单分析一下代码
onCreate()
中,有个setContent()
,用来设置页面的主体内容,我们先不管ComposeDemoTheme
和Surface
,Greeting("Android")
是我们要关心的
setContent {
ComposeDemoTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
此方法上有个注解@Composable
,用来表示当前方法返回的是一个组件,我们可以更改其中的数值,可以看到右侧会实时的进行变化
提示: 实时渲染只针对数值的改变,如果你新增一个组件,是没有实时变化效果的,需要重新build一次
下面也有个方法,除了@Composable
注解,还有有个@Preview
,Preview
主要是标明用来预览的
标有@Preview注解的方法,不能存在有参数,否则无法预览
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemoTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
登录页实现
上面也是比较简单的讲解了下代码,下面我们来个登录页实例来操作下吧
与Flutter一样,Jetpack Compose没有线性布局(LinearLayout),但有Row和Column两个布局,从名字可以看得出来,一种是水平布局,一种是垂直布局
我们先简单搭建个登录页面
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemoTheme {
Column() {
Row() {
Text(text = "用户名")
TextField(value = "", onValueChange = {str -> Log.e("test",str)})
}
Row() {
Text(text = "密码")
TextField(value = "", onValueChange = {str -> Log.e("test",str)})
}
TextButton(onClick = { }) {
Text(text = "登录")
}
}
}
}
上面代码中出现了几个组件Text,TextField和TextButton,字面意思很好理解
组件名 | 作用 |
---|---|
Text | 文本 |
TextField | 输入框 |
TextButton | 文字按钮 |
预览效果如下图所示:
测试的发现,无法输入文字,这是怎么回事呢?
因为
Jetpack Compose
使用了类似MVVM的数据绑定的方式,所以,我们得给输入框绑定一个变量,onValueChange方法数值改变的时候会回调,我们在回调更改变量的数值即可达到更改UI的效果
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
var name by remember { mutableStateOf("") }
var pwd by remember { mutableStateOf("") }
ComposeDemoTheme {
Column() {
Row() {
Text(text = "用户名")
TextField(value = name, onValueChange = { str -> name = str })
}
Row() {
Text(text = "密码")
TextField(value = pwd, onValueChange = { str -> pwd = str })
}
TextButton(onClick = { }) {
Text(text = "登录")
}
}
}
}
上面代码出现了
remember
和mutableStateOf
的两个关键字,但本章作为入门篇,先暂时不讲解过多知识,先放着,后续再进行补充
最后,我们还差一步,就是判断输入的账号和密码是否正确,然后弹出登录失败或登录成功的提示
这里,我准备使用传统简单的Toast进行提示,但是Toast需要传一个Context,由于组件的那个函数是写在Activity外面的,所以是拿不到Activity本身的,但是我们可以把Activity本身传到方法里(但不确定我这方法规不规范)
PS:看了下对话框的使用,觉得有些复杂,也是放在之后再讲解吧
2021.8.12补充
Compose中提供了获取context对象方法 目前代码为
val context = LocalContext.current
,不确定后期API是否会变更,详情可以参考此文android - How to get Context in Jetpack Compose - Stack Overflow
@Composable
fun DefaultPreview(context: Activity) {
var name by remember { mutableStateOf("") }
var pwd by remember { mutableStateOf("") }
ComposeDemoTheme {
Column() {
Row() {
Text(text = "用户名")
TextField(value = name, onValueChange = { str -> name = str })
}
Row() {
Text(text = "密码")
TextField(value = pwd, onValueChange = { str -> pwd = str })
}
TextButton(onClick = {
if (name == "test" && pwd == "123") {
Toast.makeText(context, "登录成功", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "登录失败", Toast.LENGTH_SHORT).show()
}
}) {
Text(text = "登录")
}
}
}
}
最后效果如下图所示