Compose的基本布局
本篇博客参考博客
先看一下实现的效果
主要是由3个部分构成的,一个是上面那个搜索框(搜索框是死的,就是一个纯UI,只能看,文字都没办法输入);第二个是中间的,中间的又可以分为2部分,上面的那块是用LazyRow可以左右滑动,下面的是用LazyHorizontalGrid实现了两列的左右滑动(使用LazyHorizontalGrid的时候务必注意:你的kotlin版本必须特别高,否则用不了这个);最后是下面的底部导航栏(这个也是写死的东西,点击后不会有任何反应)。
顶部搜索框的实现
我们会用一个TextField,该组件的功能是
在Jetpack Compose中,TextField是用于输入和编辑文本的组件。可以将其理解为一个可编辑的文本框。当用户在TextField中输入时,输入的内容可以通过onValueChange回调函数捕获并进行处理。
最开始的时候只用TextField基本上什么也看不见,出现不了我最开始那张截图的效果,因为TextField的颜色和那个Search字没写并且没有那个搜索的Icon,我们只能自己加上去
value = "",
onValueChange = {},
leadingIcon = { Icon(imageVector = Icons.Default.Search, contentDescription = null) },
colors = TextFieldDefaults.textFieldColors(backgroundColor = MaterialTheme.colors.background),
placeholder = {
Text("Search")
},
modifier = modifier
.fillMaxWidth()
.heightIn(min = 56.dp)
从这段代码中可以看出Icon是leadingIcon这里面控制的,搜索框的颜色是由colors控制的,
placeholder = {
Text("Search")
},
是用来写那个Search的
而那里面的
onValueChange = {},
是用来进行回调并处理的
具体什么意思呢?
最开始**value = “”**意思就是最开始那个搜索框的显示的就是空,如果你把它该值设置为
value ="nihao" ,
那么效果就是这样的
搜索框就会出现一个nihao
虽然搜索框上面写的是nihao但是因为前面
onValueChange = {},
所以我想读取搜索框输入了什么的时候,读取出来的一直都是"",然后会把onValueChange的值传回给value,然后value = “”,所以显示的就是空
搜索框的ui就基本结束了,但是我不想只要ui,我还想做到我输入什么东西,搜索框就能展示什么东西
搜索框显示text
TextField(
var searchText by remember { mutableStateOf("") }
value =searchText ,
onValueChange = {searchText = it},
leadingIcon = { Icon(imageVector = Icons.Default.Search, contentDescription = null) },
colors = TextFieldDefaults.textFieldColors(backgroundColor = MaterialTheme.colors.background),
placeholder = {
Text("Search")
},
modifier = modifier
.fillMaxWidth()
.heightIn(min = 56.dp)
)
这段代码定义了一个可变状态变量searchText
,它的初始值为空字符串""。这个可变状态变量是通过mutableStateOf
函数来创建的。
mutableStateOf
函数是Compose中的一个状态管理函数,用于创建可变的状态变量,并返回一个包含该变量的MutableState
对象。在这个例子中,我们使用了remember
修饰符,将这个可变状态变量保存在Composable函数的记忆中。这意味着,当Composable函数重新执行时,该变量的值会被保留下来,而不会被重置为初始值。
onValueChange = {searchText = it},
这段代码没太理解,但是chatgpt上说it表示当前文本字段中的新值
然后就没了
如果,我想让搜索框原先什么都没有,然后随便输入什么出来的结果都是12,怎么解决
var searchText by remember { mutableStateOf("") }
value =searchText ,
onValueChange = {searchText = "12"},
和上面的代码差不多,但是我的onValueChange里面的代码改一下就行了
没办法放视频,到时候自己写一下就知道了
中间滑动的实现
上下两个其实差不多,甚至有一个函数我定义的都是一样的。就是下面比上面多了LazyHorizontalGrid,但当时弄这个把我弄的难受的呀。
LazyRow()
先说上面的:我主要用了
data class AlignYourBodyData(
val drawable: Int,
val text: String
)
这个是用来到时候保存图片和文字的
val alignYourBodyData = listOf(
AlignYourBodyData(R.mipmap.saber, "Saber"),
AlignYourBodyData(R.mipmap.archer, "Archer"),
AlignYourBodyData(R.mipmap.lancer, "Lancer"),
AlignYourBodyData(R.mipmap.caster, "Caster"),
AlignYourBodyData(R.mipmap.rider, "Rider"),
AlignYourBodyData(R.mipmap.assassin, "Assassin"),
AlignYourBodyData(R.mipmap.berserker, "Berserker")
)
这就相当于一个数组或者一个集合保存了每张图片和文字
最后在LazyRow里面
items(alignYourBodyData) { item ->
AlignYourBodyElement(item.drawable, item.text)
}
挨个在下面这个方法里面遍历
@Composable
fun AlignYourBodyElement(text: Int, s: String) {
Column(
modifier = Modifier,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painter = painterResource(id = text), contentDescription = null,
contentScale = ContentScale.Crop,//不加这句话,图片不是一个圆形
//contentScale = ContentScale.Crop
// 用于指定在将图像缩放到与卡片的宽度相同的同时,保留图像中心部分,以便显示一个“切片”效果的图像。
modifier = Modifier
.size(120.dp)
.clip(CircleShape)
)
Text(
text = s,
fontStyle = Italic
)
}
}
这个方法就一个比较重要的
contentScale = ContentScale.Crop
如果没有这段代码的话,
modifier = Modifier
.size(120.dp)
.clip(CircleShape)
这段代码是让图像变圆的,如果没有
contentScale = ContentScale.Crop
这段代码,图像就特别怪异
圆的两边像被砍了一刀
contentScale = ContentScale.Crop
chatgpt是这么解释的
contentScale
是一个用于指定如何缩放和裁剪显示内容的属性,它通常用于图片、视频等可缩放的内容。其中ContentScale.Crop
是一个预定义的枚举值,表示将内容缩放并裁剪以填充目标框架,使其填满可用空间并完全填充。这通常意味着图片的宽高比可能会被裁剪,以便完全填充所用的空间。这与ContentScale.FillBounds
相反,它会尽可能填充目标框架,但不会剪切内容。例如,如果目标框架的宽高比与内容的宽高比不同,那么内容可能会被留有空白区域。
我没怎么看懂,反正直接加上就对了
好,现在看下面的代码
LazyHorizontalGrid()
这个和LazyRow()很像,都是可以左右滑动。但是不一样,看我上面的上面的(n个上面的)截图可以看到,用LazyRow()的一列只有一个,但是LazyHorizontalGrid可以一列设置多个
LazyHorizontalGrid(
rows = GridCells.Fixed(2),
contentPadding = PaddingValues(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(15.dp),
modifier = modifier.height(215.dp)
//若不加最后这句最后界面有点点问题
) {
items(favoriteCollectionsData) { item ->
FavoriteCollectionCard(item.drawable, item.text)
}
}
通过
rows = GridCells.Fixed(2),
可以设置一列有多少个,其他都没啥问题
但是但是,一般情况下最大的问题是你的**LazyHorizontalGrid()**显示不出来
当时候我只找到了LazyVerticalGrid(),找不到LazyHorizontalGrid(),原本以为是某个
implementation
没加上去,最后发现Android开发者文档说了,我的kotlin版本太低了,所以没有这个,得升级版本,然后我就把kotlin那个改成了
implementation 'androidx.compose.foundation:foundation:1.4.2'
然后又报错,这次好像还是直接红了,说的是compose_ui_version 和org.jetbrains.kotlin.android的版本号不统一还是啥的。
最后改成了compose_ui_version = '1.4.3’
id ‘org.jetbrains.kotlin.android’ version ‘1.8.10’ apply false
然后又说好像必须得Sdk 33才能用,然后又改,
然后将compileSdk 改成了33
,结果把minSdk也改成33了导致只能用安卓13及以上的用(后来改了)
终于终于,最后**LazyHorizontalGrid()**可以用了
底部导航栏
@Composable
fun SootheBottomNavigation() {
BottomNavigation(
modifier = Modifier,
backgroundColor = MaterialTheme.colors.secondary
) {
BottomNavigationItem(
icon = {
Icon(
imageVector = Icons.Default.Home,
contentDescription = null
)
},
label = {
Text("HOME")
},
selected = true, onClick = {})
BottomNavigationItem(
icon = {
Icon(
imageVector = Icons.Default.AccountCircle,
contentDescription = null
)
},
label = {
Text("PROFILE")
},
selected = true, onClick = {})
}
}
这个不太难,主要就是会用BottomNavigation设置底部导航栏的颜色BottomNavigationItem来设置对应的icon与label
最重要也是最重要的,怎么让你的BottomNavigation位于界面的底部
Scaffold(bottomBar = { SootheBottomNavigation() }) { paddingValues ->
HomeScreen(Modifier.padding(paddingValues))
}
SootheBottomNavigation()是刚才那个底部导航栏
亲测
HomeScreen(Modifier.padding(paddingValues))
中括号里面的东西可以不写
对了HomeScreen()就是除了底部导航栏以外的所有东西
这个讲完了compose的基本布局也就结束了
什么你问我
还有下面
为什么不讲一下,直接一个Text结束。