You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Glance App Widget动态缩放异常:API32无法渲染单月组件

Glance组件API32无法渲染单月视图问题解决

问题背景

开发了一款支持根据可用尺寸渲染单月/双月视图的Glance App Widget,API 33下缩放正常,但API 32中无法渲染单月视图。

API 32异常表现

异常演示动图

API 33正常表现

正常演示动图

核心代码

class ConsolidatorAppWidget: GlanceAppWidget() {

    private val isDebugOverride = false     // 设置为true可仅保留一种组件尺寸,减少日志冗余
    
    /**
     * 用户调整组件尺寸时,用于动态配置组件
     */
    override val sizeMode: SizeMode = SizeMode.Responsive(
        if (isDebugOverride && isDebug()) setOf(ONE_MONTH_WIDGET) else setOf(ONE_MONTH_WIDGET, TWO_MONTH_WIDGET)
    )

    /**
     * Glance提供的DataStore实现,用于应用与组件间的通信
     */
    override val stateDefinition: GlanceStateDefinition<*>
        get() = PreferencesGlanceStateDefinition

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        provideContent {
            val prefs = currentState<Preferences>()
            val firstMonthState = prefs.getFirstMonth()
            prefs.toMutablePreferences().setFirstMonth(firstMonthState)

            val calendarEventsMap = prefs.getCalendarData().createMonthToDayEventsMap()
            val size = LocalSize.current
            calendarWidgetLog(
                "Content: size: $size, calendarEventsMap with last entry ${ 
                    calendarEventsMap.entries.lastOrNull()?.value?.get(
                        0
                    )?.startDateTime
                }"
            )

            when (size) {
                ONE_MONTH_WIDGET -> CalendarAppWidgetUI(firstMonthState, 1, calendarEventsMap)
                TWO_MONTH_WIDGET -> CalendarAppWidgetUI(firstMonthState, 2, calendarEventsMap)
            }
        }
    }

    companion object {
        private val ONE_MONTH_WIDGET = DpSize(200.dp, 200.dp)
        private val TWO_MONTH_WIDGET = DpSize(200.dp, 425.dp)
    }
}

问题原因

API 32及更低版本中,Glance的SizeMode.Responsive对固定DpSize断点的匹配逻辑与API 33不一致,无法正确识别单月视图的尺寸触发条件,导致切换到小尺寸时无法渲染对应UI。

解决方案

1. 改用精确尺寸模式+范围判断

放弃SizeMode.Responsive的固定断点,改用SizeMode.Exact,通过尺寸范围直接判断视图类型:

override val sizeMode: SizeMode = SizeMode.Exact

// 在provideContent中修改判断逻辑
override suspend fun provideGlance(context: Context, id: GlanceId) {
    provideContent {
        // ... 原有逻辑保持不变
        val size = LocalSize.current
        val targetUI = if (size.height < 300.dp) { // 根据实际布局调整阈值
            CalendarAppWidgetUI(firstMonthState, 1, calendarEventsMap)
        } else {
            CalendarAppWidgetUI(firstMonthState, 2, calendarEventsMap)
        }
        targetUI
    }
}

2. 兼容API 32的尺寸回调

API 32中LocalSize.current的更新可能滞后,可主动监听组件尺寸变化广播,触发组件刷新:
在组件的update方法或广播接收器中,当检测到尺寸变化时调用update(context, id)强制刷新Glance组件。

3. 检查布局适配

确认单月视图的布局在API 32中没有硬编码高度或超出组件容器的情况,确保布局能自适应小尺寸容器。

验证

修改后在API 32设备/模拟器上测试组件缩放操作,确认单月视图能正常触发渲染,同时保留API 33的原有功能。

内容的提问来源于stack exchange,提问作者andude

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 20:52:52