1. 响应式布局基础
- 使用
Box
、Column
、Row
等布局容器:
Box
:用于重叠元素,可用于放置背景和前景元素等。例如,在一个屏幕上同时显示图片和其上的文字说明。
Column
:垂直排列子元素,适合将元素按从上到下的顺序布局,比如一个包含标题、副标题和正文的界面。
Row
:水平排列子元素,常用于将相关的小部件(如按钮组)放在同一行。
- 使用
Modifier
调整布局:
fillMaxWidth()
、fillMaxHeight()
:使元素填充可用的最大宽度或高度。例如,在一个列表项中,使图片填充整个列表项的宽度。
width(IntrinsicSize.Min)
、height(IntrinsicSize.Min)
:让元素根据其子元素的最小尺寸来确定自身尺寸。
2. 针对不同屏幕尺寸的布局策略
implementation "androidx.compose.material3:material3-window-size-class:1.1.0"
- 然后在
Activity
或Composable
函数中获取WindowSizeClass
:
import androidx.compose.material3.WindowSizeClass
import androidx.compose.material3.calculateWindowSizeClass
@Composable
fun MyApp() {
val windowSizeClass = calculateWindowSizeClass(LocalDensity.current)
// 根据windowSizeClass进行不同布局
when (windowSizeClass.widthSizeClass) {
WindowSizeClass.WindowWidthSizeClass.Compact -> {
// 手机竖屏等窄屏幕布局
}
WindowSizeClass.WindowWidthSizeClass.Medium -> {
// 平板竖屏等中等屏幕布局
}
WindowSizeClass.WindowWidthSizeClass.Expanded -> {
// 平板横屏或桌面等宽屏幕布局
}
}
}
- 使用
Density
和Configuration
:
Density
:可用于根据屏幕密度调整布局。例如,在高密度屏幕上适当增加元素的大小以保持视觉一致性。
@Composable
fun DensityAwareLayout() {
val density = LocalDensity.current
val size = with(density) { 16.dp.toPx() }
// 使用size来设置元素大小
}
Configuration
:可以监听设备配置变化(如屏幕方向变化)。
@Composable
fun ConfigurationAwareLayout() {
val configuration = LocalConfiguration.current
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
// 根据屏幕方向进行布局调整
}
3. 列表布局在不同设备上的处理
- 手机竖屏:
- 通常采用单列垂直滚动列表。使用
LazyColumn
来实现高效的列表渲染。
@Composable
fun PhonePortraitList() {
LazyColumn {
items(100) { item ->
Text("Item $item")
}
}
}
- 列表项高度可适当增大,以方便触摸操作,例如使用
Modifier.height(64.dp)
。
- 手机横屏:
- 可以保持单列垂直滚动列表,但如果有足够空间,可以考虑在列表项中显示更多信息。例如,原本在竖屏时显示标题和简短描述,横屏时可以增加图片等内容。
@Composable
fun PhoneLandscapeList() {
LazyColumn {
items(100) { item ->
Row {
Image(
painter = painterResource(R.drawable.sample_image),
contentDescription = null,
modifier = Modifier.size(64.dp)
)
Column {
Text("Item $item Title")
Text("Item $item Description")
}
}
}
}
}
- 平板:
- 竖屏:可以采用双列布局,左边显示列表项标题,右边显示详细内容。使用
Row
和LazyColumn
组合实现。
@Composable
fun TabletPortraitList() {
Row {
LazyColumn(
modifier = Modifier.weight(1f)
) {
items(100) { item ->
Text("Item $item Title")
}
}
Column(
modifier = Modifier.weight(2f)
) {
// 显示详细内容,根据选中的列表项动态更新
}
}
}
- 横屏:可以进一步扩展为多列布局,或者采用瀑布流布局(使用
LazyVerticalGrid
)。例如,展示图片列表时,可根据屏幕宽度自适应列数。
@Composable
fun TabletLandscapeList() {
val windowSizeClass = calculateWindowSizeClass(LocalDensity.current)
val numColumns = when (windowSizeClass.widthSizeClass) {
WindowSizeClass.WindowWidthSizeClass.Medium -> 3
WindowSizeClass.WindowWidthSizeClass.Expanded -> 5
else -> 2
}
LazyVerticalGrid(
columns = GridCells.Fixed(numColumns),
contentPadding = PaddingValues(8.dp)
) {
items(100) { item ->
Image(
painter = painterResource(R.drawable.sample_image),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
)
}
}
}