Compose实用知识

一些实用的知识总是用起来的时候提笔忘字,所以专门开帖子记录

993、compose绘制背景

compose绘制背景使用drawBehind操作符来实现

例如如果我们想设置聊天背景,那么因为compose是无法直接设置图片背景的,所以.9.png就无法使用,这个使用可以使用drawBehind来了实现背景绘制(只能绘制纯色,带图案的无法拉伸,这一点还是不能完全替代.9.png)。

drawBehind操作符和background操作符冲突,会互相覆盖

代码

Box(Modifier.background(Color.Red)) {
    Box(Modifier
        .size(80.dp)
        .drawBehind {
            drawImage(
                bitmap.asImageBitmap(),
                srcSize = IntSize(bitmap.width, bitmap.height),
                dstSize = IntSize((density * 50).toInt(), (density * 50).toInt()),
                srcOffset = IntOffset.Zero,
                dstOffset = IntOffset.Zero
            )
        }) {
    }
    Text(text = "将图片绘制到成一个宽高50dp的情况")
}
Box(Modifier.background(Color.Red)) {
    Box(Modifier
        .size(80.dp)
        .drawBehind {
            val density = density.toInt()
            this.drawImage(
                bitmap.asImageBitmap(),
                srcOffset = IntOffset(15 * density, 15 * density),
                srcSize = IntSize(bitmap.width, bitmap.height),
                dstOffset = IntOffset(40 * density, 40 * density),
                dstSize = IntSize(density * 35, density * 35)
            )
            //                        dstSize = IntSize(density * 50, density * 50)
        }) {
    }
    Text(text = "将图片绘制到成一个宽高50dp的情况")
}

995、 Compose更改输入框键盘回车键行为的方式 (20220404)

代码

关键就是下面的三个属性:
其中keyboardOption用来设置输入的内容类型和返回键展示的样式
keyboardActions用来展示回车键被点击相应的行为后的回调方法
singleLine=true尤其要设置单行为true,否则回车键的行为图标不会发生改变

singleLine = true, keyboardOptions = KeyboardOptions(
    keyboardType = KeyboardType.Text,
    imeAction = actionData.imeAction
), keyboardActions = KeyboardActions(
    onDone = {
        showToast("onDone")
    },
    onGo = {
        showToast("onGo")
    },
    onNext = {
        showToast("onNext")
    },
    onPrevious = {
        showToast("onPrevious")
    },
    onSearch = {
        showToast("onSearch")
    },
    onSend = {
        showToast("onSend")
    }
)

实现效果

compose软键盘回车键行为更改.gif

995、Compose实现键盘弹出和关闭的方法

代码

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun KeyboardShowAndHide() {
    var text by remember {
        mutableStateOf("")
    }
    val requester = remember {//用于请求焦点的对象
        FocusRequester()
    }
    val keyboard = LocalSoftwareKeyboardController.current//用于操作键盘的对象
    LaunchedEffect(key1 = Unit, block = {
        requester.requestFocus()//首次进入和重组页面请求焦点
        keyboard?.show()//首次进入页面弹出键盘,注意必须先获取焦点才能弹出键盘成功
    })
    Column(
        Modifier
            .padding(top = 150.dp)
            .fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        OutlinedTextField(
            value = text, onValueChange = {
                text = it
            }, modifier = Modifier.focusRequester(requester)//focusRequester方法表明让OutLineTextField可以获取焦点
        )
        Button(onClick = {
            requester.requestFocus()//替OutLineTextField请求焦点,一定要获取焦点才能操作键盘
            keyboard?.hide()//关闭键盘
        }, modifier = Modifier.fillMaxWidth()) {
            Text(text = "关闭键盘")
        }
    }
}

效果

在这里插入图片描述

996、Compose中使用mutableStateListOf实现列表数据观察

我们实现这样一个需求,在ViewModel中声明一个mutableStateListOf的对象datas。然后我们使用这个列表渲染数据,当我们点击列表中item的时候就向datas中添加一条数据,然后列表的数据可以实时刷新预览。

?为什么我们要使用mutableStateListOf而不是mutableListOf呢,因为如果使用mutableListOf那么当我们向列表中添加数据的时候,我们渲染的列表是无法更新数据预览的。所以我们必须使用mutableStateListOf。

实现代码如下

