Compose 修饰符 - 原理

Android Compose Modifier 在 Android 的 Compose 框架中,`Modifier` 是一种非常强大且灵活的工具,它用于修饰 Compose UI 元素的行为、布局和外观。你可以用它来做很多事情,比如设置宽度、高度、点击事件、拖拽动作等。在这篇文章中,我们将详细讲解 `Modifier` 的用法,并带你逐步走过实际代码示例。 阅读详情
AI摘要

本文深入解析 Jetpack Compose 中 Modifier 的底层链表结构、调用顺序优化策略及自定义实践。重点涵盖 Modifier 链式构建机制、Element 与 Modifier Node 的状态管理差异、graphicsLayer() 图层合并以减少 GPU 过度绘制、Lambda 版本 Modifier 避免无效重组,以及自定义 Modifier 提升复用性与性能的方法。

一、概念

不可变性每个Modifier操作(如padding/background)都会返回一个新的Modifier,原Modifier不变,避免副作用。
链式调用通过链式调用连接多个修饰符,按“从左到右”的顺序累加生效,顺序影响最终效果。
装饰者模式每个修饰符不修改组件本身,而是包装组件,添加额外能力(如clickable为组件添加点击事件)。
单一职责每个修饰符只做一件事(如padding仅处理边距,background仅处理背景),便于组合和复用。

在 NodeKind.kt 文件中根据功能对 Modifier 类型进行了分类。

1.1 什么时候用到

三大使用场景:

  • 修改外观(尺寸、样式、布局、行为)。详见
  • 添加交互功能(点击、滚动、拖拽、缩放)。详见
  • 添加额外信息(如无障碍标签)。

1.2 调用顺序(优化)

每一个 Modifier 都是对前一个结果的再包装,调用顺序的不同直接影响最终效果。先通过布局类型明确大小位置 → 再通过绘制类型进行内容装修 → 最后通过交互类型让成本响应用户操作。遵循这个顺序,确保组件行为符合直觉且性能最高。

  • 布局类型(先完成布局阶段的):size/padding/weight等大小,align/offset等位置。
  • 绘制类型(再完成绘制阶段的):background/border/clip等。
  • 交互类型(最后才搞别的):clickable/draggable/focusable等。

1.2.1 减少布局计算

用 remember() 缓存需要复杂计算的尺寸/位置,避免每次布局阶段重复计算。

val screenWidth = LocalConfiguration.current.screenWidthDp.dp
val itemWidth by remember(screenWidth) {
    derivedStateOf { screenWidth * 0.8f }
}
Box(modifier = Modifier.size(itemWidth)) {}

1.2.2 使用带 Lambda 参数版本的 Modifier 读取状态

应该尽量避免在 Modifier 修饰符上读取状态,因为它并不是用来显示数据的地方。标准的 Modifier 函数是一定会在组合阶段被执行的,当状态变化时会重新创建 Modifier 实例,UI树会先删除旧的再添加新的实例,而UI树的变化会导致重组,每次重组都可能触发 组合→布局→绘制 三个阶段,若读取的是一个频繁变化的状态非常要命(动画或滚动)。

val color by animateColorBetween(Color.Blue, Color.Red)
Box(
    modifier = Modifier.background(color)    //Box必须在每一帧上重组,因为每一帧的颜色值都在变化
)

有时不可避免需要一直读取一个不断变化的值从而达到变化的绘制效果。带 Lambda 参数版本的 Modifier 函数不会在组合阶段被执行(根据修改类型延迟到布局阶段或绘制阶段),Modifier实例不会改变,因此UI树不会变化,Compose只会在需要的时候调用 Lambda,也就可以跳过不必要的重组了。

@Composable
fun Demo() { 
    var offsetX by remember { mutableStateOf(0f) }
    val modifier1 = Modifier.offset(x = offsetX.dp)    //直接读取
    val modifier2 = Modifier.offset{ val newX = offsetX.dp }    //在Lambda中读取
}

1.2.3 合并图形操作 graphicsLayer()

