第一个,Text 的跑马灯效果,对标传统 TextView 的跑马灯效果,通过 Modifier.basicMarquee() 即可实现,代码非常简单:

Text(
    text="This text is very long.".repeat(100),
    maxLines = 1,
    modifier = Modifier.basicMarquee()
)

效果:

在这里插入图片描述

第二个,放大镜效果,主要是 Modifier.magnifier 这个修饰符,参考代码如下:

var offset by remember { mutableStateOf(Offset.Zero) }
Box(
   modifier = Modifier
       .fillMaxWidth()
       .pointerInput(Unit) {
           detectDragGestures { change, dragAmount ->
               offset = change.position
           }
       }
       .magnifier(
           sourceCenter = {
               offset
           },
           magnifierCenter = {
               offset - Offset(x = 0f, y = 200f)
           }
       )
) {
   Image(
       painter = painterResource(R.drawable.kermit),
       contentDescription = null,
       modifier = Modifier.fillMaxWidth(),
       contentScale = ContentScale.FillWidth
   )
}

效果如下:

在这里插入图片描述

如果要实现常见的圆形放大镜效果,只需将上面代码稍加修改,为 magnifier 加一个 style 属性配置即可:

var offset by remember { mutableStateOf(Offset.Zero) }
Box(
    modifier = Modifier
        .fillMaxWidth()
        .pointerInput(Unit) {
            detectDragGestures { change, dragAmount ->
                offset = change.position
            }
        }
        .magnifier(
            sourceCenter = {
                offset
            },
            magnifierCenter = {
                offset - Offset(x = 0f, y = 200f)
            },
            style = MagnifierStyle(
                size = DpSize(100.dp, 100.dp),
                cornerRadius = 100.dp
            )
        )
) {
    Image(
        painter = painterResource(R.drawable.kermit),
        contentDescription = null,
        modifier = Modifier.fillMaxWidth(),
        contentScale = ContentScale.FillWidth
    )
}

效果如下:

在这里插入图片描述

第三个,Modifier.drawWithContent,这个修饰符可以让我们在原本组件内容绘制的之前和之后的时机做一些自己的绘制操作,比如在原来的文字图片后面画个背景,或者在原来的内容之上画个圆画个圈、添加一些小装饰啥的,别提有多方便了。

下面是一个简单的示例:

@Preview(showBackground = true)
@Composable
fun DrawBefore() {
    Box(
        modifier = Modifier.size(120.dp),
        contentAlignment = Alignment.Center
    ) {
        Card(
            shape = RoundedCornerShape(8.dp),
            modifier = Modifier
                .size(100.dp)
                .drawWithContent {
                	// 显示在drawContent()的下层,即背景
                    drawRect( 
                        Color.Green,
                        size = Size(110.dp.toPx(), 110.dp.toPx()),
                        topLeft = Offset(x = -5.dp.toPx(), y = -5.dp.toPx()),
                        //style = Stroke(width = 5f)
                    )
                    // 在 drawContent() 的前后自定义绘制一些内容,可以控制绘制的层级
                    drawContent()
                    drawCircle( // 显示在drawContent()的上层层,即前景
                        Color(0xffe7614e),
                        radius = 18.dp.toPx() / 2,
                        center = Offset(drawContext.size.width, 0f)
                    )
                }
        ) {
            Image(
                painter = painterResource(id = R.drawable.ic_head3),
                contentDescription = "head",
                contentScale = ContentScale.Crop
            )
        }
    }
}

drawWithContent修饰符的lambda中,drawContent()这一句是必须调用的,它是组件原本的绘制内容,而在它的前后可以分别Canvas的Api进行自定义绘制,最终会分别显示为原本内容的背景和前景。

显示效果如下:

在这里插入图片描述

其实像这样方便的 DrawModifier 修饰符,Compose 总共提供了三个: drawWithContentdrawBehinddrawWithCache。不一一介绍了,感兴趣可以看这篇:Jetpack Compose 中的 Canvas ,这篇文章里我已经全部整理好了。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