Jetpack Compose 布局

1.标准布局组件

package com.tiger.jetpackcomposelayouts


import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp


val LocalContentAlpha = compositionLocalOf<Float> { error("No ViewModel found!") }

@Composable
fun PhotographerCard(modifier: Modifier = Modifier) {//用反射的方式去创建

    Row(
        modifier = modifier
            .clip(RoundedCornerShape(4.dp))//切圆角
            .background(color = MaterialTheme.colorScheme.surface)//白色 有黑就有白
            .clickable(onClick = {})
            .padding(16.dp)//这里如果 先padding 后clickable 就会在内填充的地方没有水泵
    ) {
        Surface(
            modifier = Modifier.size(50.dp),//大小50
            shape = CircleShape, //圆形
            color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.2f) //一个  颜色  黑色 alpha = 0.2f透明度,不让他那么透明
        ) {
            Image(
                painter = painterResource(id = R.drawable.touxiang),
                contentDescription = null
            )
        }
        Column(
            modifier = Modifier
                .padding(start = 8.dp)//左边距8 dp
                .align(Alignment.CenterVertically)//垂直居中

        ) {
            Text(text = "Alfred Sisley", fontWeight = FontWeight.Bold)

            CompositionLocalProvider(LocalContentAlpha provides 0.3f) {

                val ap = LocalContentAlpha.current
                //这个好像新版本没有
                Text(
                    text = "3 minutes ago", modifier = Modifier.alpha(ap)   //透明度
                    , style = MaterialTheme.typography.bodySmall// 字体样式
                )
            }

        }
    }

}
package com.jmj.myapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.jmj.myapp.ui.theme.MyAppTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyAppTheme {
                PhotographerCard()
            }
        }
    }
}

2.Slots Api

package com.jmj.myapp

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.AlertDialogDefaults.containerColor
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarColors
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LayoutStudy(){
    //插槽
    Scaffold(
        //解决头部
        topBar= { //顶部
            TopAppBar( //顶部组件
                title = { //标题
                    Text(text = "LayoutStudy")
                },
                actions = {//按钮,行为
                    IconButton(onClick = { /*TODO*/ }) { //图标按钮
                        Icon(imageVector = Icons.Filled.Favorite //矢量图标
                            ,contentDescription = null) //残障设计
                    }
                }, colors = TopAppBarDefaults.smallTopAppBarColors(containerColor= Color(0xFF753BDD))

            )
        }) { innerPadding -> //默认插槽下面是有自己的填充的 将填充的值传入进来
        //内容部分
        BodyContent(Modifier.padding(innerPadding))

    }
}

@Composable
fun BodyContent(modifier: Modifier =Modifier){
    //不管他传进来多少, 我在默认填充 8.dp
    Column(modifier = modifier.padding(8.dp)) {
        Text(text = "Hi there!")
        Text(text = "Thanks for going through the LayoutStudy !")
    }
}

3.列表

第一种实现方式

package com.tiger.jetpackcomposelayouts

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
import androidx.compose.ui.unit.dp
import coil.compose.SubcomposeAsyncImage
import coil.compose.rememberAsyncImagePainter
import coil.compose.rememberImagePainter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

@Composable
fun SimpleColumn() {
    Column {
        repeat(100) { //repeat函数 重复执行100次
            Text(text = "Item #$it", style = MaterialTheme.typography.bodyMedium)
        }
    }
}

/**
 * 上面的组件不支持滚动 由此来支持
 */
@Composable
fun SimpleList() {
    //给他一个状态
    val scrollState = rememberScrollState()
    //垂直方向上的滚动
    Column(Modifier.verticalScroll(state = scrollState)) {
        repeat(100) { //repeat函数 重复执行100次
            Text(text = "Item #$it", style = MaterialTheme.typography.bodyMedium)
        }
    }
}

/**
 * 这个是一个缓冲域,用于不知道有多少条数量的列表进行加载
 */
@Composable
fun LazyList() {
    //给他一个状态
    val scrollState = rememberLazyListState()
    LazyColumn(state = scrollState) {
        items(100) {
            Text(text = "Item #$it", style = MaterialTheme.typography.bodyMedium)
        }
    }
}


suspend fun fetch() {}

