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学习—— 各种控件的用法的主要内容,如果未能解决你的问题,请参考以下文章

Android Jetpack Compose学习—— Jetpack compose基础布局

Android Jetpack Compose学习—— Jetpack compose入门

Android Jetpack Compose学习—— Jetpack compose入门

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

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

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