Android compose

在 Jetpack Compose 中,响应式适配主要通过以下几种方式实现。我将通过具体例子来说明:

一、基于屏幕配置的响应式布局

1. 使用 LocalConfiguration 获取屏幕信息

kotlin 复制代码
@Composable
fun ResponsiveLayout() {
    val configuration = LocalConfiguration.current
    val screenWidth = configuration.screenWidthDp.dp
    val screenHeight = configuration.screenHeightDp.dp
    
    Box(modifier = Modifier.fillMaxSize()) {
        if (screenWidth > 600.dp) {
            // 大屏幕布局
            LargeScreenContent()
        } else {
            // 小屏幕布局
            SmallScreenContent()
        }
    }
}

@Composable
fun LargeScreenContent() {
    Row(modifier = Modifier.fillMaxSize()) {
        Sidebar(modifier = Modifier.width(200.dp))
        MainContent(modifier = Modifier.weight(1f))
    }
}

@Composable
fun SmallScreenContent() {
    Column(modifier = Modifier.fillMaxSize()) {
        TopBar()
        MainContent(modifier = Modifier.weight(1f))
        BottomNavigation()
    }
}

2. 监听屏幕方向变化

kotlin 复制代码
@Composable
fun OrientationLayout() {
    val configuration = LocalConfiguration.current
    val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
    
    if (isLandscape) {
        Row {
            Image(modifier = Modifier.weight(1f), painter = painterResource(R.drawable.image))
            Text(modifier = Modifier.weight(1f), text = "横屏内容")
        }
    } else {
        Column {
            Image(painter = painterResource(R.drawable.image))
            Text(text = "竖屏内容")
        }
    }
}

二、Material Design 3 的 WindowSizeClass

1. 基本用法

kotlin 复制代码
@Composable
fun AdaptiveContent() {
    WindowSizeClass { windowSizeClass ->
        when (windowSizeClass.widthSizeClass) {
            WindowWidthSizeClass.Compact -> CompactContent()
            WindowWidthSizeClass.Medium -> MediumContent()
            WindowWidthSizeClass.Expanded -> ExpandedContent()
        }
    }
}

@Composable
fun CompactContent() {
    // 手机竖屏布局
    Column {
        Text(text = "紧凑布局")
        // ...
    }
}

@Composable
fun MediumContent() {
    // 平板或手机横屏布局
    Row {
        Text(text = "中等布局")
        // ...
    }
}

@Composable
fun ExpandedContent() {
    // 大屏设备布局
    Row {
        Sidebar()
        MainArea()
        DetailPanel()
    }
}

2. 高度方向的适配

kotlin 复制代码
@Composable
fun HeightAdaptiveContent() {
    WindowSizeClass { windowSizeClass ->
        val heightClass = windowSizeClass.heightSizeClass
        
        when (heightClass) {
            WindowHeightSizeClass.Compact -> {
                // 矮屏设备(如折叠屏折叠状态)
                LazyColumn { items(3) { ItemCard() } }
            }
            WindowHeightSizeClass.Medium -> {
                // 中等高度
                LazyColumn { items(5) { ItemCard() } }
            }
            WindowHeightSizeClass.Expanded -> {
                // 高屏设备
                LazyColumn { items(8) { ItemCard() } }
            }
        }
    }
}

三、基于密度的动态缩放

1. 使用 LocalDensity 动态调整尺寸

kotlin 复制代码
@Composable
fun DensityAwareLayout() {
    val density = LocalDensity.current
    val context = LocalContext.current
    
    // 根据屏幕密度动态计算
    val baseSize = with(density) { 100.dp.toPx() }
    val adjustedSize = baseSize * getScaleFactor(context)
    
    Box(
        modifier = Modifier
            .width(with(density) { adjustedSize.toDp() })
            .height(50.dp)
    ) {
        Text(text = "自适应尺寸")
    }
}

fun getScaleFactor(context: Context): Float {
    val metrics = context.resources.displayMetrics
    return metrics.density / 2.0f // 相对于 xxhdpi 的缩放
}

2. 自定义密度感知组件

kotlin 复制代码
@Composable
fun AdaptiveText(text: String) {
    val configuration = LocalConfiguration.current
    val screenWidth = configuration.screenWidthDp
    
    // 根据屏幕宽度动态调整字体大小
    val textSize = when {
        screenWidth < 360 -> 14.sp
        screenWidth < 600 -> 16.sp
        else -> 18.sp
    }
    
    Text(
        text = text,
        fontSize = textSize,
        modifier = Modifier.padding(16.dp)
    )
}

四、ConstraintLayout 组合

1. 百分比约束