/**
 * 自动跳到首行和末尾
 */
@Composable
fun ScrollingList() {
    val scrollState = rememberLazyListState()
    val scope = rememberCoroutineScope()

    val map = remember {
        mutableStateOf(mutableMapOf("a" to "a"))
    }

    data class Student(
        val name: String,
        val age: Int,
    )

    val student = Student(name = "asd", age = 10).apply {
        this.copy(name = "修改")
    }

    LaunchedEffect(Unit, block = {
        scope.launch {
            fetch()
        }
    })

    Column {
        Row {
            Button(
                modifier = Modifier.weight(1f),
                onClick = {
                    scope.launch {
                        scrollState.animateScrollToItem(0)
                    }

                }
            ) {
                Text(text = "Scroll to the top")
            }

            Button(
                modifier = Modifier.weight(1f),
                onClick = {
                    scope.launch {
                        scrollState.animateScrollToItem(99)
                    }
                }
            ) {
                Text(text = "Scroll to the end")
            }
        }
        LazyColumn(state = scrollState) {

            item {
                Column {
                    map.value.entries.forEach {
                        Row {
                            Text(text = "${it.key}----------${it.value}")
                        }
                    }

                    Button(onClick = {
                        var m = map.value
                        val hashMap = HashMap<String, String>(m)
//                        val update = map.value.toMutableMap()
                        hashMap["b"] = "b"
                        map.value = hashMap
                    }) {
                        Text(text = "Add")
                    }
                }

            }
            items(100) {
                Row {
                    ImageListItem(it)
                    Text(text = "Item #$it", style = MaterialTheme.typography.bodyMedium)

                }
            }
        }

    }
}

@Composable
fun ImageListItem(index: Int) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        SubcomposeAsyncImage(
            model = "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
            loading = {
                CircularProgressIndicator()
            },
            contentDescription = "avatar",
            contentScale = ContentScale.Crop,
            modifier = Modifier.size(48.dp)
        )
//        Image(
//            painter = rememberAsyncImagePainter("https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"),
//            contentDescription = "image"
//        )
    }
}

 第二种实现方式

package com.jmj.myapp

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import coil.compose.rememberAsyncImagePainter
import kotlinx.coroutines.launch

@Composable
fun SimpleColumn() {
    Column {
        repeat(100) {
            Text(text = "Item  #$it", style = MaterialTheme.typography.bodyMedium)
        }
    }
}

/**
 * 上面是不能滚动的
 */
@Composable
fun SimpleList() {
    val scrollState = rememberScrollState()
    Column(Modifier.verticalScroll(scrollState)) {
        repeat(100) {
            Text(text = "Item  #$it", style = MaterialTheme.typography.bodyMedium)
        }
    }
}

/**
 * 缓冲集合,不知道集合的数量的时候可以用这个
 */
@Composable
fun LazyList() {
    val scrollState = rememberLazyListState()
    LazyColumn(state = scrollState) {//朝那个地方划他才会去重新绘制,这样节省了空间
        items(100) {
            Text(text = "Item  #$it", style = MaterialTheme.typography.bodyMedium)
        }
    }
}


/**
 * 小案例  点击按钮改变状态
 */
@Composable
fun ScrollingList() {
    val listSize = 100
    val scrollState = rememberLazyListState()
    val coroutineScope = rememberCoroutineScope()//拿到一个协程作用域
    Column {
        Row {

            Button(modifier = Modifier.weight(1f), onClick = {
                //通过状态 去滑动
                coroutineScope.launch {
                    scrollState.animateScrollToItem(0)
                }

            }) {
                Text(text = "Scroll to the top")
            }

            Button(modifier = Modifier.weight(1f), onClick = {
                coroutineScope.launch {
                    scrollState.animateScrollToItem(listSize-1)
                }

            }) {
                Text(text = "Scroll to the bottom")
            }
        }

        LazyColumn(state = scrollState) {//朝那个地方划他才会去重新绘制,这样节省了空间
            items(listSize) {
                    ImageListItem(index = it)
            }
        }
    }
}


/**
 * 在线图片组件
 */
