前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >compose--CompositionLocal、列表LazyColumn&LazyRow、约束布局ConstraintLayout

compose--CompositionLocal、列表LazyColumn&LazyRow、约束布局ConstraintLayout

作者头像
aruba
发布于 2022-12-11 01:20:01
发布于 2022-12-11 01:20:01
1.1K00
代码可运行
举报
文章被收录于专栏:android技术android技术
运行总次数:0
代码可运行

通过前面内置组件和修饰符Modifier的使用,结合Stat状态,相信对于一般的开发需求已经没有问题了,接下来对CompositionLocal进行学习,以及对列表组件LazyColumn&LazyRow和约束布局的完善ConstraintLayout

一、CompositionLocal

CompositionLocal可以创建以树为作用域的具名对象,简单来说就是可组合函数的作用域内,其所有的内容组件都可以隐式的拿到和修改CompositionLocal中的内容,针对组件的颜色、样式等属性值,他们往往按照一套风格来设计,使用隐式调用更加合适

1.MaterialTheme主题

之前我们在使用一些ShapeColorTextStyle时,用到了MaterialThemeshapescolorstypography获取,这些都是CompositionLocal对象

创建项目时,也会自动帮助我们创建一个主题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private val DarkColorScheme = darkColorScheme(
    primary = Purple80,
    secondary = PurpleGrey80,
    tertiary = Pink80
)

private val LightColorScheme = lightColorScheme(
    primary = Purple40,
    secondary = PurpleGrey40,
    tertiary = Pink40

    /* Other default colors to override
    background = Color(0xFFFFFBFE),
    surface = Color(0xFFFFFBFE),
    onPrimary = Color.White,
    onSecondary = Color.White,
    onTertiary = Color.White,
    onBackground = Color(0xFF1C1B1F),
    onSurface = Color(0xFF1C1B1F),
    */
)

@Composable
fun MyComposeApplicationTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    // Dynamic color is available on Android 12+
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit
) {
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
        }
        darkTheme -> DarkColorScheme
        else -> LightColorScheme
    }
    val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            (view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb()
            ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = darkTheme
        }
    }

    MaterialTheme(
        colorScheme = colorScheme,
        typography = Typography,
        content = content
    )
}

官方也推荐使用md风格,也就是使用预设的几种颜色,尺寸等对组件进行样式的选择,并且整体APP遵循md风格进行设计

在项目中,直接使用定义的Theme主题包含compose组件,即可获取md风格的样式,以及深色与浅色主题的切换:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyComposeApplicationTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    MyScaffold()
                }
            }
        }
    }
}

效果:

2.CompositionLocalProvider

CompositionLocalProvider可以临时改变CompositionLocal的属性值,如果你想要对某些组件的样式进行特殊处理,推荐使用CompositionLocalProvider,此改变只争对该作用域内的组件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Preview
@Composable
fun MyCompositionLocalProvider() {
    MyComposeApplicationTheme { // MaterialTheme sets ContentAlpha.high as default
        Column {
            Text("Uses MaterialTheme's provided alpha")
            CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5f)) {
                Text("Medium value provided for LocalContentAlpha")
                Text("This Text also uses the medium value")
                CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)) {
                    DescendantExample()
                }
            }
        }
    }
}

@Composable
fun DescendantExample() {
    // CompositionLocalProviders also work across composable functions
    Text("This Text uses the disabled alpha now")
}

效果:

3.自定义CompositionLocal

我们也可以为组件自定义CompositionLocal,方式有两种:

3.1 compositionLocalOf

在重组期间只有读取current的组件才会发生重组:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 定义数据类
data class TextColor(var color: Color)

// 定义CompositionLocal
val LocalColors = compositionLocalOf { TextColor(Color.Black) }

object Colors {
    val Blue: TextColor
        get() = TextColor(color = Color.Blue)
    val Red: TextColor
        get() = TextColor(color = Color.Red)
}

@Composable
fun MyTextColor(
    text: String,
    color: Color = LocalColors.current.color
) {
    Text(text, color = color)
}

@Preview
@Composable
fun MyCompositionLocalProvider2() {
    Row {
        MyTextColor("hi")

        Spacer(modifier = Modifier.width(10.dp))

        CompositionLocalProvider(LocalColors provides Colors.Red) {
            MyTextColor("hi")
        }
    }
}

预览效果:

3.2 staticCompositionLocalOf

staticCompositionLocalOf 为更改值会导致提供 CompositionLocal 的整个 content lambda 被重组,如果提供的值发生更改的可能性微乎其微或永远不会更改,使用 staticCompositionLocalOf 可提高性能

