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的情况") } 复制代码
994、 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") } ) 复制代码
实现效果
995、Compose实现键盘弹出和关闭的方法(20220403更新)
代码
@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 = "关闭键盘") } } } 复制代码
效果
Compose中使用mutableStateListOf实现列表数据观察
我们实现这样一个需求,在ViewModel中声明一个mutableStateListOf的对象datas。然后我们使用这个列表渲染数据,当我们点击列表中item的时候就向datas中添加一条数据,然后列表的数据可以实时刷新预览。
?为什么我们要使用mutableStateListOf而不是mutableListOf呢,因为如果使用mutableListOf那么当我们向列表中添加数据的时候,我们渲染的列表是无法更新数据预览的。所以我们必须使用mutableStateListOf。
996、实现代码如下
@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) } 复制代码
实现效果
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() } }) } 复制代码
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() } } } 复制代码
效果
gif 中有两个按钮,
- 第一个使用正常的 clickable,每次点击悲剧都会变色;
- 第二个按钮使用了我们的防快速点击操作符,500ms 内多次点击之后出发一次背景变色;
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 地址:github.com/ananananzhu…