绘制类型的修饰符,底层都是使用 Modifier.graphicsLayer() 实现的,都会创建一个图形层,例如应用 alpha 效果:

  1. 保存 (Save) 当前的绘制状态。
  2. 创建一个新的、独立的 Layer (离屏缓冲区)。
  3. 把内容绘制到这个新 Layer 上。
  4. 对整个 Layer 应用 alpha 效果。
  5. 把修改后的 Layer 绘制回主画布。
  6. 恢复 (Restore) 原始的绘制状态。

每一次 save 和 restore 都是有成本的。当把这些绘制类型的修饰符分开写时,就相当于在反复支付这个“图层税”。使用 Modifier.graphicsLayer() 相当于批处理,一次性完成多种图形变换,减少GPU过度绘制避免重复计算。由于只是绘制,当它读取状态时,请求的是 GPU 重绘,完全绕过了 Kotlin 代码的执行逻辑。这几乎是 0 CPU 开销。

graphicsLayer()fun Modifier.graphicsLayer(block: GraphicsLayerScope.() -> Unit): Modifier
GraphicsLayerScope

interface GraphicsLayerScope : Density {
    var scaleX: Float        //X轴缩放
    var scaleY: Float        //Y轴缩放
    var alpha: Float        //透明度
    var translationX: Float
    var translationY: Float
    var shadowElevation: Float        //阴影高度
    var ambientShadowColor: Color
    var spotShadowColor: Color
    var rotationX: Float        //X轴旋转角度
    var rotationY: Float        //Y轴旋转角度
    var rotationZ: Float        //Z轴旋转角度
    var cameraDistance: Float        //查看图层的距离(拉远拉进)
    var transformOrigin: TransformOrigin

    var clip: Boolean        //是否裁切
    var shape: Shape        //形状
    var renderEffect: RenderEffect?        //高斯模糊
    var blendMode: BlendMode        //混合模式
    var colorFilter: ColorFilter?        //色彩滤镜
    var compositingStrategy: CompositingStrategy
    val size: Size        //尺寸
}

错误示范:三种绘制类型修饰符分别创建了独立的图层,并且 RoundedCornerShape(12.dp) 这个形状的路径计算也可能被重复执行了多次。

modifier = Modifier
    //Layer1:透明度
    .alpha(0.5F)
    //Layer2:裁剪
    .clip(RoundedCornerShape(12.dp))
    //Layer3:阴影
    .shadow(8.dp, RoundedCornerShape(12.dp))

正确使用:

modifier = Modifier
    .graphicsLayer {
        alpha = 0.5F,
        shadowElevation = 8.dp.toPx(),
        shape = RoundedCornerShape(12.dp),
        clip = true,
        renderEffect = BlurEffect(10f, 10f)
    }
    .background(Colors.red)    //背景会被绘制在上面创建的Layer内部并自动被裁剪

1.3 为组合函数添加 Modifier 参数

任何一个组合项都应该有一个 Modifier 参数,以便让调用方进行调整。

  • 放在第一个可选参数位置:由于是可选参数,放在所有必传参数后面,这样调用方就可以选择是否传递那些有默认值的可选参数,否则就必须被强制性的先指定 Modifier 才能传必传参数。 
  • 作用于内部根节点上:调用方一般只需要调整根节点的布局,对于内部子元素的配置可通过传递其它的参数来配置。
  • 避免重复使用:将同一个 Modifier 传递给不同的可组合共享,可能引起不必要的重组。
  • 同名覆盖问题:通过 then() 可以定义组件内部配置和外部传入配置的顺序。对尺寸的设置参考 Constrains(详见),一般都会用具体值(fillMaxSize、100.dp)因此以第一个为准,约束范围写死了(最大值最小值都是100dp)后续再调用不会生效。offset 多次调用会多次偏移。background 默认情况下只看得到后一个,如果多次调用之间存在 padding、 offset 就不会完全覆盖,可以看到之前的颜色。
@Composable
fun Out() {
    //调用时指定对齐方式
    In(Modifier.background(Color.Red))
}