二、列表LazyColumn&LazyRow

LazyColumnLazyRow相当于RecyclerView,内部组件并不会全部一次性加载,而是利用缓存机制,适用于加载大量的数据

1.LazyRow

LazyRow 支持横向滑动:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Composable
fun LazyRow(
    modifier: Modifier = Modifier,
    state: LazyListState = rememberLazyListState(),// 可以获取当前第一个显示的元素索引的状态
    contentPadding: PaddingValues = PaddingValues(0.dp),// 为内容组件设置的padding
    reverseLayout: Boolean = false,
    horizontalArrangement: Arrangement.Horizontal =
        if (!reverseLayout) Arrangement.Start else Arrangement.End,//可以通过Arrangement.spacedBy(xx.dp)设置元素的间距
    verticalAlignment: Alignment.Vertical = Alignment.Top,// 垂直对齐方式
    flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
    userScrollEnabled: Boolean = true,
    content: LazyListScope.() -> Unit
) 

例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Preview
@Composable
fun MyLazyRow() {
    LazyRow {
        items(100) { index ->
            Text(
                text = "hi${index}",
                modifier = Modifier
                    .width(50.dp)
                    .padding(top = 10.dp, bottom = 10.dp),
                textAlign = TextAlign.Center
            )
        }
    }
}

效果:

2.LazyColumn

LazyColumn即纵向滑动列表,我们可以配合使用stickyHeader达到粘性标题:

例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@OptIn(ExperimentalFoundationApi::class)
@Preview
@Composable
fun MyLazyColumn() {
    val lazyListState = rememberLazyListState()

    LazyColumn(
        state = lazyListState,
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(10.dp)
    ) {
        stickyHeader {
            Text(
                text = "index:${lazyListState.firstVisibleItemIndex}",
                modifier = Modifier
                    .background(MaterialTheme.colorScheme.surface)
                    .padding(10.dp),
                color = MaterialTheme.colorScheme.onSurface
            )
        }

        items(100) { index ->
            Text(
                text = "hi${index}",
                color = MaterialTheme.colorScheme.onSurface,
                modifier = Modifier
                    .fillMaxWidth()
                    .background(MaterialTheme.colorScheme.surface)
                    .padding(top = 10.dp, bottom = 10.dp)
                    .animateItemPlacement(),// 显示时的动画效果
                textAlign = TextAlign.Center
            )
        }
    }
}

效果:

除了LazyRowLazyColumn外,此外还有LazyVerticalGridLazyHorizontalGrid 可组合项为在网格中显示列表项提供支持,用法上是大致相同的

三、约束布局ConstraintLayout

ConstraintLayout面对一些复杂布局中,对对齐要求较高时,使用ConstraintLayout时一个很好的选择,它能够做到不需要嵌套各种RowBox等布局,只用一个约束布局实现内部组件的对齐,可以通过官网介绍进行学习使用:ConstraintLayout

ConstraintLayout需要导入依赖,版本可以通过官网查看: ConstraintLayout 版本页面

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
1.创建引用,使用约束

ConstraintLayout作用域内,需要通过createRefs()createRefFor()为内容组件创建引用,通过约束条件,如linkTo()对引用的组件进行对齐,约束条件由constrainAs() 修饰符提供

例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Preview
@Composable
fun MyConstraintLayout1() {
    ConstraintLayout {
        // 创建两个引用
        val (txt, btn) = createRefs()

        // 对button、text两个组件分别设置引用
        Button(
            onClick = { /*TODO*/ },
            // 为button进行约束
            modifier = Modifier.constrainAs(btn) {
                // 以父组件顶部,进行一个16dp的margin
                top.linkTo(parent.top, margin = 16.dp)
            }
        ) {
            Text("hi")
        }

        Text(
            "小弟",
            // 为text进行约束
            modifier = Modifier.constrainAs(txt) {
                // 位于btn的下面,并且有一个16dp的margin
                top.linkTo(btn.bottom, margin = 16.dp)
            })
    }
}

预览效果:

2.解构

如果你不想在ConstraintLayout作用域内定义引用以及约束规则,那么可以将 ConstraintSet 作为参数传递给 ConstraintLayout,外部通过createRefFor("key")指定一个字符串key创建引用,constrain("key")进行约束条件;内容组件使用修饰符layoutId("key")进行约束匹配

