【问题标题】:Access a menu item of an Activity in a fragment?在片段中访问 Activity 的菜单项?
【发布时间】:2021-07-13 10:34:35
【问题描述】:

我是 Android 新手。我有一个活动,它有一个片段和底部导航视图,它绑定到一组菜单。我想在片段中捕获菜单项单击事件。如何做到这一点?

<?xml version="1.0" encoding="utf-8"?>
<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=".view.MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentContainerView"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="1dp"
        android:layout_marginTop="1dp"
        android:layout_marginEnd="1dp"
        android:layout_marginBottom="1dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/todo_nav" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>

【问题讨论】:

  • ViewModel 不能捕获任何与 View 相关的内容,否则它会泄漏您的 Activity/Fragment。您应该反转您的设计,以便 Activity 或 Fragment 通知 ViewModel 发生这些事件。
  • @Tenfour04 你是对的。我实际上想在片段中访问它,而不是在它的视图模型中。我已经编辑了问题。

标签: android kotlin android-mvvm


【解决方案1】:

在您的 MainActivity 中。将 BottomNavigationView 设为公开

public BottomNavigationView bottomNavigation;

在 Fragment 中,访问 BottomNavigationView 并用它做任何你想做的事情。

if (getActivity() instanceof MainActivity) {
        // get Main Activity
        activity = (Main) getActivity();
     
         // Do what you want to do with bottom Navigation
        activity.BottomNavigationView 
}

【讨论】:

    【解决方案2】:

    我为名为 MainActivity 的应用程序使用了一个 Activity。由于我知道它是与应用程序中的任何 Fragment 相关联的唯一活动,因此将其设置为扩展属性是安全的。和requireActivity()一样,只能在附加Fragment时使用。

    val Fragment.mainActivity: MainActivity get() = requireActivity() as MainActivity
    

    然后,如果您使用的是 NavController,您可以添加一个侦听器,但是您需要记住在分离 Fragment 时将其删除,这样 Fragment 就不会泄漏到 NavController 并且侦听器不会在何时被调用Fragment 已分离。

    class MyFragment: Fragment(), NavController.OnDestinationChangedListener {
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            //...
            mainActivity.navController.addOnDestinationChangedListener(this)
        }
    
        override fun onDestroyView() {
            super.onDestroyView()
            mainActivity.navController.removeOnDestinationChangedListener(this)
        }
    
        override fun onDestinationChanged(
            controller: NavController,
            destination: NavDestination,
            arguments: Bundle?
        ) {
            //...
        }
    }
    

    【讨论】:

      【解决方案3】:

      要获得关于导航的优雅解决方案,请使用 Navigation UI 框架。这里是官方文档:Bottom Navigation

      回答您的问题:

      interface BottomNavigationListener{
         onButtonOneClicked(View yourOptionalArgument)
         onButtonOneClicked(View yourOptionalArgument)
      }
      
      • MainFragment : Fragment, BottomNavigationListener 扩展它(并且需要实现)

      在您的活动中;创建一个 BottomNavigationListener 类型的属性:

      var bottomNavListener: BottomNavigationListener?
      

      一旦你可以访问你的片段就初始化它,并在onDestroy()中删除它

      override fun onCreate(){
          val mainFragment = supportFragmentManager.findFragmentByTag(tag):MainFragment
          // requires you to set tag in your MainFragment first
          bottomNavListener = mainFragment
      }
      
      override fun onDestroy(){
          bottomNavListener = null
      }
      

      在Activity中从BottomBarItems调用onClickListener时,调用相应的函数:

      bottomBarButtonOne.setOnClickListener(v -> {
          bottomNavListener.onButtonOneClicked(v);
          // do stuff here
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-30
        • 2019-04-21
        • 2011-11-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多