1.概述
主页的页面比前面的欢迎页和登录页面要杂乱得多,假设运用传统的view,即运用xml布局的方法,咱们可能需要书写很多的代码,可是运用Compose UI,这一切都会变得很简略,有了前面的页面开发经历,咱们拿到这个主页的页面时首要想到的第一步便是拆分页面。然后将拆分后的页面运用Compose UI中对应的组件来完成。
2.页面展现
2.1 亮色主题
2.2 深色主题
3.页面拆分及完成
咱们的主页能够拆分为四个部分,分别是顶部的查找栏,然后是中间的banner和信息展现列表InfoList,以及底部的导航栏,拆分如下图所示:
咱们先写一个数据类和填充一些数据来辅佐编写Home页面,代码如下:
data class ImageItem(val name:String,val resID:Int)
val bloomBannerList = listOf<ImageItem>(
ImageItem("Desert chic", R.drawable.desert_chic),
ImageItem("Tiny terrariums",R.drawable.tiny_terrariums),
ImageItem("Jungle Vibes",R.drawable.jungle_vibes)
)
val bloomInfoList = listOf<ImageItem>(
ImageItem("Monstera",R.drawable.monstera),
ImageItem("Aglaonema",R.drawable.aglaonema),
ImageItem("Peace lily",R.drawable.peace_lily),
ImageItem("Fiddle leaf tree",R.drawable.fiddle_leaf),
ImageItem("Desert chic",R.drawable.desert_chic),
ImageItem("Tiny terrariums",R.drawable.tiny_terrariums),
ImageItem("Jungle Vibes",R.drawable.jungle_vibes)
)
val navList = listOf<ImageItem>(
ImageItem("Home",R.drawable.ic_home),
ImageItem("Favorites",R.drawable.ic_favorite),
ImageItem("Profile",R.drawable.ic_account_circle),
ImageItem("Cart",R.drawable.ic_shopping_cart),)
上面代码中的资源能够导文末给的源码地址中去相应目录下拿
3.1 主页的UI全体UI架构完成
主页的全体UI架构布局咱们能够运用前面学过的Scaffold组件,快速建立,如下所示:
@Composable
fun HomePage() {
Scaffold(bottomBar = { BottomBar() //底部导航栏 }) {
Column(
Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background)
.padding(horizontal = 16.dp)
) {
SearchBar() // 查找栏
BloomRowBanner() // banner 列表
BloomInfoList() // 中间信息展现列表
}
}
}
3.2 底部导航栏BottomBar的完成
底部导航栏的完成非常简略,咱们直接运用Compose提供的BottomNavigation
组件完成就能够了,代码如下所示:
@Composable
fun BottomBar() {
BottomNavigation(
elevation = 16.dp,
modifier = Modifier
.fillMaxWidth()
.height(56.dp),
backgroundColor = MaterialTheme.colors.secondary
) {
navList.forEach {
BottomNavigationItem(
onClick = { /*TODO*/ },
icon = {
Icon(
painterResource(id = it.resID),
contentDescription = null,
modifier = Modifier.size(24.dp)
)
},
label = {
Text(
text = it.name,
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onPrimary
)
}, selected = ("Home" == it.name)
)
}
}
}
3.3 查找栏SearchBar的完成
对于查找栏,能够运用TextField完成,TextField是一个Material组件,会带着默认的背景色和底部边框色彩,所以咱们还需对TextField进行额外的色彩装备。代码如下所示:
@Composable
fun SearchBar() {
Box {
TextField(
value = "",
onValueChange = {},
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.clip(RoundedCornerShape(4.dp)),
leadingIcon = {
Icon(
painter = rememberVectorPainter(
image = ImageVector.vectorResource(R.drawable.ic_search),
),
contentDescription = "search",
modifier = Modifier.size(18.dp),
tint = Color.Gray
)
},
placeholder = {
Text(
text = "Search",
style = MaterialTheme.typography.body1,
color = Color.Gray
)
},
colors = TextFieldDefaults.outlinedTextFieldColors(
backgroundColor = Color.White,
unfocusedBorderColor = Color.White,// 未选中时的下边框色彩
focusedBorderColor = Color.White // 选中时下边框色彩
)
)
}
}
3.4 Banner完成
要完成Banner的展现,咱们需要由一个Text组件和LazyRow组件组合而成。banner内容的展现咱们能够编写一个子元素模板组件PlantCard组件来辅佐完成Home主页,代码如下所示:
@Composable
fun PlantCard(plant: ImageItem) {
Card(
modifier = Modifier
.size(136.dp)
.clip(RoundedCornerShape(4.dp))
) {
Column {
Image(
painterResource(
id = plant.resID
),
contentScale = ContentScale.Crop,
contentDescription = "image",
modifier = Modifier
.fillMaxWidth()
.height(96.dp)
)
Box(
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp)
) {
Text(
text = plant.name,
style = MaterialTheme.typography.h2,
color = MaterialTheme.colors.primary,
modifier = Modifier
.fillMaxWidth()
.paddingFromBaseline(top = 24.dp, bottom = 16.dp)
)
}
}
}
}
然后在咱们编写Banner 列表展现的时分就能够运用PlantCard了,如下:
@Composable
fun BloomRowBanner() {
Column {
Box(modifier = Modifier.fillMaxWidth()) {
Text(
text = "Browse themes",
style = MaterialTheme.typography.h1,
color = MaterialTheme.colors.primary,
modifier = Modifier
.fillMaxWidth()
.paddingFromBaseline(top = 32.dp)
)
}
Spacer(modifier = Modifier.height(16.dp))
LazyRow(modifier = Modifier.height(136.dp)) {
items(bloomBannerList.size) {
if (it != 0) {
// 每个子元素之间水平距离为8.dp
Spacer(modifier = Modifier.width(8.dp))
}
PlantCard(plant = bloomBannerList[it])
}
}
}
}
3.5 中间信息列表BloomInfoList的完成
这个组件和前面的Banner列表展现差不多,只是这个组件的右侧有一个小图标,所以咱们能够运用Text组件和Icon组件组合成Row组件,再让Row组件与LazyColumn组件组合成BloomInfoList组件。 与前面一样,咱们先编写一个子元素组件模板DesignCard,代码如下所示:
@Composable
fun DesignCard(plant: ImageItem) {
Row(modifier = Modifier.fillMaxWidth()) {
Image(
painterResource(id = plant.resID),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.size(64.dp)
.clip(RoundedCornerShape(4.dp))
)
Spacer(modifier = Modifier.width(16.dp))
Column {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
)
{
Column {
Text(
text = plant.name,
style = MaterialTheme.typography.h2,
color = MaterialTheme.colors.primary,
modifier = Modifier.paddingFromBaseline(top = 24.dp)
)
Text(
text = "这是描绘。。。。。。。",
style = MaterialTheme.typography.body1,
color = MaterialTheme.colors.primary,
)
}
Checkbox(
checked = false, onCheckedChange = {},
modifier = Modifier
.padding(top = 24.dp)
.size(24.dp),
colors = CheckboxDefaults.colors(checkmarkColor = Color.White)
)
}
// 每个子元素下面画一根线
Divider(
color = Color.Gray,
modifier = Modifier.padding(top = 16.dp),
thickness = 0.5.dp
)
}
}
}
然后利用DesignCard完成咱们要展现的BloomInfoList组件,代码如下:
@Composable
fun BloomInfoList() {
Column {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = "Design your home garden",
style = MaterialTheme.typography.h1,
color = MaterialTheme.colors.primary,
modifier = Modifier.paddingFromBaseline(top = 40.dp)
)
Icon(
painterResource(id = R.drawable.ic_filter_list),
contentDescription = "filter",
modifier = Modifier
.padding(top = 24.dp)
.size(24.dp)
)
}
Spacer(modifier = Modifier.height(16.dp))
LazyColumn(
modifier = Modifier.fillMaxWidth(),
contentPadding = PaddingValues(bottom = 56.dp)
) {
items(bloomInfoList.size) {
if (it != 0) {
Spacer(modifier = Modifier.height(8.dp))
}
DesignCard(plant = bloomInfoList[it])
}
}
}
}
至此,Goole Bloom的主页就开发完成了。
4.源码地址
到此为止,Compose UI 实战练手项目就结束了,感兴趣的读者一定要自己着手敲一遍,我也是跟着书上敲的代码,发现了很多书上的代码在真实的环境中不能运行,有的是展现过错。然后改正这些过错后收成颇丰,所以主张读者也去手动敲一遍,这样的化感受和记忆都会更深。另外本系列的页面色彩是自己乱配的。读者能够自行去修改 GooleBloom源码地址