📜  Android Jetpack Compose 中的底部导航栏

📅  最后修改于: 2022-05-13 01:54:38.961000             🧑  作者: Mango

Android Jetpack Compose 中的底部导航栏

我们都在很多应用程序中看到过BottomNavigationBar,比如Instagram、Quora。在本文中,我们将学习如何在 Jetpack Compose 中添加底部导航。下面是它的外观示例。

为什么我们需要底部导航栏?

  • 它允许用户轻松切换到不同的活动/片段。
  • 它使用户了解应用程序中可用的不同屏幕。
  • 用户能够检查他们目前在哪个屏幕上。

下面是底部导航栏的解剖图:

按钮导航视图



先决条件:

  • Jetpack Compose 的知识。
  • Jetpack compose 中的 Scaffold 知识。
  • 撰写导航的知识。

分步实施

第 1 步:创建一个新项目(或在现有 Compose 项目中使用它)

在 Android Studio Canary 版本中创建一个新项目。参考这篇文章:如何使用 Jetpack Compose 在 Android Studio Canary 版本中创建一个新项目?

项目结构

第 2 步:添加依赖项

打开 build.gradle(app) 并添加以下依赖项。

第 3 步:创建屏幕

打开Screens.kt并创建三个屏幕,主页、搜索、配置文件。



主屏幕:

Kotlin
@Composable
fun HomeScreen() {
  
    // Column Composable,
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White),
        // Parameters set to place the items in center
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        // Icon Composable
        Icon(
            imageVector = Icons.Default.Home,
            contentDescription = "home",
            tint = Color(0xFF0F9D58)
        )
        // Text to Display the current Screen
        Text(text = "Home", color = Color.Black)
    }
}


Kotlin
@Composable
fun SearchScreen() {
    // Column Composable,
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White),
        // parameters set to place the items in center
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        // Icon Composable
        Icon(
            imageVector = Icons.Default.Search,
            contentDescription = "search",
            tint = Color(0xFF0F9D58)
        )
        // Text to Display the current Screen
        Text(text = "Search", color = Color.Black)
    }
}


Kotlin
@Composable
fun ProfileScreen() {
    // Column Composable,
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White),
        // parameters set to place the items in center
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        // Icon Composable
        Icon(
            imageVector = Icons.Default.Person,
            contentDescription = "Profile",
            tint = Color(0xFF0F9D58)
        )
        // Text to Display the current Screen
        Text(text = "Profile", color = Color.Black)
    }
}


Kotlin
import androidx.compose.ui.graphics.vector.ImageVector
  
data class BottomNavItem(
    val label: String,
    val icon: ImageVector,
    val route:String,
)


Kotlin
object Constants {
    val BottomNavItems = listOf(
        BottomNavItem(
            label = "Home",
            icon = Icons.Filled.Home,
            route = "home"
        ),
        BottomNavItem(
            label = "Search",
            icon = Icons.Filled.Search,
            route = "search"
        ),
        BottomNavItem(
            label = "Profile",
            icon = Icons.Filled.Person,
            route = "profile"
        )
    )
}


Kotlin
@Composable
fun NavHostContainer(
    navController: NavHostController,
    padding: PaddingValues
) {
  
    NavHost(
        navController = navController, 
          
        // set the start destination as home
        startDestination = "home",
  
        // Set the padding provided by scaffold
        modifier = Modifier.padding(paddingValues = padding),
          
        builder = {
  
            // route : Home
            composable("home") {
                HomeScreen()
            }
  
            // route : search
            composable("search") {
                SearchScreen()
            }
  
            // route : profile
            composable("profile") {
                ProfileScreen()
            }
        })
  
}


Kotlin
@Composable
fun BottomNavigationBar(navController: NavHostController) {
  
    BottomNavigation(
        
        // set background color
        backgroundColor = Color(0xFF0F9D58)) {
  
        // observe the backstack
        val navBackStackEntry by navController.currentBackStackEntryAsState()
  
        // observe current route to change the icon 
          // color,label color when navigated
        val currentRoute = navBackStackEntry?.destination?.route
  
        // Bottom nav items we declared
        Constants.BottomNavItems.forEach { navItem ->
  
            // Place the bottom nav items
            BottomNavigationItem(
                    
                // it currentRoute is equal then its selected route
                selected = currentRoute == navItem.route,
  
                // navigate on click
                onClick = {
                    navController.navigate(navItem.route)
                },
                
                // Icon of navItem
                icon = {
                    Icon(imageVector = navItem.icon, contentDescription = navItem.label)
                },
                
                // label
                label = {
                    Text(text = navItem.label)
                },
                alwaysShowLabel = false
            )
        }
    }
}


