Android Jetpack Compose学习—— 各种控件的用法

Posted yubo_725

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Jetpack Compose学习—— 各种控件的用法相关的知识,希望对你有一定的参考价值。

前言

Jetpack Compose主要是用来写android UI的,Android UI无外乎文本、图片、列表等各种控件的展示,这里我用的“控件”一词不确定是否准确,因为传统的Android UI确实是一个个控件,而在Jetpack Compose中,类似Text Image Column Row等其实是用Kotlin写的一个函数,这个函数会渲染出对应的文本、图片、列表等。今天记录的主要是这些“控件”的使用方法。

Text

使用Text可以显示一行文本,下面的代码展示了Text的一些用法:

@Preview
@Composable
fun TextTest() 
    Text(
        text = "Hello world", // 文本
        fontSize = 30.sp,  // 字号
        fontWeight = FontWeight.Bold, // 加粗
        fontStyle = FontStyle.Italic, // 斜体
        fontFamily = FontFamily.Serif, // 字体
        color = Color.White, // 颜色
        textAlign = TextAlign.Center, // 居中对齐
        modifier = Modifier.background(Color.Gray) // 背景色
            .fillMaxWidth() // 横向填充最大
            .clickable  // 点击事件
                Toast.makeText(this, "Test", Toast.LENGTH_SHORT).show()
            
    )

这段代码运行在模拟器上效果如下图:


关于以上代码做如下说明:

  1. Text实际上是一个Kotlin方法,其源码如下:

    @Composable
    fun Text(
        text: String,
        modifier: Modifier = Modifier,
        color: Color = Color.Unspecified,
        fontSize: TextUnit = TextUnit.Unspecified,
        fontStyle: FontStyle? = null,
        fontWeight: FontWeight? = null,
        fontFamily: FontFamily? = null,
        letterSpacing: TextUnit = TextUnit.Unspecified,
        textDecoration: TextDecoration? = null,
        textAlign: TextAlign? = null,
        lineHeight: TextUnit = TextUnit.Unspecified,
        overflow: TextOverflow = TextOverflow.Clip,
        softWrap: Boolean = true,
        maxLines: Int = Int.MAX_VALUE,
        onTextLayout: (TextLayoutResult) -> Unit = ,
        style: TextStyle = LocalTextStyle.current
    ) 
        Text(
            AnnotatedString(text),
            modifier,
            color,
            fontSize,
            fontStyle,
            fontWeight,
            fontFamily,
            letterSpacing,
            textDecoration,
            textAlign,
            lineHeight,
            overflow,
            softWrap,
            maxLines,
            emptyMap(),
            onTextLayout,
            style
        )
    
    
  2. 设置字号时使用了fontSize = 30.sp这种方式,30.sp实际上是使用了Kotlin的扩展方法,给Int类增加了一个sp方法:

    @Stable
    val Int.sp: TextUnit get() = pack(UNIT_TYPE_SP, this.toFloat())
    

Image

使用Image可以显示一个图片,加载资源文件中的图片可以用如下方法:

@Preview
@Composable
fun ShowImage() 
    Column 
        Image(
            painter = painterResource(R.mipmap.avatar), // 加载资源文件中的图片
            contentDescription = null,
            modifier = Modifier
                .size(200.dp) // 图片大小
                .clip(CircleShape) // 裁剪成圆形
        )
    

这段代码在AS中预览如下图:


加载本地图片非常容易,如果想加载网络上的图片呢?

这里推荐一个非常好用的图片加载库Coil
经测试,Coil比Glide有更优秀的内存占用,分别使用这两个库加载同一个图片列表,Coil占用的内存大概是Glide的一半,而且Coil完全使用Kotlin编写,其更适用于采用Kotlin开发的Android项目,在Jetpack Compose中使用Coil加载图片如下步骤:

  1. 添加依赖配置
// 注意这个库并不是Coil库,而是Google封装了Coil用于在Jetpack compose中使用
implementation "com.google.accompanist:accompanist-coil:0.11.1"
  1. 添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
  1. 加载网络图片