@Composable
fun ImageListItem(index: Int) {
    Row(verticalAlignment = Alignment.CenterVertically) {//垂直居中
        Image(
            //给上图片路径即可
            painter = rememberAsyncImagePainter(model = "https://i01piccdn.sogoucdn.com/d0515abf9470c2d4"),
            contentDescription = "",
            modifier = Modifier.size(50.dp)//图片大小
        )
        Spacer(modifier = Modifier.size(10.dp)) //中间间隔距离
        Text(text = "Item  #$index", style = MaterialTheme.typography.bodyMedium)
    }
}

需要开启网络权限 

  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" /><!--开启网络的权限-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

 

4.自定义布局

 

4.1 第一种自定义布局, 自定义 让容器中字体的基准线到第一个父级边框的dp 为自定义

package com.jmj.myapp

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.magnifier
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.FirstBaseline
import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.jmj.myapp.ui.theme.MyAppTheme

fun Modifier.firstBaseLineToTop(//写一个扩展函数
        firstBaseLineToTop:Dp //参数为Dp 类型
)=this.then(
    layout{measurable, constraints -> //修改元素的位置
        //测量元素
        val placeable = measurable.measure(constraints)
        //测量之后,获取元素的基线值
        val firstBaseline = placeable[FirstBaseline] //文字底部到第一个父级元素的距离

        val placeableY =firstBaseLineToTop.roundToPx() - firstBaseline //用像素相减

        val height = placeable.height+placeableY

           layout(placeable.width,height){ //设置组件的总高度
                    placeable.placeRelative(0,placeableY) //设置元素坐标
            }
    }
)

@Composable
fun  TextWithPaddingToBaseLine(){

    MyAppTheme {

        Column() {
            Box(
                modifier = Modifier
                    .then(Modifier.border(1.dp, Color.Black))
            ) {
                Text(
                    text = "Hi there!", Modifier
                        .firstBaseLineToTop(24.dp)
                        .background(Color.Red)

                )

            }
        }


    }

}

4.2 第二种自定义布局 仿Column组件

package com.tiger.jetpackcomposelayouts

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.unit.dp
import com.tiger.jetpackcomposelayouts.ui.theme.JetpackComposeLayoutsTheme

@Composable
fun MyOwnColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
//这个modifier 修饰的是 content的父容器也就是MyOwnColumn

    //肯定会有Layout是由Layout去布局的 ,所以参数被使用的是 Layout这个父容器
  
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constrains ->
        // 测量里面的元素
        val placeables = measurables.map { measurable ->
            //一一测量
            //stream流类似 映射成  List<Placeable>
            measurable.measure(constrains)

        }
        var  yPosition = 0
        //当前布局的大小
        //父容器决定最大值
        layout(constrains.maxWidth, constrains.maxHeight) {
            placeables.forEach{placeable->
                placeable.placeRelative(x = 0,y=yPosition)
                yPosition+=placeable.height
            }
        }
    }


}

@Composable
fun MyOwnColumnSample() {

    JetpackComposeLayoutsTheme {
        MyOwnColumn(modifier = Modifier.padding(8.dp)) {
            Text(text = "MyOwnColumn")
            Text(text = "places items")
            Text(text = "vertically")
            Text(text = "we've done it by hand!")
        }
    }


}

4.3 第三种自定义布局 StaggeredGrid

  4.3.1 先写第一个 卡片

package com.tiger.jetpackcomposelayouts

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp



val topics = listOf(
    "Arts & Crafts",
    "Maths",
    "Chinese",
    "Books",
    "Beauty",
    "Fashion",
    "Deign",
    "History",
    "Film",
    "Business",
)




@Composable
fun StaggeredGrid(
    modifier: Modifier = Modifier
) {
    Chip(modifier,"Arts & Crafts")

}


@Composable
fun Chip(
    modifier: Modifier = Modifier,
    text: String
) {
    //一个卡片,圆角,里面包含一个Row ,第一列是Box ,第二列是文本
    Card(
        modifier = modifier,
        border = BorderStroke(color = Color.Black, width = Dp.Hairline),//边框 黑色 1像素
        shape = RoundedCornerShape(8.dp)//圆角边框弧度
    ) {
        Row(
            modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp), //水平方向 和垂直方向 填充
            verticalAlignment = Alignment.CenterVertically //垂直居中
        ) {
            //Row里的内容
            Box(
                modifier = Modifier
                    .size(16.dp, 16.dp)
                    .background(color = MaterialTheme.colorScheme.secondary)
            )//一个正方形图片
            Spacer(modifier = Modifier.width(4.dp))

            Text(text = text)


        }

    }


}

 4.3.2 开始StaggeredGrid 布局