@Composable
fun In(
    text: String,
    modifier: Modifier = Modifier,    //放在第一个可选参数位置
    enable: Boolean = true
) {
    // 传入的 Modifier 作用域根部节点
    Box(
        // 举例一:这里把外部配置放在了最前面,最终显示 Blue
        modifier = modifier
            .background(Color.Blue)

        // 举例二:这里把外部配置放在了后面,最终显示 Red
        modifier = Modifier
            .background(Color.Blue)
            .then(modifier)
    )
}

1.3 底层结构原理

        Modifier底层是一个链表结构,每个修饰符节点包含Element(具体操作)和next(下一个修饰符),Compose在测量/布局/绘制组件时,会遍历修饰符链表,依次应用每个修饰符的逻辑。 

       Modifier#then 创建 Element 加入 Modifier chain 中。Element 是无状态的,重组中会重新生成,Element 会在组合中创建有状态的 Modifier Node。Modifier Node 有状态,重组中仅当状态发生变化时被更新,否则不会重新生成。Modifier Node 是 Compose 1.5 引入的新优化,目的就是通过存储 Modifier 状态参与比较,提升重组性能。

interface Modifier {
    interface Element : Modifier {...}

    companion object : Modifier {...}

    class CombinedModifier {...}

    fun then() {...}
}

fun Modifier.composed() {...}

Element 子接口调用 Modifier 不同的配置方法会返回各种 Modifier 的实现类对象(如 .size() 返回 SizeElement、.background() 返回 BackgroundElement),这些实现类又都是 Element 类型。
companion 伴生对象伴生对象实现了 Modifier,因此类名 Modifier 可以用作链式调用的开头。
CombinedModifier

class CombinedModifier(
    internal val outer: Modifier,        //当前的 Element
    internal val inner: Modifier        //新增的 Element
) : Modifier

内部维护的数据结构,用于连接调用链中的每个 Element 结点,类似于俄罗斯套娃一样的装饰者模式。

then() 函数

用于连接两个 Element 的方法,底层就是用的 CombinedModifier 结构。

composed() 扩展函数

fun Modifier.composed(
    inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo,
    factory: @Composable Modifier.() -> Modifier
): Modifier

内部持有一个工厂 Lambda 来生产 Modifier,用于实现内部有状态的 Modifier,如监听手势的修饰符 .pointerInput() 底层就是用到 composed()。

1.3.1 链式调用

Modifier.size(100.dp).background(Color.Red).padding(10.dp)

当链式调用 Modifier 的时候,先调用的会包裹后调用的(加入到链表尾部),最里层是 Layout Node。

  • 调用 .size() 生成 SizeElement。
  • 调用 .background() 生成 CombinedModifier(outer  = SizeElement, inner = BackgroundElement)。
  • 调用 .padding() 生成 CombinedModifier(outer = CombinedModifier(SizeElement, BackgroundElement), inner = PaddingElement)。 

二、自定义 Modifier(优化)

2.1 提取重复使用的效果

将相同的效果(修饰符链)提取到变量中,以便在多个组件中重复使用,这样做有助于提高代码可读性,还有助于提升应用性能。

  • 对使用修饰符的可组合项进行重组时,不会重新分配修饰符。
  • 修饰符链可能很长并且非常复杂,因此重复使用相同的链实例可以减轻 Compose 运行时在对比时所需的工作量。
  • 这种提取方式可提高整个代码库中的代码简洁性、一致性和可维护性。

2.1.1 简单使用

注意有些修饰符限定了作用域,只能在特定场景下使用,如 BoxScope 的 matchParentSize()

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

@Composable
fun Demo() {
    Box(modifier = reusableModifier)
    Box(modifier = reusableModifier)
}

2.1.2 观察频繁变化的状态时

在组件中观察频繁变化的状态时(如动画状态、scrollState)可能引发大量重组,在这种情况下,Modifier 会在每次重组时创建实例,这可能发生在动画的每一帧。可以提取 Modifier 到可组合项外面来重用。

val reusableModifier = Modifier
    .padding(12.dp)
    .background(Color.Gray)

