Jetpack-Compose 布局 详解

2,073 阅读3分钟

Compose 基础知识

这套东西和android的view系统基本没有关系,更和flutter的那种自会引擎没有关联。 你可以把他理解为 只包含 android中 canvas和draw的一个 高级自定义view

也就是说Compose 编译出来的界面,你在设置里面把布局边界打开,他看起来就和原生的布局是一样的,各种组件之间都是有边界的,但实际上 他真的不是textview imageview 等等,完完全全的 是利用canvas和draw的机制 自己从头到尾 绘制出来的

为啥要这样做? 因为这样做的好处就是 我的Compose 的所有组件 都可以和android平台 脱离关系,我再也不需要担心 我发布了android新系统 因为用户没有升级 而导致的 特性用不到 等等等等,只要我一直更新我的jetpack库,开发者更新了对应的依赖,那么用户就能够使用到最新的android 特性

Compose的分包

可以看下官方文档

懒得看的 就看下这个截图

image.png

红框标注的 其实就是Compose的分包了,下面是对应的版本号,我们主要关注上面就可以。可以看出来这里就是分了六个包。

其中 material和material3 其实就是材料设计 一般我们不会使用它, 国内的公司喜欢自己搞设计规范。大家无视就好,有兴趣的可以用一下,其实就是一些简单的 组件,遵循谷歌的设计规范。

compiler 就是 compose的编译组件 ,对应着你的build文件的:

image.png

runtime 其实就是 提供运行时的组件,比如rememeber之类的,他往往和数据的计算有关。

ui 这个包 就是大部分的组件 比如 text和image 都在这个ui 包内。

foundation 这个是在ui包基础之上的,他提供了一系列便捷的组件,让你可以快速的写界面,比如Column和Row, 但其实你不用他 也可以,也能写出界面,用了以后 你会觉得更加方便,

除此之外,大家还需要关注这个accompanist 库,

这个库的作用是把你在使用compose的时候 觉得不爽的,欠缺的功能 先做到这个库里面,等到 谷歌的人发现,这个欠缺的功能已经做的很好了,就有可能 挪到compose的 基础库里面,也有可能谷歌发现 诶这个欠缺的功能 大家是不是都不用了,那我就直接删掉吧。

比如下图中的 pager 就是compose中 的 所谓 viewpager 组件。 image.png

另外要注意的是 红框中的 viewmodel-compose 组件 千万不要忘记了, 否则你在用compose的时候 会很麻烦。千万千万不要忘记。

Compose中的 FrameLayout

关键词 Box 其实就是view的叠加效果

@Composable
    fun frameLayout() {
        Box {
            Image(painterResource(R.mipmap.tly2), contentDescription = "佟丽娅", Modifier.size(100.dp), contentScale = ContentScale.Crop)
            Text(text = "佟丽娅", fontSize = 15.sp, color = Color.Green)
        }
    }
}

image.png

Compose中的 LinearLayout

分别对应着 Column 纵向布局,Row 横向布局

@Composable
fun linearLayout() {

    Column {
        Column {
            Text(text = "hello vivo ", fontSize = 15.sp, color = Color.Green)
            Text(text = "hello apple", fontSize = 15.sp, color = Color.Green)
        }

        Row() {
            Text(text = "hello xiaomi ", fontSize = 15.sp, color = Color.Red)
            Text(text = "hello 华为", fontSize = 15.sp, color = Color.Red)
        }
    }

}

image.png

Compose中的 相对布局

这个就是依靠 Box 和modifier 来互相配合


@Composable
fun relativeLayout() {
    Box(Modifier.background(Color.Black).size(100.dp)) {
        Text(text = "hello vivo ", fontSize = 15.sp, color = Color.Green, modifier = Modifier.align(Alignment.TopEnd))
        Text(text = "hello oppo ", fontSize = 15.sp, color = Color.Red, modifier = Modifier.align(Alignment.BottomStart))
    }
}

image.png

Compose中的Recyclerview

LazyColumn 与 LazyRow,写法上比传统的adapter 那一套 要高效许多

@Composable
fun recyclerview() {

    val itemsList = arrayListOf<String>()
    for (index in 1..100) {
        itemsList.add("hello vivo-${index}")
    }
    // 横向你就lazyRow
    LazyColumn {
        item {
            Image(painterResource(R.mipmap.tly2), contentDescription = "佟丽娅", Modifier.size(100.dp), contentScale = ContentScale.Crop)
        }
        items(itemsList) {
            Box(
                Modifier
                    .fillMaxWidth()
                    .height(30.dp)
            ) {
                Text(text = it, fontSize = 15.sp, color = Color.Red)
            }
        }
    }
}

image.png

Compose中的ScrollView

Scrollview 在Compose中 就是verticalScroll (当然也有水平的)

@Composable
fun scrollView() {
    Column(
        Modifier
            .fillMaxWidth()
            .height(300.dp)
            .verticalScroll(rememberScrollState())
    ) {
        Box(
            Modifier
                .fillMaxWidth()
                .background(Color.Black)
                .height(150.dp)
        ) {
            Text(text = "1", fontSize = 15.sp, color = Color.Red, modifier = Modifier.align(Alignment.Center))
        }
        Box(
            Modifier
                .fillMaxWidth()
                .background(Color.White)
                .height(150.dp)
        ) {
            Text(text = "2", fontSize = 15.sp, color = Color.Red, modifier = Modifier.align(Alignment.Center))
        }
        Box(
            Modifier
                .fillMaxWidth()
                .background(Color.Blue)
                .height(150.dp)
        ) {
            Text(text = "3", fontSize = 15.sp, color = Color.Red, modifier = Modifier.align(Alignment.Center))
        }
    }
}

image.png

Compose中的ViewPager

这个就和之前提过的一样,是com.google.accompanist 这个包下的, 但是要注意了 这个api 还不太稳定, 所以要加上对应的注解

@ExperimentalPagerApi
@Composable
fun viewPager() {
    val pagerState = rememberPagerState()
    HorizontalPager(state = pagerState, count = 10) {
        Text(
            text = "Page: $it", modifier = Modifier.fillMaxWidth()
        )
    }
}

Compose 中的 margin与padding

在传统的布局中,内边距padding和外边距的margin 概念大家很熟悉了,但是在compose中 是没有margin 只有padding的, 你要实现 margin的效果怎么做呢?

@Composable
fun marginOrPadding() {
    Column {
        Box(
            Modifier
                .background(Color.Black)
                .size(100.dp)) {
            Text(text = "Margin", fontSize = 15.sp, color = Color.Red, modifier = Modifier
                .padding(10.dp)
                .background(Color.White))
        }

        Box(
            Modifier
                .background(Color.Blue)
                .size(100.dp)) {
            Text(text = "Padding", fontSize = 15.sp, color = Color.Red, modifier = Modifier
                .background(Color.White)
                .padding(10.dp))
        }

    }

}

image.png

简而言之一句话,padding 在前 则为margin,padding在后 则为 padding, 注意下padding的顺序即可