package com.tiger.jetpackcomposelayouts

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import kotlin.math.max


val topics = listOf(
    "Arts & Crafts",
    "Maths",
    "Chinese",
    "Books",
    "Beauty",
    "Fashion",
    "Deign",
    "History",
    "Film",
    "Business",
)


@Composable
fun StaggeredGrid(
    modifier: Modifier = Modifier,
    rows: Int = 3, //自定义传进来多少行
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        //计算每一行的宽度和高度

        val rowWidths = IntArray(rows) { 0 }//用来存放每行的宽度值  = 每行的元素宽度之和

        val rowHeight = IntArray(rows) { 0 }//用来存放每行的高度值

        val placeables: List<Placeable> = measurables.mapIndexed { index, measurable ->
            //测量所有元素
            val placeable = measurable.measure(constraints)
            //计算每一行的宽度与高度
            //元素下标 ,假设总共11个元素
            //index :0,1,2,3,4,5,6,7,8,9,10
            //行数 ,假设3行
            //rows:3
            // 保存行宽高数组的下标值:
            //row 0,1,2
            val row = index % rows
            //一行的宽度等于这一行所有元素之和
            rowWidths[row] += placeable.width;
            //一行的高度等于这一行所有元素高度最高的
//            val i = rowHeight[row]
//            val height = placeable.height
//            if (i<height){
//                rowHeight[row]=height
//            }// 等价于
            rowHeight[row] = max(rowHeight[row], placeable.height)
            placeable
        }

        //计算表格的宽高
        //表格的宽度,应该是所有行当中最宽的那一行的宽度
        val width = rowWidths.maxOrNull() ?: constraints.minWidth
        //表格的高度,应该是所有最高的高度之和
//        val height = rowHeight.sumOf { it }  等价
        val height = rowHeight.sum()

        //设置每一行的Y坐标
        val rowY = IntArray(rows) { 0 }
        // 索引从1开始 ,是因为第一行Y 的坐标肯定为0,row[0] = 0
        for (i in 1 until rows) {
            rowY[i] = rowY[i - 1] + rowHeight[i - 1]
        }

        layout(width, height) {

            val rowX = IntArray(rows) { 0 }

            //设置每一个元素的坐标
            placeables.forEachIndexed { index, placeable ->
                val row = index % rows //读出下表
                val x = rowX[row]
                val y = rowY[row]
                placeable.placeRelative(x, y)
                rowX[row] += placeable.width
            }

        }

    }

}


@Composable
fun Chip(
    modifier: Modifier = Modifier,
    text: String
) {
    //一个卡片,圆角,里面包含一个Row ,第一列是Box ,第二列是文本
    Card(
        modifier = modifier,
        border = BorderStroke(color = Color.Black, width = Dp.Hairline),//边框 黑色 1像素
        shape = RoundedCornerShape(8.dp)//圆角边框弧度
    ) {
        Row(
            modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp), //水平方向 和垂直方向 填充
            verticalAlignment = Alignment.CenterVertically //垂直居中
        ) {
            //Row里的内容
            Box(
                modifier = Modifier
                    .size(16.dp, 16.dp)
                    .background(color = MaterialTheme.colorScheme.secondary)
            )//一个正方形图片
            Spacer(modifier = Modifier.width(4.dp))

            Text(text = text)


        }

    }


}

@Composable
fun StaggeredGridBodyContent(modifier: Modifier = Modifier) {
    Row(
        modifier = modifier
            .background(color = Color.LightGray)
            .padding(16.dp)
            .horizontalScroll(rememberScrollState()), //水平滚动
        content = {
            StaggeredGrid(modifier = Modifier, rows = 2) {
                for (topic in topics) { //从上面的主题集合 放入
                    Chip(modifier = Modifier.padding(8.dp), text = topic)
                }
            }
        }
    )

}

 

4.4 约束布局

 

 4.4.1 导入Compose对约束布局的支持依赖

    implementation("androidx.constraintlayout:constraintlayout-compose:1.0.0-beta01") 