@Composable
fun Demo() {
    val animatedState = animateFloatAsState(/*...*/)
    LoadingWheel(
        // 无需分配内存,因为只是重复使用同一个实例
        modifier = reusableModifier,
        animatedState = animatedState
    )
}

2.1.3 延迟布局条目复用

延迟布局会大量创建条目,复用 Modifier 可以优化内存。

val reusableItemModifier = Modifier
    .padding(bottom = 12.dp)
    .size(216.dp)
    .clip(CircleShape)

@Composable
private fun Demo(authors: List<Author>) {
    LazyColumn {
        items(authors) {
            // 无需分配内存,因为我们只是重复使用同一个实例。
            AsyncImage(modifier = reusableItemModifier)
        }
    }
}

2.1.4 进一步链接提取的修饰符

通过调用 then() 进一步链接或附加提取的修饰符链。

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

// 追加到自己的修饰符后面
reusableModifier.clickable { /*...*/ }

// 追加到别人的后面
otherModifier.then(reusableModifier)

2.2 自定义带参数的修饰符

fun Modifier.cardStyle(
    backgroundColor: Color = Color.White,
    cornerRadius: Dp = 8.dp,
    elevation: Dp = 4.dp
): Modifier {
    return this
        .background(backgroundColor, shape = RoundedCornerShape(cornerRadius))
        .shadow(elevation, shape = RoundedCornerShape(cornerRadius))
        .padding(16.dp)
}

2.3 自定义 Element

//自定义测量和摆放
fun Modifier.XXX(): Modifier = then(
    layout { measurable, constraints ->
        //TODO...
    }
}

//去掉涟漪效果
fun Modifier.clickableNoRipple(onClick: () -> Unit): Modifier = composed {
    clickable(
        onClick = onClick,
        interactionSource = remember { MutableInteractionSource() },
        indication = null
    )
}

三、添加额外信息

        在Compose的内部,是用树型结构来存储一次重组过程中每个Composable函数节点的。一颗就是我们现在看到的重组树,另外一颗则是我们看不到的语义树。

        语义树完全不参与绘制和渲染工作,因此是完全不可见的,它只为 Accessibility 和 Test 服务。Accessibility需要根据语义树的节点内容进行发音,Test则需要根据语义树找到想要测试的节点来执行测试逻辑。

        绝大部分情况下不需要专门为语义树去做什么事情,标准的组合项已经在内部处理好了这些工作(Button嵌套一个Text,它俩是独立控件,Talkback会单独发声,但只要控件可点击,就会自动将所有子节点合并)。若使用了一些底层API自行绘制界面(日历选中8号,只会发音选中日历),这些工作就得自己来做了。

.semantics(
    mergeDescendants: Boolean = false,
    properties: (SemanticsPropertyReceiver.() -> Unit)
)

允许向当前Compose控件添加键值对形式的额外信息,但是不能覆写。

.clearAndSetSemantics(
    properties: (SemanticsPropertyReceiver.() -> Unit)
)

相对用得更多一些,它会把Compsoe控件之前携带的一些额外信息都清除掉。