Kotlin
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BottomNavigationTheme {
                
                // remember navController so it does not
                  // get recreated on recomposition
                val navController = rememberNavController()
  
                Surface(color = Color.White) {
                    // Scaffold Component
                    Scaffold(
                        // Bottom navigation
                        bottomBar = {
                            BottomNavigationBar(navController = navController)
                        }, content = { padding ->
                            // Navhost: where screens are placed
                            NavHostContainer(navController = navController, padding = padding)
                        }
                    )
                }
            }
        }
    }
}


搜索屏幕:

科特林

@Composable
fun SearchScreen() {
    // Column Composable,
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White),
        // parameters set to place the items in center
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        // Icon Composable
        Icon(
            imageVector = Icons.Default.Search,
            contentDescription = "search",
            tint = Color(0xFF0F9D58)
        )
        // Text to Display the current Screen
        Text(text = "Search", color = Color.Black)
    }
}

配置文件屏幕:

科特林

@Composable
fun ProfileScreen() {
    // Column Composable,
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White),
        // parameters set to place the items in center
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        // Icon Composable
        Icon(
            imageVector = Icons.Default.Person,
            contentDescription = "Profile",
            tint = Color(0xFF0F9D58)
        )
        // Text to Display the current Screen
        Text(text = "Profile", color = Color.Black)
    }
}

第 4 步:创建底部导航项目

让我们创建一个数据类来保存与底部导航项(如标签、图标、路线)相关的数据。打开模型/BottomNavItem.kt并添加以下代码。

科特林

import androidx.compose.ui.graphics.vector.ImageVector
  
data class BottomNavItem(
    val label: String,
    val icon: ImageVector,
    val route:String,
)

并创建一些底部导航项目,打开 Utils/ Constants.kt 以及三个导航项目的列表。



科特林

object Constants {
    val BottomNavItems = listOf(
        BottomNavItem(
            label = "Home",
            icon = Icons.Filled.Home,
            route = "home"
        ),
        BottomNavItem(
            label = "Search",
            icon = Icons.Filled.Search,
            route = "search"
        ),
        BottomNavItem(
            label = "Profile",
            icon = Icons.Filled.Person,
            route = "profile"
        )
    )
}

第 5 步:使用 MainActivity 和导航组件

MainActivity.kt 中创建一个名为NavHostContainer的函数,它将包含 NavHost 和用于导航的 Composable。参考代码中的注释更好理解

科特林

@Composable
fun NavHostContainer(
    navController: NavHostController,
    padding: PaddingValues
) {
  
    NavHost(
        navController = navController, 
          
        // set the start destination as home
        startDestination = "home",
  
        // Set the padding provided by scaffold
        modifier = Modifier.padding(paddingValues = padding),
          
        builder = {
  
            // route : Home
            composable("home") {
                HomeScreen()
            }
  
            // route : search
            composable("search") {
                SearchScreen()
            }
  
            // route : profile
            composable("profile") {
                ProfileScreen()
            }
        })
  
}

第 6 步:添加底部导航

请参阅注释以获得更好的理解。

科特林

@Composable
fun BottomNavigationBar(navController: NavHostController) {
  
    BottomNavigation(
        
        // set background color
        backgroundColor = Color(0xFF0F9D58)) {
  
        // observe the backstack
        val navBackStackEntry by navController.currentBackStackEntryAsState()
  
        // observe current route to change the icon 
          // color,label color when navigated
        val currentRoute = navBackStackEntry?.destination?.route
  
        // Bottom nav items we declared
        Constants.BottomNavItems.forEach { navItem ->
  
            // Place the bottom nav items
            BottomNavigationItem(
                    
                // it currentRoute is equal then its selected route
                selected = currentRoute == navItem.route,
  
                // navigate on click
                onClick = {
                    navController.navigate(navItem.route)
                },
                
                // Icon of navItem
                icon = {
                    Icon(imageVector = navItem.icon, contentDescription = navItem.label)
                },
                
                // label
                label = {
                    Text(text = navItem.label)
                },
                alwaysShowLabel = false
            )
        }
    }
}

第 7 步:将所有内容放在 Scaffold 中

现在我们需要把所有的东西都放在MainActivity类的 setContent 中

科特林

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BottomNavigationTheme {
                
                // remember navController so it does not
                  // get recreated on recomposition
                val navController = rememberNavController()
  
                Surface(color = Color.White) {
                    // Scaffold Component
                    Scaffold(
                        // Bottom navigation
                        bottomBar = {
                            BottomNavigationBar(navController = navController)
                        }, content = { padding ->
                            // Navhost: where screens are placed
                            NavHostContainer(navController = navController, padding = padding)
                        }
                    )
                }
            }
        }
    }
}

输出:

项目链接:点我

想要一个更快节奏和更具竞争力的环境来学习 Android 的基础知识吗?
单击此处前往由我们的专家精心策划的指南,旨在让您立即做好行业准备!