第一种
@Composable
fun ConstraintLayoutContent(){
        ConstraintLayout {
            //通过createRefs创建引用,ConstrainLayout 中的每个元素都需要关联一个引用
            val (button,text) = this.createRefs() //创建两个对象 的引用 button,text
            Button(
                onClick = {},
                // 使用Modifier.constrainAs来提供约束,引用作为它的第一个参数
                //在lambda表达式中指定约束规则
                modifier = Modifier.constrainAs(button){//关联引用
                    //使用linkTo 指定约束,parent 是 ConstraintLayout 的引用
                   this.top.linkTo(this.parent.top, margin = 16.dp)
                }
            ) {
                Text(text = "Button")
            }

            Text(text = "Text", modifier = Modifier.constrainAs(text){
                this.top.linkTo(button.bottom, margin = 16.dp)
                //在ConstraintLayout 中水平居中
                this.centerHorizontallyTo(parent)
            })

        }
}

第二种
@Composable
fun ConstraintLayoutContent2(){
    ConstraintLayout {
       val (button1,button2,text) = createRefs()
        Button(
            onClick = {},
            modifier = Modifier.constrainAs(button1){
                top.linkTo(parent.top, margin = 16.dp)
            }
        ) {
            Text(text = "Button 1")
        }

        Text(text = "Text", modifier = Modifier.constrainAs(text){
            this.top.linkTo(button1.bottom, margin = 16.dp)
            centerAround(button1.end)//它的中间 在button1按钮的结尾
        })
        //将button1 和 text组合起来,建立一个屏障(barrier)
        val barrier = createEndBarrier(button1,text)
        Button(
            onClick = {},
            modifier = Modifier.constrainAs(button2){
                top.linkTo(parent.top, margin = 16.dp)
                start.linkTo(barrier) //起始是在构建的组合的末尾
            }
        ) {
            Text(text = "Button 1")
        }

    }
}

第三种:文字换行约束


@Composable
fun LargeLayoutContent(){
    ConstraintLayout {
        val text = createRef()
        val guidenline = createGuidelineFromStart(fraction =0.5f)//指导线将会位于布局的水平方向上中央的位置
        Text(text = "this is  a very very very very very very very very very very very very very very very very very very very very very very very long Text"
            , modifier = Modifier.constrainAs(text){
            linkTo(start = guidenline ,end = parent.end)
             width= Dimension.preferredWrapContent//开启可以自动换行
        })
    }

5.解耦API

 

@Composable
fun DecoupledConstraintLayout2() {
    BoxWithConstraints {

        val constraints = if (maxWidth<maxHeight){
            decoupledConstraint(16.dp) //竖屏
        }else{
            decoupledConstraint(160.dp)//横屏
        }
        ConstraintLayout (constraints){
            //需求:想要屏幕横屏的时候不一样,竖屏的时候又不一样
            Button(
                onClick = {},
                modifier = Modifier.layoutId("button")
            ) {
                Text(text = "Button")
            }

            Text(text = "Text", modifier = Modifier.layoutId("text"))
        }
    }
}


private fun decoupledConstraint(margin: Dp): ConstraintSet {

    return ConstraintSet {
        val button = createRefFor("button")//给予ID
        val text = createRefFor("text")//给予ID

        this.constrain(button)
        {
            top.linkTo(parent.top, margin)
        }

        this.constrain(text)
        {
            top.linkTo(button.bottom, margin)
        }
    }
}

6.Intrinsics

 

package com.tiger.jetpackcomposelayouts

import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material3.Divider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp


@Composable
fun TwoTexts(modifier:Modifier=Modifier){

    Row (modifier = modifier.height(IntrinsicSize.Min)){

        Text(
            text = "Hi",
            modifier = Modifier
                .weight(1f)
                .padding(start = 4.dp)
                .wrapContentWidth(Alignment.Start)
        )

        Divider(
            color = Color.Black,
            modifier = Modifier
                .fillMaxHeight()
                .width(1.dp)
        )

        Text(
            text = "There",
            modifier = Modifier
                .weight(1f)
                .padding(start = 4.dp)
                .wrapContentWidth(Alignment.End)
        )
    }


}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值