Compose 去除点击水波纹阴影效果_局部and全局去除-CompositionLocal实例 一针对单个view,去除点击效果,可以在clickable中添加indication=null,interactionSource=remember{MutableInteractionSource()}实际开发中,要求去掉点击效果,不单单是一个view,肯定是整个界面,甚至是整个应用,如何全局去除默认的点击效果?针对整个Activity,你可以在最root的compose里设置,通过CompositionLocal(composeview的点击默认有阴影效果,实际开发中要求去除?...... 阅读详情

相关推荐

Jetpack Compose——LazyRow、LazyColumn简单使用

LazyRow: LazyRow( modifier: Modifier = Modifier,//布局修饰 state: LazyListState = rememberLazyListState(),//列表状态 contentPadding: PaddingValues = PaddingValues(0.dp),//内边距 reverseLayout: Boolean = false,//反转滚动和布局的方向 horizontalArrangement:

lplj717的博客 2698

compose--修饰符Modifier

上次介绍了compose中大多数的标准组件,此外还有两个重要的组件:列表LazyColumn和LazyRow,以及约束布局ConstraintLayout,在使用它们之前,先来认识Modifier 修饰符Modifier Modifier之前已经运用过,它能做的事情很多,不仅仅是改变组件的样式,还能够改变组件的位置,以及自定义交互事件,关于Modifier的所有用法,可以查看官方文档:https:...

aruba的博客 3128

Compose 常用UI组件

Compose 预置了很多基础组件,如 Button,TextField,TopAppBar等,他们都是基于 Material Design规范设计等。同时也提供了 Column,Row,Box等容器组件,每个基础组件都有一个Modifier修饰符。

BoBoMEe 1505

Compose:Modifier、CombinedModifier 和 ComposedModifier

Compose Modifier

Vincent的博客 570

Compose 中的 touch 事件

pointerInput 为 Compose 中处理所有手势事件的入口,可以编写自己的手势处理程序来自定义手势。和原生开发中的 touch 事件一样,经由抵达以及实际根 View 的DecorView。经由 ViewGroup 的分发抵达 Compose 最上层的的。将转化为类型并交由处理。处理过程中先调用的记录 touch 事件的分发路径。接着调用执行分发,并按照两个步骤抵达 Compose 的各层 Node:步骤一:首先调用进行Initial和Main策略的事件分发。这其中会调用各。

yuantian_shenhai的博客 3002

Compose鱼骨加载动画:从原理到实践

本文深入解析了如何在安卓Jetpack Compose中实现鱼骨加载动画(Skeleton Screen with Shimmer),以提升应用加载体验。文章从Shimmer动画的图形学原理讲起,详细阐述了Compose修饰符(Modifier)的核心机制,并通过一个完整的订单列表实战案例,手把手教你五步构建流畅的骨架屏效果,涵盖状态管理、组件复用及性能优化等关键实践。

weixin_29253711的博客 209

Compose 实践与探索十一 —— ParentDataModifier

)但是这样的话,在实现 modifyParentData() 的具体内容时,你需要去查阅 Box 的父组件 Row 的内部都用到了哪些 parentData,这是一件很麻烦的事情。因此,这种方式不可行。@Stable。

tmacfrank 1580

Jetpack Compose Modifier顺序问题解析与最佳实践

在Android开发中,Jetpack Compose的Modifier机制是构建UI的核心技术之一。其链式调用特性决定了修饰符的应用顺序会直接影响最终效果,这涉及到Compose的绘制原理和布局系统。理解Modifier的工作原理对开发高质量UI至关重要,特别是在处理交互状态与视觉效果的叠加时。典型的应用场景包括点击效果与透明度的组合,其中修饰符顺序错误会导致按压态失效等问题。通过掌握交互修饰符、布局修饰符和绘制修饰符的正确排列规则,开发者可以避免常见陷阱,同时提升代码可维护性。本文以clickable和

weixin_29174141的博客 140

5-Compose开发-Modifier进阶

在前一篇文章中,我们学习了 Modifier 的基础用法、分类和顺序规则。现在,让我们深入探索 Modifier 的进阶世界——从核心原理到高性能自定义,从作用域控制到复杂交互,全面掌握 Modifier 的高级用法。本文结合了原理剖析与实际案例,帮助你在 Compose 开发中游刃有余。根据需求复杂度,自定义 Modifier 可以选择不同层次的方法。) = thisText(text = "默认样式",Text(text = "红色圆角20dp",Box() {

weixin_36848576的博客 622

RouterOS网桥VLAN实战:从零构建安全隔离的二层虚拟网络

本文详细讲解了如何在RouterOS上利用网桥和VLAN功能,从零开始构建安全隔离的二层虚拟网络。通过分步实战演示,涵盖核心概念、网桥创建、PVID设置、VLAN规则配置及安全过滤,帮助网络管理员实现办公、访客与服务器网络的逻辑隔离与灵活管理,提升网络安全性。

u9v0w的博客 504

计算机视觉之姿态识别(原理+代码实操)

计算机视觉中的姿态识别原理+模型介绍,同时通过代码实操简单的演示基于mediapipe的单人姿态识别。

输出既学习 3万+

Jetpack Compose 更新一览 | 2022 Android 开发者峰会

作者 /Android 开发者关系工程师 Jolanda Verhoef去年我们发布了 Jetpack Compose,此后一直在进行优化。我们已添加了新的功能并创造出功能更强大的工具,帮助您获得更高效、更直观、更有趣的 Android 界面开发体验。如果您正在开发一款新应用,那现在是时候用 Compose 来编写了!这一激动人心的 Compose 版本现可支持 Material Design ...

谷歌开发者 576

比利时风电光伏负荷一体化数据集解析与应用

本文深度解析了由比利时输电系统运营商Elia集团提供的风电光伏负荷一体化数据集。该数据集整合了负荷、风电与光伏出力数据,并包含多时间尺度的官方预测值,时间跨度长达四年,是研究能源转型、构建电力预测模型及分析电网运行的宝贵资源。文章详细介绍了数据价值、字段含义、实战应用场景(如预测模型基准测试、风光互补性分析)以及数据处理指南,为相关领域的研究与开发提供了高质量数据基础和实践参考。

weixin_29200741的博客 429

Android全新UI编程 - Jetpack Compose 超详细教程

1. 简介 Jetpack Compose是在2019Google i/O大会上发布的新的库。Compose库是用响应式编程的方式对View进行构建,可以用更少更直观的代码,更强大的功能,能提高开发速度(这一段是谷歌自己说的)。 说实话,View/Layout的模式对安卓工程师来说太过于熟悉,对于学习曲线陡峭的Jetpack Compose能不能很好的普及还是有所担心。 因为Jetpack Compose的内容比较多,我会分成多个文章来进行介绍。 内容包括常用UI组件的使用,Flow和Compose的结合.

Android23333的博客 7359

海康SDK实战:如何从PS流中提取H264裸流并实现前端播放(附完整代码)

本文详细介绍了如何利用海康SDK从PS流中提取H264裸流,并构建无插件前端播放的完整链路。通过解析PS流结构、提取H264 ES流,结合WebSocket实时传输与WFS.js前端播放器,实现了低延迟、高可控性的视频流处理方案,为开发者提供了从数据源到前端渲染的实战代码与清晰指南。

weixin_29051811的博客 476

FC7300 Clock介绍

FC7300的时钟架构包括一个高级时钟图和内部时钟需求。它有5个CMU,使用SIRC监控FIRC/SOSC/FOSC,并使用FIRC监控SIRC。此外,CMU4还使用FOSC监Slow Clock。

舊梦的博客 327

CircularReveal 圆形揭示动画完整指南:用 material-motion-compose 实现 Material 风格展开效果

在 Android 与 Compose Multiplatform 开发中,**CircularReveal 圆形揭示动画**是 Material Design 里最具代表性的过渡效果之一:内容从某个中心点如涟漪般向外展开,或反向收缩消失。借助 **material-motion-compose** 这一开源库,开发者只需一行 `circularReveal` 修饰符即可在 Jetpack Com

gitblog_00267的博客 411

倾斜摄影数据转换为3DTile格式的方法:基于CesiumLab GIS

通过使用CesiumLab GIS,倾斜摄影数据可以方便地转换为3DTile格式,并在CesiumJS等3D地理信息可视化工具中进行展示和分析。一旦成功导入3DTile数据,就可以在CesiumLab GIS中利用其强大的可视化和分析功能进行进一步的处理。转换完成后,可以将生成的3DTile数据导入到CesiumLab GIS中进行可视化和分析。启动CesiumLab GIS应用程序,并按照界面上的指导导入转换后的3DTile数据。脚本将开始执行,并将倾斜摄影数据转换为3DTile格式。

ObDjango的博客 1076

Android Compose 图像修饰深度解析(八)

定义了图像的缩放策略,位于包:kotlin/** 保持宽高比,缩放至完全显示 */Fit,/** 保持宽高比,缩放至覆盖区域,可能裁剪 */Fill,/** 保持宽高比,居中缩放显示 */FitCenter,/** 保持宽高比,居中裁剪 *//** 拉伸填充,不保持比例 *//** 不缩放,原始尺寸 */Nonekotlinkotlin布局与测量:通过Layout组件管理图像的尺寸和位置。变换矩阵:利用Matrix实现旋转、缩放等几何变换。剪裁路径:通过Path定义剪裁区域,结合。

Android开发领域创作者 1247

38.XDMA寄存器详解2-H2C、C2H通道寄存器组剖析

目录 1.上节回顾 2. H2C寄存器剖析 2.1 H2C通道标识寄存器(0x00) 2.2 H2C通道控制寄存器(0x04) 2.3 H2C通道状态寄存器(0x40) 2.4 H2C通道完成描述符数量寄存器(0x48) 2.5 H2C通道对齐寄存器(0x4C) 2.6 H2C通道查询模式回写地址寄存器(0x88、0x8C) 2.7 H2C通道中断掩码寄存器(0x90)​ 2.8 H2C通道性能监视控制寄存器(0xC0) 2.9 H2C通道周期计数性能寄存器(0xC4、0xC8) 2

一个早起的程序员 5206

31.华为路由器:PPPOE配置模拟实验及NAT配置

实验环境 pppoe-client上面的接口信息 [AR1]dis ip interface brief *down: administratively down ^down: standby (l): loopback (s): spoofing The number of interface that is UP in Physical is 2 The number of interface that is DOWN in Physical is 1 The number of interface

迷逝 8117

Android Compose Modifier修饰符

在Compose中,Modifier承担了绝大部分的修饰作用,通过它可以为控件设置width、height、size、padding、background等等。

Chenyile161616的博客 266

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Compose 中的 modifier

Modifiers 让你可以修饰或增强 composable。Modifiers 是标准的 Kotlin 对象。在上面的代码中,请注意一起使用的不同的 modifer 函数。最佳实践是让所有 composables 接受一个 modifer 参数,并将该 modifer 传递给 emit UI 的第一个子组件。这样做可以使代码更具可重用性,并使其行为更可预测和直观。

leihu007的专栏 428

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Compose中的自定义布局(四)

文章目录一、前言二、使用布局修饰符三、创建自定义布局四、固有特性测量五、分析修饰符六、参考链接 一、前言 在实际开发中会出于各种原因进行自定义布局,所以这里简单记录下使用Compose进行自定义布局的方式 二、使用布局修饰符 本段参考代码是google的代码 我们可以使用layout修饰符来元素的测量和布局方式,大概方式如下: fun Modifier.customLayoutModifier(...) = Modifier.layout { measurable, constraints ->

Mr_Tony的专栏 1074

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Compose 实践与探索七 —— Modifier 基础

从本篇文章开始我们要讲解 Modifier 修饰符,它是一个很精妙的东西,允许我们通过链式调用的方式为组件应用一系列的样式设置,如边距、字体、位移等。在 Compose 中,每个基础的 Composable 组件都有一个 modifier 参数,通过传入自定义的 Modifier 修改组件的样式。 此外,前面我们还提过 Modifier 调用链对顺序敏感,不同的调用顺序会产生不同的 Modifier 链从而影响最终的 UI 效果,这是 Compose 按照 Modifier 链来顺序完成页面布局与绘制的结

tmacfrank 1407

4-Compose开发-Modifier基础

Modifier(修饰符)是 Compose 中用于装饰或增强可组合项的核心接口。它本质上是一个有序的、链式调用的元素集合,每个元素都定义了某种行为或样式(如设置宽度、添加内边距、处理点击等)。Modifier 的设计遵循“组合优于继承”的理念——你不需要创建复杂的自定义 View,而是通过组合多个小粒度的修饰符来构建所需的 UI 效果。用于在组件的绘制阶段添加自定义效果,比如偏移、旋转、缩放等。修饰符作用偏移组件位置(x 水平,y 垂直)旋转组件(角度)缩放组件(x 水平缩放,y 垂直缩放)

weixin_36848576的博客 561
上一篇: Jetpack - ViewModel
下一篇: Compose 基础 - 基本使用
Jomurphys
博客等级 码龄9年 1768粉丝 261原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值