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()
        }
    }
}
相关推荐
hunterandroid14 小时前
Android WebView JSBridge 治理实战:从线上白屏崩溃到协议化通信
android·前端
一个用户名i14 小时前
【Compose 系列】第 1 篇:认识 Compose,为什么要学它
android·android jetpack
极客猴子15 小时前
iPhone实时转写软件推荐:会议录音功能真实体验
android·人工智能·飞书
达令哥15 小时前
告别 ARouter!基于 Google 官方 Navigation 3 + KSP 打造 Compose 时代的双轨制路由框架
android·前端
YF021116 小时前
Android App启动与权限管控
android
嘟哩DuliDuli16 小时前
AI 短剧生成为什么要有角色库、场景库和镜头卡
android·人工智能·安全·ai·软件工程
NINO18 小时前
深度解析 Android ANR:从标准分析流程到 NativePollOnce 疑难破局
android
阿巴斯甜18 小时前
AppFunctions 完整介绍
android
蜡台18 小时前
Jetpack Compose 从入门到精通
android·前端·kotlin·compose·jepack
toooooop818 小时前
踩坑:PHP7.2导出Excel正常,升级7.3文件损坏需修复
android·excel