@Composable
fun Test() {
    val model: TestModel = viewModel()
    CustomScaffold(title = "测试页面") {
        LazyColumn(content = {
            itemsIndexed(model.datas) { index: Int, data: Int ->
                Box(
                    Modifier
                        .padding(5.dp)
                        .fillMaxWidth()
                        .height(50.dp)
                        .border(width = 1.dp, color = Color.Green)
                        .clickable {
                            model.datas.add(index + 1)
                        },
                    contentAlignment = Alignment.Center
                ) {
                    if (index == model.datas.size - 1) {
                        Icon(
                            imageVector = Icons.Default.Add,
                            contentDescription = "",
                            tint = Color.Red
                        )
                    } else {
                        Text(text = data.toString())
                    }
                }
            }
        })
    }
}

class TestModel : ViewModel() {
    val datas = mutableStateListOf(0)
//    val datas = mutableListOf(0,1,2,3)
}

git:https://github.com/ananananzhuo-blog/ComposeApiSample/blob/main/app/src/main/java/com/ananananzhuo/composeapi/ui/function/MutableStateListOfView.kt

实现效果

使用mutableStateListOf实现数据渲染编辑

997、Compose返回键监听方法

方法1

@Composable
fun Back1(controller: NavHostController) {
    Column(
        Modifier
            .fillMaxSize()
            .background(Color.Red)
            .clickable {
                controller.popBackStack()
            }) {
        Text(text = "点击返回上一个页面")
        Text(text = "使用BackHandler实现返回键监听")
    }
    BackHandler(enabled = true) {
        Log.e("tag","返回键被点击")
    }
}

方法2

在@Composable方法中加入如下监听设置,方法1的实现方式就是使用如下方式实现的

@Composable
fun Back2(controller: NavHostController) {
    Column(
        Modifier
            .fillMaxSize()
            .background(Color.Green)
            .clickable {
                controller.popBackStack()
            }) {
        Text(text = "点击返回上一个页面")
        Text(text = "使用OnBackPressedDispatcher监听返回键被点击")
    }
    val callback = remember {
        object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                log("回退键被点击")
                showToast("监听到返回键被点击监听")
            }
        }
    }
    val dispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
    DisposableEffect(key1 = Unit, effect = {
        dispatcher?.addCallback(callback)
        onDispose {
            callback.remove()
        }
    })
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wQozz9aR-1648286447554)(https://github.com/ananananzhuo-blog/ComposeApiSample/blob/main/app/src/main/java/com/ananananzhuo/composeapi/ui/function/BackKey.kt)]

998、防快速点击

说明

防快速点击主要使用 Modifier 操作符来实现,代码如下

代码

@Composable
fun Modifier.avoidRepeatclickable(millis: Long = 500, onClick: () -> Unit): Modifier {
    var timeStamp by remember {
        mutableStateOf(0L)
    }

    return clickable {
        if (System.currentTimeMillis() - timeStamp > millis) {
            onClick()
            timeStamp = System.currentTimeMillis()
        }
    }
}

git:https://github.com/ananananzhuo-blog/ComposeApiSample/blob/main/app/src/main/java/com/ananananzhuo/composeapi/ui/function/AvoidFastClick.kt

效果

gif 中有两个按钮,

  • 第一个使用正常的 clickable,每次点击悲剧都会变色;

  • 第二个按钮使用了我们的防快速点击操作符,500ms 内多次点击之后出发一次背景变色;

compose防快速点击

999、Compose 中跳转 Activity,并获取返回结果

说明

这里需要使用 ActivityResult Api,compose 专门进行了扩展

需要使用的扩展库如下:

androidx.activity:activity-compose:1.3.0

代码

val launcher = rememberLauncherForActivityResult(contract =object : ActivityResultContract<String, String>() {
        override fun parseResult(resultCode: Int, intent: Intent?): String {
           return intent?.getStringExtra("data")?:""
        }

        /**
         * @param compose向Compose中传的数据 ActivityResultContract<String, String>的第一个泛型
         */
        override fun createIntent(context: Context, input: String?): Intent {
            return Intent(context,GenerateActivityResultActivity::class.java).apply {
                putExtra("data",input)
            }
        }
    } , onResult = {result-> //result 是ActivityResultContract<String, String>第二个泛型
        activityResult = result
    })

git 地址:https://github.com/ananananzhuo-blog/ComposeApiSample/blob/main/app/src/main/java/com/ananananzhuo/composeapi/ui/function/LaunchToActivityExpectResult.kt

效果

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值