How to create realistic UI with Jetpack Compose(Part II)
作者:Kruti Kamani
我们已经在之前的文章Saying Hello to Jetpack Compose介绍过Jetpack Compose的基础概念了。
Jetpack Compose是是一种用声明式的构建Android应用UI的新方式。现在不需要任何xml你也可以写一个Android APP了。
构建UI真的可以不需要XML了吗?
是的!用最新的Jetpack Compose这个现代化的UI工具你就可以做到。通过Compose只需要要定义一套Composable的函数就可以构建UI了,这套Composable函数接收数据然后将UI元素给展示出来。
Jetpack Compose这套声明式UI设计模式的几个关键点:
- 提高开发效率:跟现有的代码完全兼容。
- 更少的代码:用更少的代码反而可以做更多的事情,同时避免整个类的问题,因此代码更简洁,也更容易维护。
- 更强大的工具:利用Android平台提供的API,可以创建更具吸引力的APP。
- 直观思维:你只需要把UI描述出来,然后剩下的就可以交给Compose了。每次状态改变,UI会自动更新。
这边文章,我们会创一个一个来自Dribbble shots的Flower app的UI,并学习怎么用Jetpack Compose构建简单的UI。不浪费大家时间,直接开始吧。
快速开始
开始之前Jetpack Compose 之前需要配置一组gradle依赖。
//App level build.gradle
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.ui:ui-tooling:$compose_version"
还有compose的标记需要置为true,这个在android下面的buildFeatures块里面。
//App level build.gradle
buildFeatures {
compose true
}
Compose APP的入口
因为Jetpack Compose以编程的方式去构建UI,所以你不再需要任何XML了。因此你也不在需要去调用setContentView(R.layout.activity_main)
, 而是需要去构建setContent
这个方法。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text("Hello, World!")
}
}
}
让我们创建一个flower的列表,展示一些基本信息
如果我们需要设计的UI不止这些元素的话,那我们可能还需要线性布局,相对布局或者是约束布局,来实现更完美的设计。
在Jetpack里面为了达到相同的效果,我们需要用到一些特殊的容器,比如Column就是其中之一。
Column {
//Write your design here
}
正如这个函数名描述的那样,这个函数会纵向的布局它的子元素。这里我们有一个纵向布局两个Text组件的例子。
@Composable
fun FlowerCard(flower: Flowers){
Column {
Text(
text = flower.name,
style = TextStyle(
color = gray,
fontSize = 16.sp
)
)
Text(
text = flower.price,
style = TextStyle(
color = colorPrimary,
fontSize = 16.sp
)
)
}
现在我们在flower信息的添加一个加号按钮。
正如你期望的那样,你可以用Row()函数来进行横向的布局子元素。默认的配置是所有的子元素紧挨着进行布局,没有空隙。
@Composable
fun FlowerCard(flower: Flowers){
Row(modifier = Modifier.padding(20.dp)) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = flower.name,
style = TextStyle(
color = gray,
fontSize = 16.sp
)
)
Text(
text = flower.price,
style = TextStyle(
color = colorPrimary,
fontSize = 16.sp
)
)
}
IconButton(
onClick = { },
modifier = Modifier.background(
color = colorPrimary,
shape = RoundedCornerShape(10.dp)
)
) {
Icon(Icons.Default.Add, tint = Color.White)
}
}
}
上面的代码里面,我们通过Modifier添加了间距。但是modifier具体是什么东西呢?modifier是一个有序的,不可变的元素的集合,用来装饰或者给Compose UI元素添加行为的,比如背景,间距,点击事件等等。
现在我们再在row的基础上包一层Card。
@Composable
private fun FlowerCard(flower: Flowers) {
Card(
shape = RoundedCornerShape(14.dp),
backgroundColor = Color.White,
modifier = Modifier.padding(10.dp).width(180.dp)
) {
Row(modifier = Modifier.padding(20.dp)) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = flower.name,
style = TextStyle(
color = gray,
fontSize = 16.sp
)
)
Text(
text = flower.price,
style = TextStyle(
color = colorPrimary,
fontSize = 16.sp
)
)
}
IconButton(
onClick = { },
modifier = Modifier.background(
color = colorPrimary,
shape = RoundedCornerShape(10.dp)
)
) {
Icon(Icons.Default.Add, tint = Color.White)
}
}
}
}
Card有非常丰富的属性。如果你想要一个圆形或者其他形状,通过modifier你可以给卡片添加间距,宽度和高度。Card可以一个子元素展示信息。
现在我们想添加花的图片到花的信息上面。也就是说,我们想在卡片上展示多个信息,但是我们知道Card只能接受一个子元素。因此我们必须用Column。
@Composable
private fun FlowerCard(flower: Flowers) {
Card(
shape = RoundedCornerShape(14.dp),
backgroundColor = Color.White,
modifier = Modifier.padding(10.dp).width(180.dp)
) {
Column(
modifier = Modifier.fillMaxWidth().padding(10.dp),
) {
Image(
modifier = Modifier.size(140.dp),
asset = imageResource(id = flower.image)
)
Row(modifier = Modifier.padding(top = 20.dp)) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = flower.name,
style = TextStyle(
color = gray,
fontSize = 16.sp
)
)
Text(
text = flower.price,
style = TextStyle(
color = colorPrimary,
fontSize = 16.sp
)
)
}
IconButton(
onClick = { },
modifier = Modifier.background(
color = colorPrimary,
shape = RoundedCornerShape(10.dp)
)
) {
Icon(Icons.Default.Add, tint = Color.White)
}
}
}
}
在上面的代码里面,为了添加一张图片我们用到了Image。
asset这个属性用来提供图片资源。imageResource函数接收一个一个图片的ID作为参数,然后将ImageAsset展示到View上面。Image还有很多其他属性,比如scaling,aligning,改变图片UI的展示等等。
创建一个花列表
通常创建一个列表你会用到RecyclerView。与之类似,在Jetpack Compose里面我们用LazyRowFor。这是一个横向的列表,只布局当前显示的item。
现在把所有的放在一起,创建PopularFlowersList()。
@Composable
private fun PopularFlowersList() {
LazyRowFor(
items = FlowersData.list,
modifier = Modifier.fillMaxWidth()
) { flowers ->
FlowerCard(flowers)
}
}
恭喜你,你已经成功用Jetpack Compose成功创建了第一个真实的UI。
注意:因为Jetpack Compose目前还处于alpha(目前已经是beta),组件回这它们的属性都有可能改变。
这篇文章只是这个系列的开始,在后续的文章里,我们计划用MVVM的设计模式写一个示例。所以请继续保持关注,到时候我们继续Composing!!