例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Preview
@Composable
fun MyConstraintPreview2() {
    BoxWithConstraints {
        val constraints = if (minWidth < 600.dp) {
            decoupledConstraints(margin = 16.dp) // Portrait constraints
        } else {
            decoupledConstraints(margin = 32.dp) // Landscape constraints
        }
        ConstraintLayout(constraintSet = constraints) {
            Button(
                onClick = { /* Do something */ },
                // 找到引用
                modifier = Modifier.layoutId("button")
            ) {
                Text("hi")
            }

            Text("老弟", Modifier.layoutId("text"))
        }
    }
}

private fun decoupledConstraints(margin: Dp): ConstraintSet {
    return ConstraintSet {
        val button = createRefFor("button")
        val text = createRefFor("text")

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

预览效果:

3.Guideline

Guideline:可以创建一个指示线,指示线可以相较于父组件的topbottomstartend以一个百分比dp进行偏移,以便别的组件可以针对指示线进行约束,Guideline创建方式有以下4种:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 // 较于父组件左边10%位置创建
val startGuideline = createGuidelineFromStart(0.1f)
// 较于父组件右边10%位置创建
val endGuideline = createGuidelineFromEnd(0.1f)
// 较于父组件顶部16dp位置创建
val topGuideline = createGuidelineFromTop(16.dp)
// 较于父组件底部16dp位置创建
val bottomGuideline = createGuidelineFromBottom(16.dp)

例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Preview
@Composable
fun MyGuidelinePreview() {
    ConstraintLayout(modifier = Modifier.fillMaxSize()) {
        val txt = createRef()
        val startGuideline = createGuidelineFromStart(0.5f)

        Text(text = "hi", modifier = Modifier.constrainAs(txt) {
            start.linkTo(startGuideline)
        })
    }
}

预览效果:

4.Barrier

Barrier可以将多个内容组件引用组合成一个屏障,其他的组件就可以以屏障Barrier来进行约束,创建Barrier有以下4中方式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 以btn,txt进行组合,创建右边的barrier
 val barrier = createEndBarrier(btn, txt)
// 以btn,txt进行组合,创建左边的barrier
 val barrier = createStartBarrier(btn, txt)
// 以btn,txt进行组合,创建顶部的barrier
 val barrier = createTopBarrier(btn, txt)
// 以btn,txt进行组合,创建底部的barrier
 val barrier = createBottomBarrier(btn, txt)

例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Preview
@Composable
fun MyBarrierPreview() {
    ConstraintLayout {
        val (btn, txt) = createRefs()

        // 对button、text两个组件分别设置引用
        Button(
            onClick = { /*TODO*/ },
            // 为button进行约束
            modifier = Modifier.constrainAs(btn) {
                // 以父组件顶部,进行一个16dp的margin
                top.linkTo(parent.top, margin = 16.dp)
            }
        ) {
            Text("hi")
        }

        Text(
            "小弟",
            // 为text进行约束
            modifier = Modifier.constrainAs(txt) {
                // 位于btn的下面,并且有一个16dp的margin
                top.linkTo(btn.bottom, margin = 16.dp)
                start.linkTo(btn.end)
            })

        // 创建barrier
        val barrier = createEndBarrier(btn, txt)
        val txt2 = createRef()

        Text(
            "老弟",
            modifier = Modifier.constrainAs(txt2) {
                start.linkTo(barrier)
                top.linkTo(btn.top)
            }
        )
    }
}

预览效果:

5.Chain

Chain用于将多个内容组件引用组合成以个链,并以不同的 ChainStyles 配置链内各个组件的分布,创建方式有两种:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建水平的链
val chain = createHorizontalChain(txt1, txt2, txt3, chainStyle = ChainStyle.SpreadInside)
// 创建垂直的链
val chain = createVerticalChain(txt1, txt2, txt3, chainStyle = ChainStyle.SpreadInside)

ChainStyles配置:

  • ChainStyle.Spread:空间会在所有可组合项之间均匀分布,包括第一个可组合项之前和最后一个可组合项之后的可用空间。
  • ChainStyle.SpreadInside:空间会在所有可组合项之间均匀分布,不包括第一个可组合项之前或最后一个可组合项之后的任何可用空间。
  • ChainStyle.Packed:空间会分布在第一个可组合项之前和最后一个可组合项之后,各个可组合项之间没有空间,会挤在一起。

例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Preview
@Composable
fun MyChainPreview() {
    ConstraintLayout(Modifier.fillMaxSize()) {
        val (txt1, txt2, txt3) = createRefs()
        val chain = createHorizontalChain(txt1, txt2, txt3, chainStyle = ChainStyle.SpreadInside)

        Text("hi1", modifier = Modifier.constrainAs(txt1) {})
        Text("hi2", modifier = Modifier.constrainAs(txt2) {})
        Text("hi3", modifier = Modifier.constrainAs(txt3) {})
    }
}

预览效果:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Vue 框架学习系列五:Vue 3 与状态管理库 Pinia 的深度集成
在构建复杂的 Vue.js 应用时,状态管理是一个重要的考虑因素。Vuex 是 Vue.js 官方推荐的状态管理库,但随着 Vue 3 和 Composition API 的发布,一个新的状态管理库 Pinia 开始崭露头角。Pinia 提供了与 Vue 3 和 Composition API 更紧密的集成,同时保持了 Vuex 的核心概念,如 state、mutations、actions 和 getters。本篇文章将探讨如何在 Vue 3 应用中深度集成 Pinia。
china马斯克
2024/10/04
3190
pinia核心笔记
记录pinia核心源码阅读笔记,这里跳过hmr(热更新), mapHelpers(class 工具)等工具源码。 剔除的部分vue2.0兼容代码。 当前pinia版本2.0.13
copy_left
2022/05/13
1.1K0
pinia核心笔记
​轻松掌握vuex,让你对状态管理有一个更深的理解
Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式 。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
前端老鸟
2019/07/29
3.4K0
制作一个轻量级的状态管理插件:Vue-data-state
Vuex 是针对 Vue2 来设计的,因为 option API 本身有很多缺点,所以 Vuex 只好做各种补丁弥补这些缺点,于是变得比较“复杂”。
用户1174620
2021/04/28
8800
制作一个轻量级的状态管理插件:Vue-data-state
【玩转全栈】---- Pinia 组件状态管理器
Pinia 是一个用于 Vue 3 的状态管理库,旨在提供更加简洁、直观且灵活的状态管理模式。它由 Vue 官方团队成员开发,以其轻量级和高性能著称。Pinia 支持 Vue 3 的组合式 API,并允许开发者以一种更自然的方式组织和共享应用状态。与 Vuex 不同,Pinia 去除了复杂的概念如模块嵌套,转而采用扁平化的 store 结构,使得代码更加清晰易懂。此外,Pinia 还支持 TypeScript,提供了优秀的类型推断能力,增强了开发体验。通过 Pinia,你可以轻松地创建多个独立的 store 模块,每个模块都可以拥有自己的 state(状态)、getters(计算属性)、actions(方法)等,极大地简化了复杂应用中的状态管理。其灵活性还体现在对插件系统的良好支持,可以方便地扩展功能。总的来说,Pinia 是现代 Vue 应用中进行状态管理的理想选择。
用户11404404
2025/03/12
1060
Vue3之状态管理:Vuex和Pinia,孰强孰弱?
在前端开发中,状态管理器是一种用于管理应用程序全局状态的工具。它通常用于大型应用程序,可以帮助开发者更好地组织和管理状态,并提供一些强大的工具来简化状态的变更和使用。
用户6297767
2023/11/21
2.6K0
Vue3之状态管理:Vuex和Pinia,孰强孰弱?
Vue项目进阶:再谈Pinia函数式(composition API)用法
Hello大家好,前段时间写了一篇关于Pinia的composition API用法的文章《Pinia进阶:优雅的setup(函数式)写法+封装到你的企业项目》,收到了不少朋友的反馈和建议。笔者也结合最近项目情况和网友们的建议做一次优化,也算是一个比较完整的版本了,这包括:
南山种子外卖跑手
2022/04/21
3.5K0
Vue项目进阶:再谈Pinia函数式(composition API)用法
Pinia 入门:零基础开启 Vue 状态管理之旅
在现代 Vue 应用开发中,高效的状态管理是构建强大、可维护应用的关键。Pinia 作为一种新兴的状态管理方案,为 Vue 开发者带来了全新的体验。本文将带你从零开始,深入了解 Pinia 的基础知识,开启 Vue 状态管理的精彩之旅。
程序媛夏天
2024/11/19
3900
Pinia.js - Vue新一代状态管理器
安装成功会把依赖加在 package.json 的 dependencies 中。
青年码农
2022/09/27
1.3K1
Pinia.js - Vue新一代状态管理器
感受 Vue 新的状态管理工具之美之 Pinia---学习篇
相信在Vue中提到状态管理,大家一定会想到 Vuex。的确 Vuex确实是比较强大的,但Vuex 多少有点重,而且对 Typescript的支持也不是那么的友好,同时门槛也比较高,学习成本比较大。
用户9078190
2022/10/28
2530
感受 Vue 新的状态管理工具之美之 Pinia---学习篇
学习 Vue 3 全家桶 - vuex
现代 Web 应用都是由三大件构成,分别是:组件、数据和路由。在一些数据组件之间需要共享的时候,应该如何实现?
Cellinlab
2023/05/17
3480
学习 Vue 3 全家桶 - vuex
vue3了,试试轻量化的Vuex -- Pinia?
Pinia 是 Vue.js 的轻量级状态管理库,最近很受欢迎。它使用 Vue 3 中的新反应系统来构建一个直观且完全类型化的状态管理库。
玖柒的小窝
2021/11/04
1.5K0
vue3了,试试轻量化的Vuex -- Pinia?
Pinia入门-实现简单的用户状态管理
在整个应用程序中访问的数据(且不需要被持久化),例如导航栏中显示的用户信息,以及需要通过页面保留的数据,例如一个非常复杂的多步骤表格。
luciozhang
2023/04/22
7640
测试一下Pinia,Vuex 要出局了?
自从我开始使用Vue 3和组合API以来,我也尝试使用 Pinea 作为状态管理库。如果是从是 vue2 和 vuex 过来的,就会觉得用起来差别还是很大的。
前端小智@大迁世界
2022/09/01
6530
测试一下Pinia,Vuex 要出局了?
告别Vuex,发挥compositionAPI的优势,打造Vue3专用的轻量级状态 定义main.jscontroller组件设置监听和钩子局部状态
Vuex 是基于 Vue2 的 option API 设计的,因为 optionAPI 的一些先天问题,所以导致 Vuex 不得不用各种方式来补救,于是就出现了 getter、mutations、action、module、mapXXX 这些绕圈圈的使用方式。想要使用 Vuex 就必须先把这些额外的函数给弄明白。
用户1174620
2021/10/20
1.1K0
一杯茶的时间入门Vue新的状态管理库Pinia
Pinia 是 Vue.js 官方推荐的新一代状态管理库,它提供了非常简洁和直观的 API,可以极大地提高我们管理应用状态的效率。本文将深入介绍 Pinia 的各种高级用法,内容涵盖:
linwu
2023/08/08
4440
一杯茶的时间入门Vue新的状态管理库Pinia
Vue.js 状态管理:Pinia 与 Vuex
Vuex 和 Pinia 是用于管理 Vue.js 应用程序状态的标准 Vue.js 库。让我们比较一下他们的代码、语言、功能和社区支持。
海拥
2023/02/27
2.7K0
Vue3中使用Pinia详解
Pinia是一个专门为Vue.js设计的状态管理库,它提供了一种简单和直观的方式来管理应用程序的状态。在使用Pinia时,可以轻松地创建定义状态的存储,然后将其与Vue组件绑定,使它们能够使用该状态。和上一个博客提到的Vuex相比,Pinia 更加简单易用,体积更小,同时具有更好的 TypeScript 支持和插件系统。
九仞山
2023/10/14
9960
使用 Vue 3 与 TypeScript 构建 Web 应用: Todo
引言 界面: Vue.js 3 JavaScript 超集: TypeScript 包管理器: pnpm 前端工程化/打包: Vite 路由: Vue Router 状态管理: Pinia CSS 预处理器: Less 代码格式化: Prettier 代码质量: ESLint 预览
yiyun
2023/07/17
1.2K0
使用 Vue 3 与 TypeScript 构建 Web 应用: Todo
Pinia状态管理器学习笔记,持续记录
官方文档:https://pinia.vuejs.org/ 中文文档:https://pinia.web3doc.top/
房东的狗丶
2023/02/17
1.7K0
推荐阅读
相关推荐
Vue 框架学习系列五:Vue 3 与状态管理库 Pinia 的深度集成
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • 一、CompositionLocal
    • 1.MaterialTheme主题
    • 2.CompositionLocalProvider
    • 3.自定义CompositionLocal
      • 3.1 compositionLocalOf
      • 3.2 staticCompositionLocalOf
  • 二、列表LazyColumn&LazyRow
    • 1.LazyRow
    • 2.LazyColumn
  • 三、约束布局ConstraintLayout
    • 1.创建引用,使用约束
    • 2.解构
    • 3.Guideline
    • 4.Barrier
    • 5.Chain
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档