kotlin 复制代码
@Composable
fun PercentLayout() {
    ConstraintLayout(modifier = Modifier.fillMaxSize()) {
        val (box1, box2, box3) = createRefs()
        
        Box(
            modifier = Modifier
                .constrainAs(box1) {
                    start.linkTo(parent.start)
                    end.linkTo(parent.end)
                    top.linkTo(parent.top)
                    width = Dimension.percent(1f)
                    height = Dimension.percent(0.3f)
                }
                .background(Color.Blue)
        )
        
        Box(
            modifier = Modifier
                .constrainAs(box2) {
                    start.linkTo(parent.start)
                    top.linkTo(box1.bottom)
                    width = Dimension.percent(0.5f)
                    height = Dimension.percent(0.4f)
                }
                .background(Color.Red)
        )
        
        Box(
            modifier = Modifier
                .constrainAs(box3) {
                    start.linkTo(box2.end)
                    top.linkTo(box1.bottom)
                    end.linkTo(parent.end)
                    height = Dimension.percent(0.4f)
                }
                .background(Color.Green)
        )
    }
}

五、折叠屏适配

1. 检测折叠状态

kotlin 复制代码
@Composable
fun FoldableLayout() {
    val windowInfo = rememberWindowInfo()
    val isFolded = windowInfo.windowLayoutInfo.foldingFeatures.isNotEmpty()
    
    if (isFolded) {
        // 折叠状态布局
        FoldedLayout()
    } else {
        // 展开状态布局
        ExpandedLayout()
    }
}

@Composable
fun FoldedLayout() {
    Column(modifier = Modifier.fillMaxSize()) {
        ContentAboveFold()
        // 注意折叠区域可能不可用
        Spacer(modifier = Modifier.height(100.dp))
        ContentBelowFold()
    }
}

@Composable
fun ExpandedLayout() {
    Row(modifier = Modifier.fillMaxSize()) {
        LeftPanel(modifier = Modifier.weight(1f))
        RightPanel(modifier = Modifier.weight(1f))
    }
}

2. 响应式导航

kotlin 复制代码
@Composable
fun ResponsiveNavigation() {
    WindowSizeClass { windowSizeClass ->
        val isLargeScreen = windowSizeClass.widthSizeClass >= WindowWidthSizeClass.Medium
        
        if (isLargeScreen) {
            // 大屏使用侧边栏导航
            NavigationRail {
                NavigationRailItem(icon = { Icon(Icons.Default.Home) }, label = { Text("首页") })
                NavigationRailItem(icon = { Icon(Icons.Default.Search) }, label = { Text("搜索") })
            }
        } else {
            // 小屏使用底部导航
            NavigationBar {
                NavigationBarItem(icon = { Icon(Icons.Default.Home) }, label = { Text("首页") })
                NavigationBarItem(icon = { Icon(Icons.Default.Search) }, label = { Text("搜索") })
            }
        }
    }
}

六、实用工具函数

1. 屏幕尺寸判断

kotlin 复制代码
@Composable
fun isTablet(): Boolean {
    val configuration = LocalConfiguration.current
    return configuration.screenWidthDp >= 600
}

@Composable
fun isLargeScreen(): Boolean {
    val configuration = LocalConfiguration.current
    return configuration.screenWidthDp >= 900
}

2. 自适应 Padding

kotlin 复制代码
@Composable
fun adaptivePadding(): PaddingValues {
    val configuration = LocalConfiguration.current
    return when {
        configuration.screenWidthDp < 360 -> PaddingValues(8.dp)
        configuration.screenWidthDp < 600 -> PaddingValues(16.dp)
        else -> PaddingValues(24.dp)
    }
}

@Composable
fun MyContent() {
    Column(modifier = Modifier.padding(adaptivePadding())) {
        Text(text = "自适应内边距")
    }
}

总结

Compose 的响应式适配核心在于:

  1. 屏幕配置感知 :通过 LocalConfiguration 获取屏幕尺寸、方向等信息
  2. 窗口大小分类 :使用 WindowSizeClass 进行设备分类
  3. 动态布局切换:根据不同条件渲染不同的布局组件
  4. 密度自适应 :通过 LocalDensity 实现像素级的动态调整

这种方式相比传统 View 体系更加灵活,能够更好地应对多样化的设备形态。

相关推荐
开开心心就好9 小时前
批量提取PDF中的图片,直接导出原图
前端·javascript·支持向量机·智能手机·pdf·html·启发式算法
Setsuna_F_Seiei11 小时前
前端转型 Agent 开发 05 之 Agent Hooks 与 Checkpointer(让 Agent 从全自动转变人为可掌控)
前端·agent·ai编程
百万蹄蹄向前冲13 小时前
风扇转了一晚上MVP专家团翻车事故
前端·人工智能
默_笙13 小时前
🏛 给 AI 配一间办公室:Harness Engineering 六大模块与它的实现
前端·javascript
linux_cfan14 小时前
videojs v10 源代码系列解读:14 · 谓词守卫:在运行时安全地调用能力
前端·javascript·音视频
kyriewen15 小时前
我扒了 10,221 条 JD:腾讯技术岗 75% 在要 AI
前端·人工智能·ai编程
郑州光合科技余经理15 小时前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
IT_陈寒16 小时前
Vue的响应式让我熬到凌晨三点,原来漏了这个小细节
前端·人工智能·后端
Blanche150016 小时前
利用 RAG 为答疑机器人扩展知识范围
前端
天若有情67316 小时前
【纯前端小工具】公历生日转农历,批量查询每年农历生日对应的公历日期(GitHub Pages在线直接用)
前端·javascript·github pages·农历转换·lunisolar·网页小工具