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()
        }
    }
}
相关推荐
AFinalStone5 小时前
Android 7系统网络(四)Native层(下)—netd Controller详解
android·网络
爱笑鱼5 小时前
Handler(一):post 之后,Runnable 到底在哪个线程执行?
android
木木子226 小时前
[特殊字符] 音乐播放器——状态驱动的多媒体控制
android·开发语言·华为·php·harmonyos
雨白7 小时前
C 语言基础:结构体、联合体与枚举
android
阿巴斯甜8 小时前
Android 代码混淆
android
apihz10 小时前
台风实时与历史详情查询免费 API 接口完整教程
android·开发语言·tcp/ip·dubbo·台风·天气预报
浪客川11 小时前
AOSP源码隐藏状态栏
android·aosp
没有了遇见11 小时前
AI Agent 是什么?—— 一文理解 LLM、Memory、Skills、Tools、MCP、Workflow,Context
android·前端·程序员
知行合一。。。11 小时前
LangChain--07--智能体、Agent的基本用法
android·数据库·langchain
御坂嘀喵12 小时前
Speed Tools:一套低侵入的 Android 插件化 + 动态换肤 + 字体切换框架
android·gitee