Jetpack Compose(二)

接上一篇文章 Jetpack Compose(一)

Compose布局

官网介绍:界面元素采用多层次结构,元素中又包含其他元素。在 Compose 中,可以通过从可组合函数中调用其他可组合函数来构建界面层次结构。

添加文本

    data class Message(val author: String, val body: String)

    @Composable
    fun MessageCard(msg: Message) {
        Column() {
            Text(text = msg.author)
            Text(text = msg.body)
        }
    }

    @Preview()
    @Composable
    fun PreviewMessageCard(){
        MessageCard(
            msg = Message("Android","Hello Android")
        )
    }

 PreviewMessageCard函数预览效果

Text:compose中的Text相当于TextView,用于显示文字。

Columm:使其中的内容垂直显示,效果与xml布局中的LinearLayout vertical类似

Row: 水平排列,与LinearLayout horizontal类似

Box:堆叠其中内容,相当于FrameLayout

添加图片

    @Composable
    fun MessageCard(msg: Message) {
        Row(modifier = Modifier.padding(all = 4.dp)) {
            Image(
                painter = painterResource(R.drawable.post_4_thumb),
                contentDescription = "Contact profile picture",
                modifier = Modifier
                    .size(40.dp)
                    .clip(CircleShape)
            )
            //在image和column中间加入空白间距
            Spacer(modifier = Modifier.width(8.dp))

            Column {
                Text(text = msg.author)
                Text(text = msg.body)
            }
        }
    }

预览效果

可以看到代码中使用Modifier来修改各个控件的属性,包括外观、大小、边距、位置等。官方称之为修饰符,将这些修饰符链接起来,即可创建更丰富的可组合项。修饰符列表

使用Material Design

Jetpack Compose 原生提供 Material Design 及其界面元素的实现。我们将使用 Material Design 样式改进 MessageCard 可组合项的外观。Material Design 是围绕三大要素构建的:颜色、排版、形状。

    @Composable
    fun MessageCard(msg: Message) {
        Row(modifier = Modifier.padding(all = 4.dp)) {
            Image(
                painter = painterResource(R.drawable.post_4_thumb),
                contentDescription = "Contact profile picture",
                modifier = Modifier
                     //图片大小
                    .size(40.dp)
                     //裁剪为圆形
                    .clip(CircleShape)
                     //添加边框
                    .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)

            )
            //在image和column中间加入空白间距
            Spacer(modifier = Modifier.width(8.dp))

            Column {
                Text(
                    text = msg.author,
                    color = MaterialTheme.colors.secondaryVariant,
                    style = MaterialTheme.typography.subtitle2
                )
                //上下间距
                Spacer(modifier = Modifier.height(4.dp))
                //添加阴影 内边框
                Surface(shape = MaterialTheme.shapes.medium,elevation = 3.dp){
                    Text(
                        text = msg.body,
                        style = MaterialTheme.typography.body2
                    )
                }
            }
        }
    }
    
    @Preview()
    @Composable
    fun PreviewMessageCard() {
        JetnewsTheme(){
            MessageCard(
                msg = Message("Android", "Hello Android")
            )
        }
    }

    //自定义 MaterialTheme 主题
    @Composable
    fun JetnewsTheme(
        darkTheme: Boolean = isSystemInDarkTheme(),
        content: @Composable () -> Unit
    ) {
        MaterialTheme(
            colors = if (darkTheme) DarkThemeColors else LightThemeColors,
            typography = JetnewsTypography,
            shapes = JetnewsShapes,
            content = content
        )
    }

给预览函数包上一个自定义的Materail风格主题JetnewsTheme,在各个控件中加入Material风格的属性,显示效果已经有了变化。

使用Material Design默认能够处理深色主题,浅色和深色主题的颜色在创建项目时就由IDE自动生成了,保存在Theme.kt文件下。预览时加入两个Preview注解即可同时显示深色和浅色主题,深色主题需加上Configuration.UI_MODE_NIGHT_YES。

 动画和列表

可以使用LazyColumn 和 LazyRow来加载列表,它只会呈现屏幕上显示的元素,因此,对于较长的列表,使用它们会非常高效 。在以下代码段中,LazyColumn 包含一个 items 子项,即列表的每一个item,会将传入的List<Message>显示出来。

    @Composable
    fun Conversation(messages: List<Message>) {
        LazyColumn {
            items(messages) { msg ->
                MessageCard(msg)
            }
        }
    }

    @Preview()
    @Composable
    fun PreviewMessageCard() {
        JetnewsTheme {
            //conversationSample为List数据
            Conversation(conversationSample)
        }
    }

 此时列表预览效果

接下来实现点击消息时展开文本,为了保存item是否展开的状态,使用到 remember 和 mutableStateOf 函数。点击item改变颜色,使用 animateColorAsState 函数。

可组合函数可以使用 remember 将本地状态存储在内存中,并跟踪传递给 mutableStateOf 的值的变化。该值更新时,系统会自动重新绘制使用此状态的可组合项(及其子项)。这一功能称为重组

简单来说,remember就是用来存储状态,而mutableStateOf用来标明这个data是有状态的,如果状态发生了改变,所有引用这个状态的控件都需要重新绘制。有点类似DataBinding,数据改变后页面也就跟着重绘。

    @Composable
    fun MessageCard(msg: Message) {
        Row(modifier = Modifier.padding(all = 4.dp)) {
            Image(
                painter = painterResource(R.drawable.post_4_thumb),
                contentDescription = "Contact profile picture",
                modifier = Modifier
                    .size(40.dp)
                    .clip(CircleShape)
                    .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)

            )
            //在image和column中间加入空白间距
            Spacer(modifier = Modifier.width(8.dp))

            //记录消息是否展开
            var isExpanded by remember { mutableStateOf(false) }
            //改变颜色
            val surfaceColor: Color by animateColorAsState(
                if (isExpanded) MaterialTheme.colors.primary
                else MaterialTheme.colors.surface
            )
            //点击时切换isExpanded变量
            Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
                Text(
                    text = msg.author,
                    color = MaterialTheme.colors.secondaryVariant,
                    style = MaterialTheme.typography.subtitle2
                )
                //上下间距
                Spacer(modifier = Modifier.height(4.dp))
                //添加阴影 内边框
                Surface(
                    shape = MaterialTheme.shapes.medium,
                    elevation = 3.dp,
                    //改变颜色
                    color = surfaceColor,
                    //改变大小动画
                    modifier = Modifier
                        .animateContentSize()
                        .padding(1.dp)
                ) {
                    Text(
                        text = msg.body,
                        modifier = Modifier.padding(all = 4.dp),
                        //如果展开消息则显示所有内容,否则只显示一行
                        maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                        style = MaterialTheme.typography.body2
                    )
                }
            }
        }
    }

 

总结

通过对官网教程学习,Compose的代码相比xml的方式精简得多,声明式UI的编程方式也饶有新意,学过Flutter的话还是比较容易上手的,可能突然转变写布局的方式会不太适应,但面对新技术还是要保持关注并不断尝试。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永琪-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值