繁体   English   中英

我如何在嵌套 Fragments.Kotlin 中使用导航(NavHost)

[英]how I can use Navigation (NavHost) in Nested Fragments .Kotlin

我尝试从Fragment1(TransformFragment)打开Fragment2在 RrecyclerView 中抛出单击项。我尝试使用Navigation (NavHost)来解决这个问题Fragment1 代码如下::

class TransformFragment : Fragment(){

private lateinit var transformViewModel: TransformViewModel
private var _binding: FragmentTransformBinding? = null

// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    transformViewModel = ViewModelProvider(this)[TransformViewModel::class.java]
    _binding = FragmentTransformBinding.inflate(inflater, container, false)
    val root: View = binding.root

    val recyclerView = binding.recyclerviewTransform

    val adapter = TransformAdapter()
    recyclerView.adapter = adapter
    transformViewModel.texts.observe(viewLifecycleOwner) {
        adapter.submitList(it)
    }

    return root
}


override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

class TransformAdapter() :
    ListAdapter<String, TransformViewHolder>(object : DiffUtil.ItemCallback<String>() {

        override fun areItemsTheSame(oldItem: String, newItem: String): Boolean =
            oldItem == newItem

        override fun areContentsTheSame(oldItem: String, newItem: String): Boolean =
            oldItem == newItem
    }) {

    private val drawables = listOf(
        R.drawable.avatar_1,
        R.drawable.avatar_2,
        R.drawable.avatar_3,
        R.drawable.avatar_4,
        R.drawable.avatar_5,
        R.drawable.avatar_6,
        R.drawable.avatar_7,
        R.drawable.avatar_8,
        R.drawable.avatar_9,
        R.drawable.avatar_10,
        R.drawable.avatar_11,
        R.drawable.avatar_12,
        R.drawable.avatar_13,
        R.drawable.avatar_14,
        R.drawable.avatar_15,
        R.drawable.avatar_16,
        R.drawable.avatar_17,
    )

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransformViewHolder {
        val binding = ItemTransformBinding.inflate(LayoutInflater.from(parent.context))
        return TransformViewHolder(binding)
    }

    override fun onBindViewHolder(holder: TransformViewHolder, position: Int) {
        holder.textView.text = getItem(position)
        holder.imageView.setImageDrawable(
            ResourcesCompat.getDrawable(holder.imageView.resources, drawables[position], null)
        )

        holder.itemView.setOnClickListener {

          // my navigation(NavHost) code 

        }


    }

}

class TransformViewHolder(binding: ItemTransformBinding) :
    RecyclerView.ViewHolder(binding.root) {

    val imageView: ImageView = binding.imageViewItemTransform
    val textView: TextView = binding.textViewItemTransform
}

}

我尝试使用这个

val navController = findNavController(R.id.nav_host_fragment_content_main)
navController.navigate(R.id.nav_detail)

nav_detail导航Fragment2

和我的片段容器::这是我的 XML .. 我知道要显示动态片段,您必须使用FrameLayout ,但它会出错..但是片段容器可以

<LinearLayout 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"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/app_bar_main">

<fragment
    android:id="@+id/nav_host_fragment_content_main"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginLeft="@dimen/fragment_horizontal_margin"
    android:layout_marginRight="@dimen/fragment_horizontal_margin"
    android:layout_weight="1"
    app:defaultNavHost="true"
    app:navGraph="@navigation/mobile_navigation" />

<!--
<FrameLayout
    android:id="@+id/nav_host_fragment_content_main"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginLeft="@dimen/fragment_horizontal_margin"
    android:layout_marginRight="@dimen/fragment_horizontal_margin"
    android:layout_weight="1"
    app:defaultNavHost="true"
    app:navGraph="@navigation/mobile_navigation" />
    -->

提前致谢

要使用 findNavController() 在片段之间导航,您必须先确保已正确设置活动。

所以在你的activity layout中首先添加container,parent需要自己是FrameLayout,我会在下面使用ConstraintLayout。

activity_main.xml:

<?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=".MainActivity">

<!--    We declare attribute id to hook with MainActivity.java class-->
<!--    Attribute name will change behavior of simple fragment to NavHostFragment-->
<!--    Keep width and height to match_parent so that all our fragments take whole space-->
<!--    We change this NavHost to behave default NavHost-->
<!--    Attach our app navigation graph to this NavHostFragment-->
    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>

现在让我们将容器作为活动的代理主机。

MainActivity.kt:

class MainActivity : AppCompatActivity() {

    lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // NavigationController to set default NavHost as nav_host_fragment.
        navController = Navigation.findNavController(this, R.id.nav_host_fragment)
        NavigationUI.setupActionBarWithNavController(this, navController)
    }

    override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp()
    }
}

onSupportNavigateUp function 帮助您导航回上一个片段上触发的动作或在任何视图上使用navigateUp()专门调用

现在您要从 Fragment1 -> Fragment2 导航。

  1. 确保您已将两个片段添加到导航图中。

  2. 通过动作将第一个片段连接到第二个片段。

  3. 跟踪目的地 ID 以调用正确的 ID。

     <fragment android:id="@+id/firstFragment" android:name=".FirstFragment" android:label="FirstFragment" tools:layout="@layout/fragment_first"> <action android:id="@+id/action_first_fragment_to_second_fragment" app:destination="@id/secondFragment" /> </fragment> <fragment android:id="@+id/secondFragment" android:name=".SecondFragment" android:label="Authors" tools:layout="@layout/fragment_second" />

现在终于一旦触发动作,在 controller 上调用具有如下 ID 的动作。

yourListItemView.setOnClickListener {
    findNavController(R.id.action_first_fragment_to_second_fragment)
}

就是这样。

请检查文档,它有很好的信息。

https://developer.android.com/guide/navigation/navigation-getting-started

我在Android 开发人员文档中找到了正确答案。

holder.itemView.setOnClickListener {

            it.findNavController().navigate(R.id.nav_detail)

        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM