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()
        }
    }
}
相关推荐
半摆烂日常8 小时前
低代码平台API对接实践:接口鉴权与数据同步的完整实现
android·低代码·rxjava
事圆则缓8 小时前
volatile 使用场景全解析:它能保证什么,又解决不了什么
android
蒲公英内测分发9 小时前
智能投影仪参加海外展会,未上架的 Android 配套 App 怎么让客户限时试用?
android
ii_best9 小时前
按键精灵手机端开发安卓版实战:手写一个可最小化、可拖动的「运行日志悬浮窗」(附完整 源码 + 踩坑记录)
android·ios·智能手机·自动化·ai编程·按键精灵
终端安全笔记9 小时前
安卓做 MDM 管控,先分清三种注册入口
android·安全·智能手机
乌萨达10 小时前
手机模拟器安卓怎么用?电脑安装应用、玩手游与账号同步指南
android·智能手机·电脑·雷电模拟器
美狐美颜SDK开放平台11 小时前
Android与iOS直播APP美颜有什么区别?视频美颜SDK开发详解
android·ios·音视频·视频美颜sdk
春猿火13 小时前
某市-2026【网安·论道】misc-afterimage_note-wp
android
恋猫de小郭14 小时前
Shopify 回应为什么从 RN 回到原生,为什么不用 KMP ?
android·前端·flutter
fundroid15 小时前
Android AI 开发,真正拉开差距的是工程闭环
android·ai·大模型·agent