未来Android开发的趋势,就是Compose声明式UI。声明式UI是大势所趋,告别传统的xml方式,你会看到在Compose中有flutter的影子。
本文可以连贯去看,带你做成一个小项目
一,使用下载安装最新版本AndroidStudio,创建项目会有Compose选项。
1,创建实体类TestBean
data class TestBean(val title:String,val content:String)
2,显示页面代码
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyComposeTheme {
TestItem(bean = TestBean("Jackson", "去哪里"))
}
}
}
}
@Composable
fun TestItem(bean: TestBean) {
Row(modifier = Modifier.padding(8.dp)) {
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
contentDescription = null,
modifier = Modifier
.size(50.dp)
.clip(CircleShape)
)
Spacer(modifier = Modifier.width(10.dp))
Column() {
Text(
text = bean.title,
color = MaterialTheme.colors.secondaryVariant
)
Spacer(modifier = Modifier.width(10.dp))
Text(
text = bean.content,
style = MaterialTheme.typography.body1,
modifier = Modifier.padding(5.dp),
maxLines = 1
)
}
}
}
3,运行效果
- setCotent:view显示入口,相当于xml布局方式setContentView()
- MyComposeTheme :项目主题样式
- @Composable:表示是用Compose方式写的view组件
- Row,Column,Image,Text:这些都是view组件,没啥可说的
- Modifier:使用view组件离不开的类,可以设置view样式等等
1,创建静态数据类ListData
object ListData {
val listData = listOf(
TestBean("Jackson", "I love you"),
TestBean("Jackson", "How are you How are you How are you How are you How are you"),
TestBean("Jackson", "What are you doing"),
TestBean("Jackson", "What's your name"),
TestBean("Jackson", "I love you"),
TestBean("Jackson", "I love you"),
TestBean("Jackson", "How are you"),
TestBean("Jackson", "What are you doing"),
TestBean("Jackson", "What's your name"),
TestBean("Jackson", "I love you")
)
}
2,创建列表
@Composable
fun TestListCompose(list: List<TestBean>) {
LazyColumn() {
items(list) { bean ->
TestItem(bean)
}
}
}
3,显示列表
setContent {
MyComposeTheme {
TestListCompose(ListData.listData)
}
}
4,运行效果
可以发现很简单就实现了一个列表,只需要一行代码LazyColumn就可以实现列表加载,省去了传统的adapter方式。
implementation "androidx.navigation:navigation-compose:$nav_version"
1,创建NavController
//rememberNavController() 方法来创建 NavController
val navController = rememberNavController()
2,创建创建 NavHost实现跳转
每个 NavController 都必须与一个 NavHost 可组合项相关联。NavHost 将 NavController 与导航图相关联,后者用于指定您应能够在其间进行导航的可组合项目的地。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyComposeTheme {
Surface(color = MaterialTheme.colors.background) {
NavHostDemo()
}
}
}
}
}
@Composable
fun NavHostDemo() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "one") {
//"one":用于导航的路由路径
composable("one") { PageOne(navController) }
//two:路由路径,name:参数名称
composable("two/{name}") { backStackEntry ->
PageTwo(navController, backStackEntry.arguments?.getString("name"))
}
}
}
//页面一
@Composable
fun PageOne(navController: NavController) {
//跳转到页面二,传递参数hello
Button(onClick = { navController.navigate("two/hello") }) {
Text(text = "跳转")
}
}
//页面二 接收参数name
@Composable
fun PageTwo(navController: NavController, name: String?) {
Button(onClick = { navController.popBackStack() }) {
Text(text = "$name")
}
}
五,BottomNavigation的使用
1,用于存放底部Item数据
data class BottomItem(val label: String, val selectItemRes: Int, val unSelectItemRes: Int)
companion object {
val mBottomTabItems =
listOf(
BottomItem("首页", R.drawable.ic_home_pressed, R.drawable.ic_home),
BottomItem("发现", R.drawable.ic_find_pressed, R.drawable.ic_find),
BottomItem("学习", R.drawable.ic_study_pressed, R.drawable.ic_study),
BottomItem("我的", R.drawable.ic_user_pressed, R.drawable.ic_user)
)
}
2,简单封装BottomNavigation
@Composable
fun BottomBarWidget(
navController: NavController,
selectedPosition: Int,
bottomItems: List<BottomItem>,
onItemSelected: (position: Int) -> Unit
) {
BottomNavigation() {
bottomItems.forEachIndexed { index, item ->
BottomNavigationItem(
selected = selectedPosition == index,
onClick = {
onItemSelected.invoke(index)
navController.navigate(item.label)
},
icon = {
Image(
painter = painterResource(id = if (selectedPosition == index) item.selectItemRes else item.unSelectItemRes),
contentDescription = item.label,
modifier = Modifier.size(25.dp),
contentScale = ContentScale.Inside
)
},
label = {
Text(
text = item.label,
color = if (selectedPosition == index) Color(0xFFF25822) else Color(0xFF999999)
)
},
)
}
}
}
3,创建NavHost
@Composable
fun NavPageDemo(navController: NavController) {
NavHost(
navController = navController as NavHostController,
startDestination = "首页"
) {
composable("首页") {
//首页
PageHome()
}
composable("发现") {
//发现
PageFind()
}
composable("学习") {
//学习
PageStudy()
}
composable("我的") {
//个人中心
PageUser()
}
}
4,编写页面
@Composable
fun PageHome() {
Surface(color = Color(0xFFE04F4F)) {
Row(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(),
horizontalArrangement = Arrangement.Center,//设置水平居中对齐
verticalAlignment = Alignment.CenterVertically//设置垂直居中对齐
) {
Text(
text = "首页",
color = Color.White
)
}
}
}
//其他页面相同 省略...
5,使用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyComposeTheme {
Surface(color = MaterialTheme.colors.background) {
val navController = rememberNavController()
var bottomSelectedState by remember { mutableStateOf(0) }
Scaffold(
bottomBar = {
BottomBarWidget(navController, bottomSelectedState, mBottomTabItems) {
bottomSelectedState = it
}
}
) {
NavPageDemo(navController)
}
}
}
}
}
六,Pager的使用
implementation "com.google.accompanist:accompanist-pager:0.24.2-alpha"
implementation "com.google.accompanist:accompanist-pager-indicators:0.24.2-alpha"
- HorizontalPager:水平滑动
- VerticalPager:垂直滑动
1,HorizontalPager使用
改造PageHome代码如下,编写BannerView
@ExperimentalPagerApi
@Composable
fun PageHome() {
Surface {
BannerView()
}
}
@ExperimentalPagerApi
@Composable
fun BannerView() {
val pagerState = rememberPagerState()
Box(
) {
HorizontalPager(
count = 10,
modifier = Modifier.height(150.dp),
state = pagerState
) { page ->
Text(
text = "Page: $page",
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
.background(
if (page % 2 == 0) Color(0xFF34BFD1) else Color(0xFFF25822)
)
)
}
// 水平指示器
HorizontalPagerIndicator(
pagerState = pagerState,
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(16.dp),
)
}
}
2,看效果
七,TabRow和Pager的结合1,继续改造PageHome代码
@ExperimentalPagerApi
@Composable
fun PageHome() {
Surface {
TabRowHome()
}
}
@ExperimentalPagerApi
@Composable
fun TabRowHome() {
val pages = listOf(
"首页", "新闻", "资讯", "精品"
)
val tabPageState = rememberPagerState(0)
Column() {
TabRow(
selectedTabIndex = tabPageState.currentPage,
indicator = { tabPositions ->
TabRowDefaults.Indicator(
Modifier.pagerTabIndicatorOffset(tabPageState, tabPositions),
color = Color(0xFFF25822)
)
},
) {
pages.forEachIndexed { index, title ->
Tab(
text = {
Text(text = title)
},
selected = tabPageState.currentPage == index, //是否选中
onClick = { //点击事件
CoroutineScope(Dispatchers.Main).launch {
tabPageState.scrollToPage(index)
}
},
selectedContentColor = Color(0xFFF25822), //选中的颜色
unselectedContentColor = Color(0xFF999999), //未选中的颜色
)
}
}
HorizontalPager(
count = pages.size,
state = tabPageState,
reverseLayout = false,
itemSpacing = 2.dp
) { page ->
if (page == 0) {
BannerView()
} else {
Column(modifier = Modifier.fillMaxSize()) {
Text(
text = "Page: $page",
modifier = Modifier.fillMaxWidth()
)
}
}
}
}
}
2,效果图
八,ConstraintLayout的使用 implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha08'
1,继续改造PagerHome,在BannerView下方继续添如下View
@Composable
fun IconView(){
ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
val (box1, box2, box3,box4) = createRefs()
createHorizontalChain(box1, box2, box3,box4)
Box(modifier = Modifier
.clip(CircleShape)
.size(50.dp)
.background(Color.Red)
.constrainAs(box1) {})
Box(modifier = Modifier
.clip(CircleShape)
.size(50.dp)
.background(Color.Yellow)
.constrainAs(box2) {})
Box(modifier = Modifier
.clip(CircleShape)
.size(50.dp)
.background(Color.Blue)
.constrainAs(box3) {})
Box(modifier = Modifier
.clip(CircleShape)
.size(50.dp)
.background(Color.Green)
.constrainAs(box4) {})
}
}
2,效果图
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun GridView() {
LazyVerticalGrid(cells = GridCells.Fixed(3)) {
items(6) {
Card(
backgroundColor = Color(0xFF252525),
modifier = Modifier.size(80.dp).padding(10.dp)
){}
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)