文章首发于公众号:「 技术最TOP 」
,每天都有干货文章继续更新,能够微信搜寻「 技术最TOP 」
第一工夫浏览,回复【思维导图】【面试】【简历】有我筹备一些Android进阶路线、面试领导和简历模板送给你
Jetpack Compose 是Google公布的一个Android原生古代UI工具包,它齐全采纳Kotlin编写,能够应用Kotlin语言的全副个性,能够帮忙你轻松、疾速的构建高质量的Android应用程序。如果你还不理解Jetpack Compose是什么?倡议你读一下我后面的2篇文章:
Android Jetpack Compose 最全上手指南
Jetpack Compose,不止是一个UI框架!
去年的Google IO 大会上,Google发表了Jetpack Compose的面世,然而在去年11月份,它才公布第一个预览版-Developer Preview1,尔后,根本放弃每两周公布一个小版本,到当初,半年的工夫过来了,两头公布了十多个小版本,明天,终于迎来了重大更新,Developer Preview2 公布了。
Jetpack Compose Developer Preview1公布后,开发者最关怀的几个问题是,没有Compose版本的RecyclerView、Constriantlayout、动画等一系列问题。这些问题在Preview2都解决了。
当然,从Preview1 到当初公布的Preview2,变动十分大,甚至很多API都曾经变了,有的属性或者类的减少或者删除。具体的变换化太多,就不在这里一一解说,感兴趣的能够看看官网的每个小版本的更新日志。明天就带大家一起看看PreView2减少的一些重磅性能。
- 1、Modifier
- 2、RecyclerView
- 3、Constriantlayout
- 4、动画
- 5、原生View引入Compose
好戏收场了!
1、Modifier
首先,说一下Modifier(修改器),在Preview1版本,就曾经有了modifier,不过应用的中央不多,并且对于它的定位比拟含糊,令人困惑,因为modifier无能的事儿,通过组合函数也能做到。然而咱们发现了一件事,例如,要在Compose函数中减少padding的时候,会产生大量的嵌套,因为要给嵌套一个容器能力设置padding,因而,当初将很多性能都挪动到了Modifier,它当初应用十分宽泛,能够润饰一个元素、一个布局或者一些其余行为。如何应用Modifier?先来看一个例子:
首先,咱们写一个Compose函数(即Compose组件),展现一张图片
@Composablefun Greeting() { val (shape,setShape) = state<Shape> { CircleShape } Image(asset = imageResource(R.drawable.androidstudio), contentScale = ContentScale.Crop )}
图片显示的是原来的尺寸,而后给图片指定一个大小,比方:256dp,此时就须要应用Modifier了。
@Composablefun Greeting() { val (shape,setShape) = state<Shape> { CircleShape } Image(asset = imageResource(R.drawable.androidstudio), contentScale = ContentScale.Crop, modifier = Modifier.size(256.dp))}
批改后如下,宽高都为256dp。
modifier中有很多能够配的参数,比方,减少一个padding
,将图片裁剪成一个圆形
。
@Composablefun Greeting() { val (shape,setShape) = state<Shape> { CircleShape } Image(asset = imageResource(R.drawable.androidstudio), contentScale = ContentScale.Crop, modifier = Modifier.size(256.dp) .padding(16.dp) .drawShadow(8.dp,shape = shape) )}
成果就成了这样:
还能够再圆形头像加一个border
,代码如下:
@Composablefun Greeting() { val (shape,setShape) = state<Shape> { CircleShape } Image(asset = imageResource(R.drawable.androidstudio), contentScale = ContentScale.Crop, modifier = Modifier.size(256.dp) .padding(16.dp) .drawShadow(8.dp,shape = shape) .drawBorder(6.dp,MaterialTheme.colors.primary,shape = shape) )}
成果如下:
还能够同时增加多个border,比方我再减少2个:
@Composablefun Greeting() { val (shape,setShape) = state<Shape> { CircleShape } Image(asset = imageResource(R.drawable.androidstudio), contentScale = ContentScale.Crop, modifier = Modifier.size(256.dp) .padding(16.dp) .drawShadow(8.dp,shape = shape) .drawBorder(6.dp,MaterialTheme.colors.primary,shape = shape) .drawBorder(12.dp,MaterialTheme.colors.secondary,shape = shape) .drawBorder(18.dp,MaterialTheme.colors.background,shape = shape) )}
成果就成这样了:
设置点击事件也是再modifier中,比方咱们要在点击这个图片后,扭转形态,以前的View可麻烦了,然而Jetpack compose 却非常简单,modifier中减少如下代码:
@Composablefun Greeting() { val (shape,setShape) = state<Shape> { CircleShape } Image(asset = imageResource(R.drawable.androidstudio), contentScale = ContentScale.Crop, modifier = Modifier.size(256.dp) .padding(16.dp) .drawShadow(8.dp,shape = shape) .drawBorder(6.dp,MaterialTheme.colors.primary,shape = shape) .drawBorder(12.dp,MaterialTheme.colors.secondary,shape = shape) .drawBorder(18.dp,MaterialTheme.colors.background,shape = shape) .clickable { // 点击事件 setShape( if(shape == CircleShape) CutCornerShape(topLeft = 32.dp,bottomRight = 32.dp) else CircleShape ) } )}
下面的代码中,咱们还减少了判断,如果以后shape是CircleShape
,咱们就扭转形态,否则就设置为CircleShape
,成果就是点击图片,形态在这两种成果之间来回切换。
成果如下:
2. Jetpack Compose 中的RecyclerView
RecyclerView是咱们Android开发中用来展现大数据列表的罕用组件,它能帮忙咱们回收复用视图,有很好的性能体验。在Jetpack Developer PreView1 刚进去的时候,我就在官网或者代码库中找这个组件。很遗憾翻遍了所有材料都每找到,是的确没有,最终只找到了一个叫做VerticalScroller
的组件你。它能够用来展现列表,然而它不是RecyclerView,它相似咱们的ScrollView,也就是说,展现大量数据的列表是能够的,因为它没有复用机制,展现大列表时,内存堪忧,会OOM。
然而在这次的Preview2中,RecyclerView终于被盼来了,组件名字叫做:AdapterList
,它就对应咱们原生Android开发的RecyclerView。以前咱们要写一个列表是非常复杂的,用写xml,Adapter,ViewHolder等,最终还要在Activity/Fragment初始化和绑定数据,十分麻烦。Jetpack Compose中的列表应用则是非常简单,简略到令人发指。来看一下咱们如何展现一个列表:
@Composablefun generateList(context: Context) { val list = mutableListOf<String>() //筹备数据 for (i in 1..100) { list.add(i.toString()) } AdapterList(data = list) { Card( shape = MaterialTheme.shapes.medium, modifier = Modifier .preferredSize(context.resources.displayMetrics.widthPixels.dp, 60.dp) .padding(10.dp) ) { Box(gravity = ContentGravity.Center) { ProvideEmphasis(EmphasisAmbient.current.medium) { Text( text = it, style = MaterialTheme.typography.body2 ) } } } Spacer(modifier = Modifier.preferredHeight(10.dp)) }}
看到了没,就是这样几行代码,咱们的列表就实现了,解释一下代码:最开始的筹备数据没啥说的,向list中增加了100个数据,而后将数据源传给AdapterList
,列表的每一个Item是一个卡片,用的是Card组件,卡片里展现了一个Text文本,最初的Spacer
用来设置item之间的间距,相当于ItemDecoration
,看一下成果:
3. Constriantlayout
Constriantlayout
是一个性能十分弱小的布局,也是当初Android开发中最受欢迎的布局之一,当Jetpack Compose Preview1版本才进去的时候,很多开发者都有一个疑难,Compose 中该如何应用Constriantlayout
呢?它将如何运作,这的确是个有意思的问题。因为在Jetpack Compose中,所有的组件都是组合函数,获取不到View饮用,如何束缚彼此之间的关系的确是一个难题。好在当初这个难题解决了,上面通过几个小例子一起来看看Compose中的Constriantlayout
应用。
如下图所示,有两个View,A和B,ViewB在ViewA的左边,顶部和ViewA的底部对齐,如何应用Constriantlayout 形容它们的地位关系?
代码:
@Composablefun GreetConstraintLayout(context: Context) { ConstraintLayout(constraintSet = ConstraintSet { val viewA = tag("ViewTagA").apply { left constrainTo parent.left centerVertically() } val viewB = tag("ViewTagB").apply { left constrainTo viewA.right centerVertically() top constrainTo viewA.bottom } }, modifier = Modifier.preferredSize(context.screenWidth().dp,400.dp).drawBackground(Color.LightGray)) { Box( modifier = Modifier.tag("ViewTagA").preferredSize(100.dp, 100.dp), backgroundColor = Color.Blue, gravity = ContentGravity.Center ) { Text(text = "A") } Box( modifier = Modifier.tag("ViewTagB").preferredSize(100.dp, 100.dp), backgroundColor = Color.Green, gravity = ContentGravity.Center ) { Text(text = "B") } }}
解释一下下面的代码:在ConstraintSet
中来定义束缚,应用Tag来创立一个束缚,前面咱们就能够通过这个tag来应用咱们定义的束缚,返回的是一个ConstrainedLayoutReference
,ViewA的右边与父组件的右边对齐,垂直居中。ViewB的右边与ViewA的左边对齐,top与ViewA的底部对齐。也垂直居中。
比方ViewB中就是应用ViewA来作为约束条件了。
前面应用的时候,间接用Modifier.tag()
利用束缚到组件上。
这还不是最牛逼,还有一个弱小的性能是能够在布局束缚中增加逻辑,比方:我有一个ViewC 它的地位可能有两种状况:
- 1、ViewC 的右边与ViewA的左边对齐
- 2、View C的右边与ViewB的左边对齐
该怎么写代码?先定一个一个Boolean 变量叫hasFlag
(轻易其的名,它的值依据你的业务逻辑某些状况是true,某些状况是false)
val hasFlag = true // 它的值依据你的业务逻辑某些状况是true,某些状况是false tag("ViewC").apply { // 依据判断条件扭转,束缚也扭转 left constrainTo (if(hasFlag) viewA else viewB).right bottom constrainTo viewB.top }
残缺代码如下:
@Composablefun GreetConstraintLayout(context: Context) { ConstraintLayout(constraintSet = ConstraintSet { val hasFlag = true // 它的值依据你的业务逻辑某些状况是true,某些状况是false val viewA = tag("ViewTagA").apply { left constrainTo parent.left centerVertically() } val viewB = tag("ViewTagB").apply { left constrainTo viewA.right centerVertically() top constrainTo viewA.bottom } tag("ViewC").apply { // 依据判断条件扭转,束缚也扭转 left constrainTo (if(hasFlag) viewA else viewB).right bottom constrainTo viewB.top } }, modifier = Modifier.preferredSize(context.screenWidth().dp,400.dp).drawBackground(Color.LightGray)) { Box( modifier = Modifier.tag("ViewTagA").preferredSize(100.dp, 100.dp), backgroundColor = Color.Blue, gravity = ContentGravity.Center ) { Text(text = "A") } Box( modifier = Modifier.tag("ViewTagB").preferredSize(100.dp, 100.dp), backgroundColor = Color.Green, gravity = ContentGravity.Center ) { Text(text = "B") } Box( modifier = Modifier.tag("ViewC").preferredSize(100.dp, 100.dp), backgroundColor = Color.Red, gravity = ContentGravity.Center ) { Text(text = "C") } }}
hasFlag=true
成果如下:
hasFlag=false
成果如下:
其余的一些束缚布局属性同当初咱们应用的ConstraintLayout
雷同,有趣味的能够去试试。
4. 动画
Jetpack Compose对动画的反对也是开发者十分关怀的一个问题,这一大节就看看Compose中,动画的应用,还是来看一个小例子,先看效果图:
如上,一个简略的属性动画,图片有选中/未选中
两种状态,由未选中->选中
时,有一个正方形->圆形
的动画,并且随同着alpha
动画。
代码如下:
@Composablefun GreetAnimate(){ // val (selected,onValueChange) = state { false } // radius 变动 val radius = animate(if(selected) 100.dp else 8.dp) // alpha 动画 val selectAlpha = animate(if(selected) 0.4f else 1.0f) Surface(shape = RoundedCornerShape( topLeft = radius, topRight = radius, bottomRight = radius, bottomLeft = radius )) { Toggleable( value = selected, onValueChange = onValueChange, modifier = Modifier.ripple() ) { Image( asset = imageResource(R.drawable.androidstudio), modifier = Modifier.preferredSize(200.dp,200.dp), contentScale = ContentScale.Crop, alpha = selectAlpha ) } }}
动画应用animate
Compose函数来实现,只须要为它提供不同的target的值,它就能帮你实现之间的变动,一旦动画创立,它就和一般的Compose函数是一样的。
留神一点 :animate
创立的动画是不能被勾销的,要创立能够被勾销的动画能够应用animatedValue
。还有其余两个类似动画函数:animatedFloat
,animatedColor
啥?你说看起来有点相熟?那可不是嘛,ObjectAnimator
,ValueAnimator
, 你细品,更多对于动画的应用形式这里不开展了,有趣味的同学下来本人入手试试。
4. 与原生View 的兼容
一门新的语言,一个新的框架,思考兼容是很有必要的,就像Kotlin那样,咱们应用Kotlin不用一下子重写整个我的项目,你能够增加一个新的类,一个新的模块中应用Kotlin,因为它们与Java 齐全互相调用。
Jetpack Compose 借鉴了教训,咱们要应用Jetpack Compose,也能够慢慢来,以前的代码不必动,在你的新模块中一点一点的增加,这就波及到与原来的View的兼容,在Compose中,能够应用AndroidView来兼容以前的Views。
比方我的Jetpack Compose 中要应用到Webview,而它自身也没有提供,该如何是好?别放心,用原来的就行。
首先,创立一个xml文件webview.xml
,外面增加Webview 布局:
<?xml version="1.0" encoding="utf-8"?><WebView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"></WebView>
而后写一个compose 函数,应用AndroidView 来加载:
@Composablefun androidView(){ AndroidView(R.layout.webview){ view -> val webView = view as WebView webView.settings.javaScriptEnabled =true webView.settings.allowFileAccess = true webView.settings.allowContentAccess = true webView.loadUrl("https://juejin.im/") }}
加载了一个原生的Webview,而后在webview中加载了掘金的网址,成果如下:
看一下AndroidView函数签名:
@Composable// TODO(popam): support modifiers herefun AndroidView(@LayoutRes resId: Int, postInflationCallback: (View) -> Unit = { _ -> }) { AndroidViewHolder( postInflationCallback = postInflationCallback, resId = resId )}
承受一个布局文件资源id,和一个回调postInflationCallback
,当View被inflate进去后,会调用这个回调,而后你就能够在回调中应用它了。
然而,留神: 回调通常是在主线程被调用。
5.总结
总的来说,这次Developer PreView2 更新比拟多,并且很多API产生了变动,减少了一些要害的组件如AdapterList
,ConstraintLayout
,动画组件
等,应用形式也与Preview1有很多不同。能够来看一下Google对于Jetpack Compose 上的时间表:
- 2019.5 发表Jetpack Compose
- 2019.11 第一个 Developer Preview
- 2020.6 第二个 Developer Preview
- 2020 夏天将公布Alpha版本
- 2021 将公布release 1.0版本
然而,要说的是,当初很多API还不是最终版本,能够看到,每一个打版本的变动还是蛮大的,当初依然不能用在商用我的项目上。然而就jetpack Compose 自身来说,集体还是比拟期待的,从下面的时间表就能够看到,大略明年就能出第一个release版本,敬请期待吧!
对了,最新版本的Jetpack Compose 须要Android Studio 4.2以上版本能力应用,想要体验的同学先安卓Android Studio 4.2 Canary 版本。去官网下载!
小版本日志列表请看:https://developer.android.com...
youtobe视频介绍请看:https://www.youtube.com/watch...