【问题标题】:Android Kotlin hooking up navigation in fragments with databindingAndroid Kotlin 通过数据绑定在片段中连接导航
【发布时间】:2020-03-18 16:10:03
【问题描述】:

问题

我有一个包含多个fragmentsactivity_main.xmlfragment 中的 1 个是 bottom_menu_bar,它有 2 个按钮,我希望应用程序在单击时导航到这些按钮。

但是,我不确定连接navController 的正确方法是什么。这应该通过MainActivity.kt 还是通过FragmentBottomMainMenu.ktv 来完成(在其中创建底部菜单栏片段)

注意:根据 android 的规范,我使用的是databinding 而不是findViewById


activity_main.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <fragment
        android:id="@+id/navigation_graph_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/navigation_graph" />


    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/Fragment_Bottom_Main_Menu_hosted_in_activity_main"
        android:name="com.createdlesson.lesson1.FragmentBottomMainMenu"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

MainActivity.kt

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)  // hooking up xml to DataBinding

    //This is just a test. ignore this please. 
    //binding.apply {
        // testText.text = "overwrite text Here" 
    //}
}
}

Fragment_bottom_main_menu.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FragmentBottomMainMenu">
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom">
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/fragment_bottom_main_menu_items_container"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            app:backgroundTint="@color/colorPrimary"
            app:menu="@menu/fragment_bottom_main_menu_items" />
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout>
</layout>

FragmentBottomMainMenu.kt -> 这是我认为应该实例化和连接NavController 的地方......但我不确定这是否正确,或者应该如何正确完成

class FragmentBottomMainMenu : Fragment() {

private lateinit var binding: FragmentBottomMainMenuBinding

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    Log.i("FragBotMainMenu", "Inflating bottom main menu")
    binding = DataBindingUtil.inflate(inflater, R.layout.fragment_bottom_main_menu, container, false)
    binding.fragmentBottomMainMenuItemsContainer.setOnNavigationItemSelectedListener {
        when(it.itemId){
            R.id.item1-> {
                view?.findNavController()?.navigate(R.id.action_fragmentBottomMainMenu_to_fragmentItem1)
                println("Navigated to item1")
                return@setOnNavigationItemSelectedListener true
            }
            R.id.item2-> {
                view?.findNavController()?.navigate(R.id.action_fragmentBottomMainMenu_to_fragmentItem2)
                println("Navigated to item2")
                return@setOnNavigationItemSelectedListener true
            }
            else -> {
                println("${it.title}")
                return@setOnNavigationItemSelectedListener true
            }
        }
    }
    return binding.root
}
}

fragment_bottom_main_menu_items.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item
    android:id="@+id/item1"
    android:title="item no 1"/>
<item
    android:id="@+id/item2"
    android:title="item no 2"/>
</menu>

navigation_graph.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/navigation_graph"
app:startDestination="@id/fragmentBottomMainMenu">

<fragment
    android:id="@+id/fragmentBottomMainMenu"
    android:name="com.createdlesson.lesson1.FragmentBottomMainMenu"
    android:label="FragmentBottomMainMenu" >
    <action
        android:id="@+id/action_fragmentBottomMainMenu_to_fragmentItem1"
        app:destination="@id/fragmentItem1" />
    <action
        android:id="@+id/action_fragmentBottomMainMenu_to_fragmentItem2"
        app:destination="@id/fragmentItem2" />
</fragment>

<fragment
    android:id="@+id/fragmentItem1"
    android:name="com.createdlesson.lesson1.FragmentItem1"
    android:label="fragment_item1"
    tools:layout="@layout/fragment_item1"/>
<fragment
    android:id="@+id/fragmentItem2"
    android:name="com.createdlesson.lesson1.FragmentItem2"
    android:label="FragmentItem2" 
    tools:layout="@layout/fragment_item2"/>
</navigation>

至于Item1Item2.ktxml文件,它们现在只是一个新的片段.ktxml文件。 xml 有一个 layout 标签,.kt 文件有 databinding 连接到它。就是这样

【问题讨论】:

  • 你不能使用标准的底部导航吗?将它与导航组件挂钩非常简单

标签: android android-fragments kotlin data-binding navigation


【解决方案1】:

我建议使用这种简单且易于实现的模式: 在你的 activity_main.xml

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

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".uiHost.MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_home"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="false"
        app:layout_constraintBottom_toTopOf="@+id/bottom_nav_home"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0"
        app:navGraph="@navigation/navigation_home" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav_home"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:menu="@menu/bottom_nav_home" />


</androidx.constraintlayout.widget.ConstraintLayout>

在 MainActivity.kt 中连接底部导航的代码

val navController = childFragmentManager.findFragmentById(R.id.nav_host_home)
mBinding.bottomNavHome.setupWithNavController(navController = navController!!.findNavController())

【讨论】:

  • 不知道这是否对 OP 有帮助,但对我有帮助!
猜你喜欢
  • 2022-01-16
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 2020-04-19
  • 2021-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多