Compose 适配 - 通过 UiMediaScope 获取设备信息

官方页面

一、概念

设备信息是动态更新的,需要对其进行监控,并在发生任何更新时触发重组。mediaQuery() 和 derivedMediaQuery() 函数抽象了信息检索的细节,让你可以专注于定义触发布局更新的条件。UiMediaScope 代表了当前的设备能力和上下文环境,当发生变化时此对象会动态更新,查询函数会使用更新后的 UiMediaScope 对象对 Lambda 进行求值。

|---------------------|---------------------------------------------------------------------------------------------------------------|
| mediaQuery() | @Composable fun mediaQuery( query: UiMediaScope.() -> Boolean ): Boolean = LocalUiMediaScope.current.query() |
| derivedMediaQuery() | @Composable fun derivedMediaQuery( query: UiMediaScope.() -> Boolean ): State<Boolean> |

|----------------------------------|---------------------------------------------------|---------------------------------------|
| UiMediaScope 参数 | 类型及说明 ||
| windowWidth windowHeight 当前窗口的宽高 | Dp ||
| windowPosture 当前设备姿态 | UiMediaScope.Posture | .Flat |
| windowPosture 当前设备姿态 | UiMediaScope.Posture | .Tabletop |
| windowPosture 当前设备姿态 | UiMediaScope.Posture | .Book |
| pointerPrecision 当前指针输入的最高精度 | UiMediaScope.PointerPrecision 同时存在多个输入设备会返回精度最高的。 | .Fine 精细:鼠标、触控板、手写笔。 |
| pointerPrecision 当前指针输入的最高精度 | UiMediaScope.PointerPrecision 同时存在多个输入设备会返回精度最高的。 | .Coarse 粗略:触摸屏(手指)。 |
| pointerPrecision 当前指针输入的最高精度 | UiMediaScope.PointerPrecision 同时存在多个输入设备会返回精度最高的。 | .Blunt 迟钝:摇杆。 |
| pointerPrecision 当前指针输入的最高精度 | UiMediaScope.PointerPrecision 同时存在多个输入设备会返回精度最高的。 | .None 无:没有输入方式。 |
| keyboardKind 可用的键盘类型 | UiMediaScope.KeyboardKind | .Physical 物理硬件。 |
| keyboardKind 可用的键盘类型 | UiMediaScope.KeyboardKind | .Virtual 虚拟键盘。 |
| keyboardKind 可用的键盘类型 | UiMediaScope.KeyboardKind | .None 无:未连接硬件也没有显示虚拟键盘。 |
| hasCamera 是否支持摄像头 | Boolean ||
| hasMicrophone 是否支持麦克风 | Boolean ||
| viewingDistance 用户与屏幕之间的典型距离 | UiMediaScope.ViewingDistance | .Near 近距离:大多数个人设备的默认设置,手机、平板、笔记本、显示器。 |
| viewingDistance 用户与屏幕之间的典型距离 | UiMediaScope.ViewingDistance | .Medium 稍远:车载设备、底座模式的平板。 |
| viewingDistance 用户与屏幕之间的典型距离 | UiMediaScope.ViewingDistance | .Far 相当远:电视。 |

二、使用

2.1 窗口大小

Kotlin 复制代码
when {
    mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout()
    mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout()
    mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout()
}

2.2 设备形态

Kotlin 复制代码
val isExpanded by derivedMediaQuery {
    windowWidth >= WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND.dp
}
val isMedium by derivedMediaQuery {
    windowWidth >= WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND.dp
}
when {
    isExpanded -> ThreePaneLayout()
    isMedium -> TwoPaneLayout()
    else -> SinglePaneLayout()
}

2.3 输入精度

Kotlin 复制代码
val buttonSize = if (mediaQuery { pointerPrecision == UiMediaScope.PointerPrecision.Fine }) {
    10.dp
} else {
    20.dp
}

2.4 检测键盘

Kotlin 复制代码
if (mediaQuery { keyboardKind == UiMediaScope.KeyboardKind.None }) {
    // 提示连接键盘
}

2.5 检测麦克风/摄像头

Kotlin 复制代码
if (mediaQuery { hasMicrophone }) {
    MicButton()
}

if (mediaQuery { hasCamera }) {
    CameraButton()
}

2.5 检测距离

Kotlin 复制代码
val fontSize = when {
    mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Far } -> 20.sp
    mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Medium } -> 18.sp
    else -> 16.sp
}

三、预览

Kotlin 复制代码
@Composable
fun TablettopPreview() {
    // 1.启用 mediaQuery 函数。
    ComposeUiFlags.isMediaQueryIntegrationEnabled = true
    val currentUiMediaScope = LocalUiMediaScope.current
    // 2.定义一个实现 UiMediaScope 接口的自定义对象。
    // 该对象覆盖了 windowPosture 参数,其余参数的解析将委托给 currentUiMediaScope 对象。
    val uiMediaScope = remember(currentUiMediaScope) {
        object : UiMediaScope by currentUiMediaScope {
            override val windowPosture: UiMediaScope.Posture = UiMediaScope.Posture.Tabletop
        }
    }
    // 3. 将该对象设置为 LocalUiMediaScope。
    CompositionLocalProvider(LocalUiMediaScope provides uiMediaScope) {
        // 4.调用组件进行预览
        when {
            mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout()
            mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout()
            mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout()
        }
    }
}
相关推荐
贾艺驰1 小时前
实战Android Framework: 新增一个系统权限
android
alexhilton6 小时前
使用Android Archive进行打包
android·kotlin·android jetpack
badhope8 小时前
做了几年安卓开发,这些坑我帮你踩过了
android·android studio
逐光老顽童2 天前
Java 与 Kotlin 混合开发避坑指南:30 个真实案例实录
android·kotlin
爱勇宝3 天前
鸿蒙生态的下半场:开发者不只要能开发,还要能赚钱
android·前端·程序员
Yeyu3 天前
刷新一帧的艺术:invalidate / postInvalidate / postInvalidateOnAnimation全解析
android
潘潘潘3 天前
Android OTA 升级原理和流程介绍
android
plainGeekDev3 天前
null 判断 → Kotlin 可空类型
android·java·kotlin
plainGeekDev3 天前
getter/setter → Kotlin 属性
android·java·kotlin
YXL1111YXL3 天前
Handler 消息回收与协程异步执行的时序陷阱
android