Jetpack Compose 细节-发布文章页面

718 阅读3分钟

「这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战

用Compose写发布文章页面的过程中遇到了一些困难,逐一解决后一并分享给大家

效果图

ffdbf0f7c214b5aa2553ca180ad43e5.jpg

Scaffold

Scaffold 实现了基本的材料设计视觉布局结构。该组件提供 API 将多个Material组件组合在一起以构建您的屏幕,确保为它们提供适当的布局策略并收集必要的数据,以便这些组件能够正确协同工作

顶部的工具栏

利用Scaffold实现顶部的工具栏

Scaffold(
    modifier = Modifier.statusBarsPadding(),
    topBar = {
        TopBar()
    }
)

里面有 左上角的关闭图标和两个按钮
为了不让按钮显得很大,设定一个我觉得很舒服的高度32.dp

@Composable
private fun TopBar(state: ModalBottomSheetState) {
    TopAppBar(
        elevation = 1.dp,
        backgroundColor = CustomTheme.colors.statusBarColor
    )
    {
        Row(
            Modifier
                .fillMaxWidth()
                .padding(6.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
        //左上角的关闭图标
            Icon(
                painterResource(R.drawable.ic_arrow_left),
                null,
                Modifier
                    .clickable(onClick = { finish() })
                    .align(Alignment.CenterVertically)
                    .size(36.dp)
                    .padding(6.dp),
                tint = CustomTheme.colors.icon
            )
            Spacer(Modifier.weight(1f))

            Button(modifier = Modifier.height(32.dp),onClick = { } }) {
                Text("分类", fontSize = 13.sp, color = Color.White)
            }
            Spacer(Modifier.width(6.dp))
            Button(modifier = Modifier.height(32.dp), onClick = { }) {
                Text(text = "发布", fontSize = 13.sp, color = Color.White)
            }
        }
    }
}

编辑框

直接用系统的提供的就使用TextField或者OutlinedTextField, 系统不满足你的需求想自定义就需要用到BasicTextField

简单使用

@Composable
fun BasicTextFieldDemo() {
    var text by remember { mutableStateOf("hello") }
    BasicTextField(
        value = text,
        onValueChange = { text = it },
    )
}

image.png

TextField下划线

我是直接用系统提供的TextField
但设置了CutCornerShape后默认的下划线就显,怎么去掉呢?

175e8a8c22dc5ccaa9cfbab1e18b1e7.jpg

TextField有个TextFieldColors类型的参数colors

可以表示在不同状态的文本字段中使用的输入文本、背景和内容(包括标签、占位符、前导和尾随图标)的颜色

但目前找不到有直接设置下划线可见不可见的属性,那就把它设置透明叭

下划线颜色的有很多种情况

作用参数
有焦点时的颜色focusedIndicatorColor
无焦点时的颜色unfocusedIndicatorColor
禁用指示剂时的颜色disabledIndicatorColor
错误时候的颜色errorIndicatorColor
@Composable
fun TitleTextField(modifier: Modifier) {
    val text = remember { mutableStateOf(TextFieldValue()) }
    TextField(
        value = text.value,
        onValueChange = { text.value = it },
        label = if (text.value.text == "") {
            {
                Text(
                    "标题 (可选)",
                    color = CustomTheme.colors.textPrimary
                )
            }
        } else null,
        singleLine = true,
        colors = TextFieldDefaults.textFieldColors(
            textColor = CustomTheme.colors.textPrimary,
            backgroundColor = CustomTheme.colors.listItem,
            focusedIndicatorColor = Color.Transparent, // 有焦点时的颜色,透明
            unfocusedIndicatorColor = Color.Transparent, // 无焦点时的颜色,绿色
        ),
        modifier = modifier.fillMaxWidth(),
        shape = CutCornerShape(9.dp)
    )
}

130424608418cc903f5c6d0e37abff1.jpg

Compose软键盘顶起view

在输入内容时我希望底部的按钮

0ce785949fa6c9415556932a3763aee.jpg

可以被软键盘顶起来而不是隐藏在键盘后面

d05df7d07bd37db79632e6e0dbd94ab.jpg

Modifier.imePadding()

应用与窗框高度匹配的额外空间。软键盘沿内容底部边缘的高度。 此方法对WindowInset没有特殊处理。导航栏,通常与窗口插图相交。输入法。大多数应用程序通常都希望使用该修改器。导航栏SwithimePadding修改器

navigationBarsWithImePadding

Modifier.navigationBarsWithImePadding()

应用与虚拟按键高度匹配的额外空间,虽然大部人人都用全面屏手势,但我们还是要为少部分使用虚拟按键的人群考虑

在根布局将imePadding写上

ConstraintLayout(
    modifier = Modifier
        .background(CustomTheme.colors.background).fillMaxSize().imePadding()
        .padding(12.dp),
)

接着在onCreate下必须禁用窗口装饰装修

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    WindowCompat.setDecorFitsSystemWindows(window, false)//禁用窗口装饰装修
    setContent {
    ...
    }
}

当设置成false,就不再使用原定的间隔框架,我们的页面也就不再受状态栏的影响。
框架将不会将内容视图与嵌入物相适应,而只是将WindowInsetsCompat传递给内容视图。

8b712f194182ca1f029ece0d933d7c5.jpg

这时topBar 就会藏在了状态栏的后面了

解决办法statusBarsPadding()

Scaffold(
    modifier = Modifier.statusBarsPadding(),
    topBar = {
        TopBar()
    }
)

将Scaffold沿内容的顶部边缘应用与状态栏高度相匹配的额外空间即可

此时所有问题全部解决

ezgif.com-gif-maker (16).gif