JetPack Compose安卓开发之底部导航Tabbar
效果,页面切换
项目结构
TabBar.kt
package com.weimin.strollerapp.components.tabbar
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@Composable
fun TabBar(
destinations: List<Navigation>,
currentDestination: String,
onNavigateTo: (Int) -> Unit,
modifier: Modifier = Modifier
): Unit {
Row(
// 底部导航栏宽度充满屏幕,并远适配离安全区底部
modifier = Modifier
.fillMaxWidth()
.navigationBarsPadding()
) {
destinations.forEachIndexed { index, destination ->
val selected = destination.route == currentDestination
val color = if (selected)
MaterialTheme.colorScheme.primary
else
MaterialTheme.colorScheme.onSurface
Column(
// 水平居中
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.weight(1f)
.clickable() { onNavigateTo(index) }
) {
Image(
painter = painterResource(
id = if (selected)
destination.selectedIcon
else
destination.unSelectedIcon
),
contentDescription = stringResource(id = destination.titleTextId),
modifier = Modifier.size(25.dp)
)
Spacer(modifier = Modifier.width(5.dp))
Text(text = stringResource(id = destination.titleTextId), color = color)
}
}
}
}
Navigation.kt 枚举
package com.weimin.strollerapp.components.tabbar
import com.weimin.strollerapp.R
enum class Navigation(
val selectedIcon: Int,
val unSelectedIcon: Int,
val titleTextId: Int,
val route: String,
) {
HomePage(
selectedIcon = R.drawable.home1,
unSelectedIcon = R.drawable.home,
titleTextId = R.string.tabbar_home,
route = "Home_Page"
),
MinePage(
selectedIcon = R.drawable.home1,
unSelectedIcon = R.drawable.home,
titleTextId = R.string.tabbar_mine,
route = "Mine_Page"
)
}
MainRoute.kt 主路由
package com.weimin.strollerapp.components.route
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import com.weimin.strollerapp.components.tabbar.Navigation
import com.weimin.strollerapp.components.tabbar.TabBar
import com.weimin.strollerapp.view.home.HomePage
import com.weimin.strollerapp.view.mine.MinePage
import kotlinx.coroutines.launch
@Composable
fun MainRoute(finishPage: () -> Unit = {}) {
MainScreen()
}
//配置导航
@Composable
fun MainScreen(
finishPage: () -> Unit = {}
) {
//x当前选中的界面名称
var currentDestination by rememberSaveable {
mutableStateOf("Home_Page")
}
// 显示页面,控制页面
val pagerState = rememberPagerState {
4
}
val scope = rememberCoroutineScope()
Column(modifier = Modifier.fillMaxSize()) {
HorizontalPager(
state = pagerState,
userScrollEnabled = true,
// beyondBoundsPageCount = 4, //加载屏幕外的更多页面
modifier = Modifier
.fillMaxWidth()
.weight(1f) // 占满剩余空间(高度)
) { page ->
when (page) {
0 -> HomePage()
1 -> MinePage()
}
}
TabBar(
destinations = Navigation.entries,
currentDestination = currentDestination,
onNavigateTo = { index ->
currentDestination = Navigation.values()[index].route
// 启动协程
scope.launch {
// 挂起函数
pagerState.animateScrollToPage(index)
}
},
modifier = Modifier
)
}
}
MainActivity.kt 主页面应用
package com.weimin.strollerapp
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.compose.rememberNavController
import com.weimin.strollerapp.components.route.MainRoute
import com.weimin.strollerapp.ui.theme.StrollerAppTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
StrollerAppTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting(
// navController= navController
)
}
}
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun Greeting() {
MainRoute()
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
StrollerAppTheme {
Greeting()
}
}