基于登录 Kotlin 的用户的底部导航菜单
Bottom navigation menu based on the user logged in Kotlin
是否可以hide/show Kotlin 中基于用户登录的底部导航菜单项?
我不想向所有用户显示底部导航中的一些项目。
编辑:
这是我的代码。
我想在用户不存在时从菜单中删除 @+id/navigation_products
,例如 abc 和 xyz。
bottom_nav_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_dashboard"
android:icon="@drawable/ic_vector_dashboard"
android:title="@string/title_dashboard" />
<item
android:id="@+id/navigation_products"
android:icon="@drawable/ic_vector_products"
android:title="@string/title_products" />
<item
android:id="@+id/navigation_orders"
android:icon="@drawable/ic_vector_orders"
android:title="@string/title_orders" />
<item
android:id="@+id/navigation_sold_products"
android:icon="@drawable/ic_vector_sold_products"
android:title="@string/title_sold_products" />
<item
android:id="@+id/navigation_orders_by_status"
android:icon="@drawable/ic_vector_sold_products"
android:title="@string/title_orders_by_status" />
</menu>
mobile_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/navigation_dashboard">
<fragment
android:id="@+id/navigation_dashboard"
android:name="com.ui.fragments.DashboardFragment"
android:label="@string/title_dashboard"
tools:layout="@layout/fragment_dashboard" />
<fragment
android:id="@+id/navigation_products"
android:name="com.ui.fragments.ProductsFragment"
android:label="@string/title_products"
tools:layout="@layout/fragment_products" />
<fragment
android:id="@+id/navigation_orders"
android:name="com.ui.fragments.OrdersFragment"
android:label="@string/title_orders"
tools:layout="@layout/fragment_orders" />
<fragment
android:id="@+id/navigation_sold_products"
android:name="com.ui.fragments.SoldProductsFragment"
android:label="@string/title_sold_products"
tools:layout="@layout/fragment_sold_products" />
<fragment
android:id="@+id/navigation_orders_by_status"
android:name="com.ui.fragments.OrdersByStatusFragment"
android:label="@string/title_orders_by_status"
tools:layout="@layout/fragment_sold_products" />
</navigation>
DashboardActivity.kt
class DashboardActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)
supportActionBar!!.setBackgroundDrawable(
ContextCompat.getDrawable(
this@DashboardActivity,
R.drawable.app_gradient_color_background
)
)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_products,
R.id.navigation_dashboard,
R.id.navigation_orders,
R.id.navigation_sold_products,
R.id.navigation_orders_by_status
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onBackPressed() {
doubleBackToExit()
}
}
是的,这是可能的。对于这样的逻辑,您必须动态更改底部导航菜单。为了使事情更简单,您可以添加以下依赖项:
// Event Bus
implementation 'org.greenrobot:eventbus:3.2.0'
那么我们假设如下:
Activity xml
<layout>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".framework.ui.view.MainActivity">
<fragment
android:id="@+id/fragment_container"
android:name="com.example.app.framework.utils.MainNavHostFragment"
android:layout_width="match_parent"
android:layout_height="@dimen/wrapContent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_main" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemHorizontalTranslationEnabled="false"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/default_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
default_menu.xml(所有用户的菜单)
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/homeFragment"
android:icon="@drawable/child_selector_home"
android:title="@string/bottom_nav_home" />
<item
android:id="@id/nav_shop"
android:icon="@drawable/child_selector_shop"
android:title="@string/bottom_nav_shop" />
<item
android:id="@id/userLoggedOutFragment"
android:icon="@drawable/child_selector_profil"
android:title="@string/bottom_nav_profil" />
</menu>
logged_in_menu
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/homeFragment"
android:icon="@drawable/child_selector_home"
android:title="@string/bottom_nav_home"/>
<item
android:id="@id/documentsFragment"
android:icon="@drawable/child_selector_documents"
android:title="@string/bottom_nav_documents"/>
<item
android:id="@id/nav_shop"
android:icon="@drawable/child_selector_shop"
android:title="@string/bottom_nav_shop"/>
<item
android:id="@id/shoppingCartFragment"
android:icon="@drawable/child_selector_shopping_cart"
android:title="@string/bottom_nav_shopping_cart" />
<item
android:id="@id/userLoggedInFragment"
android:icon="@drawable/child_selector_profil"
android:title="@string/bottom_nav_profil"/>
</menu>
Activity
class MainActivity : AppCompatActivity() {
// Basic Binding Stuff
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate()
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
@Subscribe
fun onLoginLogOutEvent(event: LogInOutEvent) {
if (event.isLoggedIn) signInUserBottomNav() else signOutUserBottomNav()
}
private fun setUpBottomNav(newMenu: Int) {
with(binding.bottomNavigationView) {
menu.clear()
inflateMenu(newMenu)
setupWithNavController(findNavController(R.id.fragment_container))
// fix blinking when re selecting bottom nav item
setOnNavigationItemReselectedListener {}
}
}
private fun signOutUserBottomNav() {
setUpBottomNav(R.menu.default_menu.xml)
}
private fun signInUserBottomNav() {
setUpBottomNav(R.menu.logged_in_menu)
}
}
事件
value class LogInOutEvent(
val isLoggedIn: Boolean,
)
activity 执行以下操作:每次您通过事件总线从片段或 activity 发送事件时,onLoginOutEvent()
都会执行。在这里它检查您是否发送用户登录的事件。你可以这样使用它:
一些片段
class SomeFragment : Fragment() {
override fun onViewCreated() {
super.onViewCreated()
}
private fun doStuff() {
// here you do your stuff and decide whether to change the bottom nav or not
Eventbus.getDefault().post(LoginOutevent(isLoggedin = true))
}
}
您可以使用整个菜单项启动应用程序,然后根据登录用户删除项目:
这是 BottonNavigationView
的扩展函数,可以删除具有特定 id 的项目
fun BottomNavigationView.removeItem(id: Int) {
if (menu.findItem(id) != null)
menu.removeItem(id)
}
然后你可以将它应用到登录用户:
// check logged-in user
when (loggdUser) {
user_a -> {
bottomNavView.removeItem(R.id.menu_item_id1)
bottomNavView.removeItem(R.id.menu_item_id2)
}
user_b -> bottomNavView.removeItem(R.id.menu_item_id2)
}
menu_item_idx
应该是菜单 ID,bottomNavView
是 BottomNavigationView
实例;所以把它们换成你的
更新:
在代码中测试:
class DashboardActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)
supportActionBar!!.setBackgroundDrawable(
ContextCompat.getDrawable(
this@DashboardActivity,
R.drawable.app_gradient_color_background
)
)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_products,
R.id.navigation_dashboard,
R.id.navigation_orders,
R.id.navigation_sold_products,
R.id.navigation_orders_by_status
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
val loggdUser = "user_a"
// check logged-in user
when (loggdUser) {
"user_a" -> {
navView.removeItem(R.id.navigation_orders_by_status)
navView.removeItem(R.id.navigation_orders)
}
"user_b" -> navView.removeItem(R.id.navigation_orders)
}
}
fun BottomNavigationView.removeItem(id: Int) {
if (menu.findItem(id) != null)
menu.removeItem(id)
}
}
是否可以hide/show Kotlin 中基于用户登录的底部导航菜单项? 我不想向所有用户显示底部导航中的一些项目。
编辑: 这是我的代码。
我想在用户不存在时从菜单中删除 @+id/navigation_products
,例如 abc 和 xyz。
bottom_nav_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_dashboard"
android:icon="@drawable/ic_vector_dashboard"
android:title="@string/title_dashboard" />
<item
android:id="@+id/navigation_products"
android:icon="@drawable/ic_vector_products"
android:title="@string/title_products" />
<item
android:id="@+id/navigation_orders"
android:icon="@drawable/ic_vector_orders"
android:title="@string/title_orders" />
<item
android:id="@+id/navigation_sold_products"
android:icon="@drawable/ic_vector_sold_products"
android:title="@string/title_sold_products" />
<item
android:id="@+id/navigation_orders_by_status"
android:icon="@drawable/ic_vector_sold_products"
android:title="@string/title_orders_by_status" />
</menu>
mobile_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/navigation_dashboard">
<fragment
android:id="@+id/navigation_dashboard"
android:name="com.ui.fragments.DashboardFragment"
android:label="@string/title_dashboard"
tools:layout="@layout/fragment_dashboard" />
<fragment
android:id="@+id/navigation_products"
android:name="com.ui.fragments.ProductsFragment"
android:label="@string/title_products"
tools:layout="@layout/fragment_products" />
<fragment
android:id="@+id/navigation_orders"
android:name="com.ui.fragments.OrdersFragment"
android:label="@string/title_orders"
tools:layout="@layout/fragment_orders" />
<fragment
android:id="@+id/navigation_sold_products"
android:name="com.ui.fragments.SoldProductsFragment"
android:label="@string/title_sold_products"
tools:layout="@layout/fragment_sold_products" />
<fragment
android:id="@+id/navigation_orders_by_status"
android:name="com.ui.fragments.OrdersByStatusFragment"
android:label="@string/title_orders_by_status"
tools:layout="@layout/fragment_sold_products" />
</navigation>
DashboardActivity.kt
class DashboardActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)
supportActionBar!!.setBackgroundDrawable(
ContextCompat.getDrawable(
this@DashboardActivity,
R.drawable.app_gradient_color_background
)
)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_products,
R.id.navigation_dashboard,
R.id.navigation_orders,
R.id.navigation_sold_products,
R.id.navigation_orders_by_status
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onBackPressed() {
doubleBackToExit()
}
}
是的,这是可能的。对于这样的逻辑,您必须动态更改底部导航菜单。为了使事情更简单,您可以添加以下依赖项:
// Event Bus
implementation 'org.greenrobot:eventbus:3.2.0'
那么我们假设如下:
Activity xml
<layout>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".framework.ui.view.MainActivity">
<fragment
android:id="@+id/fragment_container"
android:name="com.example.app.framework.utils.MainNavHostFragment"
android:layout_width="match_parent"
android:layout_height="@dimen/wrapContent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_main" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemHorizontalTranslationEnabled="false"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/default_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
default_menu.xml(所有用户的菜单)
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/homeFragment"
android:icon="@drawable/child_selector_home"
android:title="@string/bottom_nav_home" />
<item
android:id="@id/nav_shop"
android:icon="@drawable/child_selector_shop"
android:title="@string/bottom_nav_shop" />
<item
android:id="@id/userLoggedOutFragment"
android:icon="@drawable/child_selector_profil"
android:title="@string/bottom_nav_profil" />
</menu>
logged_in_menu
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/homeFragment"
android:icon="@drawable/child_selector_home"
android:title="@string/bottom_nav_home"/>
<item
android:id="@id/documentsFragment"
android:icon="@drawable/child_selector_documents"
android:title="@string/bottom_nav_documents"/>
<item
android:id="@id/nav_shop"
android:icon="@drawable/child_selector_shop"
android:title="@string/bottom_nav_shop"/>
<item
android:id="@id/shoppingCartFragment"
android:icon="@drawable/child_selector_shopping_cart"
android:title="@string/bottom_nav_shopping_cart" />
<item
android:id="@id/userLoggedInFragment"
android:icon="@drawable/child_selector_profil"
android:title="@string/bottom_nav_profil"/>
</menu>
Activity
class MainActivity : AppCompatActivity() {
// Basic Binding Stuff
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate()
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
@Subscribe
fun onLoginLogOutEvent(event: LogInOutEvent) {
if (event.isLoggedIn) signInUserBottomNav() else signOutUserBottomNav()
}
private fun setUpBottomNav(newMenu: Int) {
with(binding.bottomNavigationView) {
menu.clear()
inflateMenu(newMenu)
setupWithNavController(findNavController(R.id.fragment_container))
// fix blinking when re selecting bottom nav item
setOnNavigationItemReselectedListener {}
}
}
private fun signOutUserBottomNav() {
setUpBottomNav(R.menu.default_menu.xml)
}
private fun signInUserBottomNav() {
setUpBottomNav(R.menu.logged_in_menu)
}
}
事件
value class LogInOutEvent(
val isLoggedIn: Boolean,
)
activity 执行以下操作:每次您通过事件总线从片段或 activity 发送事件时,onLoginOutEvent()
都会执行。在这里它检查您是否发送用户登录的事件。你可以这样使用它:
一些片段
class SomeFragment : Fragment() {
override fun onViewCreated() {
super.onViewCreated()
}
private fun doStuff() {
// here you do your stuff and decide whether to change the bottom nav or not
Eventbus.getDefault().post(LoginOutevent(isLoggedin = true))
}
}
您可以使用整个菜单项启动应用程序,然后根据登录用户删除项目:
这是 BottonNavigationView
的扩展函数,可以删除具有特定 id 的项目
fun BottomNavigationView.removeItem(id: Int) {
if (menu.findItem(id) != null)
menu.removeItem(id)
}
然后你可以将它应用到登录用户:
// check logged-in user
when (loggdUser) {
user_a -> {
bottomNavView.removeItem(R.id.menu_item_id1)
bottomNavView.removeItem(R.id.menu_item_id2)
}
user_b -> bottomNavView.removeItem(R.id.menu_item_id2)
}
menu_item_idx
应该是菜单 ID,bottomNavView
是 BottomNavigationView
实例;所以把它们换成你的
更新:
在代码中测试:
class DashboardActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)
supportActionBar!!.setBackgroundDrawable(
ContextCompat.getDrawable(
this@DashboardActivity,
R.drawable.app_gradient_color_background
)
)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_products,
R.id.navigation_dashboard,
R.id.navigation_orders,
R.id.navigation_sold_products,
R.id.navigation_orders_by_status
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
val loggdUser = "user_a"
// check logged-in user
when (loggdUser) {
"user_a" -> {
navView.removeItem(R.id.navigation_orders_by_status)
navView.removeItem(R.id.navigation_orders)
}
"user_b" -> navView.removeItem(R.id.navigation_orders)
}
}
fun BottomNavigationView.removeItem(id: Int) {
if (menu.findItem(id) != null)
menu.removeItem(id)
}
}