如何使用Jetpack Compose实现文本环绕图片的排版设计?
实现Jetpack Compose侧边栏+主内容区布局方案
从你提供的设计图来看,核心是固定侧边导航栏+自适应主内容区的结构,下面是具体实现方案:
核心结构拆解
- 左侧:垂直排列的导航选项,选中项带高亮样式
- 右侧:顶部操作栏+可切换的内容区域
完整代码实现
1. 定义导航数据与状态
import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.Home import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.ShoppingCart import androidx.compose.material3.* import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp // 导航项数据类 data class NavItem(val title: String, val icon: androidx.compose.ui.graphics.vector.ImageVector) // 示例导航列表 val navItems = listOf( NavItem("主页", Icons.Default.Home), NavItem("订单", Icons.Default.ShoppingCart), NavItem("收藏", Icons.Default.Favorite), NavItem("设置", Icons.Default.Settings) )
2. 整体布局实现
@OptIn(ExperimentalMaterial3Api::class) @Composable fun SidebarLayout() { var selectedItemIndex by remember { mutableIntStateOf(0) } Scaffold( topBar = { // 右侧顶部操作栏 TopAppBar( title = { Text(navItems[selectedItemIndex].title) } ) } ) { paddingValues -> Row( modifier = Modifier .fillMaxSize() .padding(paddingValues) ) { // 左侧固定宽度侧边栏 Column( modifier = Modifier .width(200.dp) .fillMaxHeight() .background(Color(0xFFF5F5F5)), verticalArrangement = Arrangement.Top ) { navItems.forEachIndexed { index, item -> val isSelected = index == selectedItemIndex Box( modifier = Modifier .fillMaxWidth() .background(if (isSelected) Color(0xFFE0E0E0) else Color.Transparent) .clickable { selectedItemIndex = index } .padding(horizontal = 16.dp, vertical = 12.dp), contentAlignment = Alignment.CenterStart ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = item.icon, contentDescription = item.title, tint = if (isSelected) Color(0xFF2196F3) else Color.Gray ) Spacer(modifier = Modifier.width(8.dp)) Text( text = item.title, color = if (isSelected) Color(0xFF2196F3) else Color.Gray, fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal ) } } } } // 右侧自适应主内容区 Box( modifier = Modifier .fillMaxSize() .padding(16.dp), contentAlignment = Alignment.Center ) { // 根据选中项切换内容 when (selectedItemIndex) { 0 -> Text("主页内容区域") 1 -> Text("订单列表内容") 2 -> Text("收藏的商品内容") 3 -> Text("设置页面内容") } } } } }
3. 进阶优化方案
- 小屏幕适配:结合
WindowSizeClass判断屏幕尺寸,在窄屏时将侧边栏替换为ModalNavigationDrawer实现折叠效果 - 复杂内容管理:如果主内容是多页面结构,可使用
NavHost替代when判断,实现页面路由管理 - 官方组件简化:直接使用Compose官方的
NavigationRail组件快速实现侧边栏:
NavigationRail(modifier = Modifier.fillMaxHeight()) { navItems.forEachIndexed { index, item -> val isSelected = index == selectedItemIndex NavigationRailItem( icon = { Icon(item.icon, contentDescription = item.title) }, label = { Text(item.title) }, selected = isSelected, onClick = { selectedItemIndex = index }, colors = NavigationRailItemDefaults.colors( selectedIconColor = Color(0xFF2196F3), selectedTextColor = Color(0xFF2196F3), unselectedIconColor = Color.Gray, unselectedTextColor = Color.Gray ) ) } }
内容的提问来源于stack exchange,提问作者Vahit Keskin
相关产品推荐
相关产品推荐