@Preview
@Composable
fun ShowImage() 
    Image(
        painter = rememberCoilPainter(
            request = "https://i02.appmifile.com/778_bbs_en/06/06/2021/efed2421ae.jpg",
            previewPlaceholder = R.mipmap.avatar
        ),
        contentDescription = null,
        modifier = Modifier
            .fillMaxWidth()
            .height(200.dp),
        contentScale = ContentScale.Crop
    )

在模拟器上运行以上代码效果如下:

如果你在跑上述代码时遇到如下错误:

java.lang.IllegalStateException: function = <anonymous>, count = 3, index = 3
	at androidx.compose.compiler.plugins.kotlin.lower.ComposerLambdaMemoization.wrapFunctionExpression(ComposerLambdaMemoization.kt:671)
	at androidx.compose.compiler.plugins.kotlin.lower.ComposerLambdaMemoization.visitComposableFunctionExpression(ComposerLambdaMemoization.kt:529)
	at androidx.compose.compiler.plugins.kotlin.lower.ComposerLambdaMemoization.visitFunctionExpression(ComposerLambdaMemoization.kt:591)

这是Kotlin版本和Compose版本问题导致的,请确保你的Kotlin版本和Compose版本如下(或者更新):

    ext.kotlin_version = '1.4.32'
    ext.compose_version = '1.0.0-beta07'

LazyColumn / LazyRow

使用LazyColumn可以很方便的实现自动回收的长列表,其使用方法如下:

    @Preview
    @Composable
    fun TestList() 
        LazyColumn 
            items(100)  i ->
                GenListItem(i)
            
        
    

    @Composable
    fun GenListItem(index: Int) 
    // 创建列表Item
        Column 
            Row(
                verticalAlignment = Alignment.CenterVertically,
                modifier = Modifier
                    .fillMaxWidth()
                    .height(50.dp)
                    .padding(16.dp, 0.dp, 16.dp, 0.dp)
            ) 
                Text("List Item $index", fontSize = 15.sp, color = Color.Black)
            
            Divider(Modifier.height(0.4.dp))
        
    

在模拟器上运行效果如下图:


LazyRow则可以创建一个横向滑动的列表,示例代码如下:

    @Preview
    @Composable
    fun TestList() 
        LazyRow 
            items(10) 
                Image(
                    painter = painterResource(R.mipmap.avatar),
                    modifier = Modifier.size(100.dp).padding(8.dp),
                    contentDescription = null
                )
            
        
    

运行效果如下:

自定义图形

在传统的Android UI开发中,我们如果要自定义View,一般会自定义一个类继承自View或者ViewGroup,然后复写其中的onMeasure onLayout onDraw等方法,但是这套在Jetpack compose中不适用了,因为Jetpack compose是一套声明式的UI,而传统的Android UI开发是命令式UI。Jetpack compose中提供了Canvas用于绘制自定义图形,其使用方法如下:

@Preview
@Composable
fun TestCanvas() 
    Canvas(modifier = Modifier.fillMaxSize()) 
        val w = size.width
        // 画直线
        drawLine(
            start = Offset(x = 0f, y = 100f), // 起点坐标
            end = Offset(x = w, y = 100f), // 终点坐标
            color = Color.Black, // 线条颜色
            strokeWidth = 10f // 线条粗细
        )
        // 画圆
        drawCircle(
            color = Color.Red, // 填充颜色
            center = Offset(x = w / 2, y = 220f), // 圆心坐标
            radius = 100f // 半径
        )
        // inset用于调整当前作用域的默认参数,相当于画矩形时将起点坐标各+50
        inset(50f, 50f) 
            drawRect(
                color = Color.Blue, // 填充颜色
                topLeft = Offset(x = 0f, y = 350f), // 左上角坐标
                size = Size(300f, 150f) // 矩形大小(长宽)
            )
        
        // rotate将包裹在其中的矩形顺时针旋转30度
        rotate(degrees = 30f) 
            drawRect(
                color = Color.Gray,
                topLeft = Offset(x = w / 2, y = 900f),
                size = Size(200f, 90f)
            )
        
    

在模拟器上运行效果如下图:

以上是关于Android Jetpack Compose学习—— 各种控件的用法的主要内容,如果未能解决你的问题,请参考以下文章