Android Primary/Detail Flow 模板的 fragment 点击跳转逻辑

更新日期: 2022-11-10 阅读次数: 213 字数: 408 分类: Android


  • 看懂原有 primary/detail 模板的跳转逻辑
  • 新建 snippet

list fragment

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val itemDetailFragmentContainer: View? = view.findViewById(
    setupRecyclerView(recyclerView, itemDetailFragmentContainer)

private fun setupRecyclerView(
    recyclerView: RecyclerView,
    itemDetailFragmentContainer: View?
) {
    recyclerView.adapter = SimpleItemRecyclerViewAdapter(
        PlaceholderContent.ITEMS, itemDetailFragmentContainer

但是这个 item_detail_nav_container 只存在于 sw600dp 的 layout 文件中:

> grep item_detail_nav_container -r app/
app/src/main/res/layout-sw600dp/fragment_item_list.xml:        android:id="@+id/item_detail_nav_container"


recycler view adapter

class SimpleItemRecyclerViewAdapter(
        private val values: List<PlaceholderContent.PlaceholderItem>,
        private val itemDetailFragmentContainer: View?
) :
    RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder>() {
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = values[position]
        holder.idView.text =
        holder.contentView.text = item.content

        with(holder.itemView) {
            tag = item
            setOnClickListener { itemView ->
                val item = itemView.tag as PlaceholderContent.PlaceholderItem
                // Bundle: A mapping from String keys to various Parcelable values.
                // A Bundle is very much like a Java Map object that maps String keys to values.
                // The reason Android doesn't use plain old Map objects for this is that Map is too flexible;
                // it can contain objects (such as, say, I/O streams) that cannot be serialized.
                // The Bundle API restricts the types of objects that can be added to a bundle
                // in such a way that the bundle's contents are guaranteed to be serializable.
                // The Android framework relies on this property.
                val bundle = Bundle()
                if (itemDetailFragmentContainer != null) {
                        .navigate(, bundle)
                } else {
                    // 为何不都使用这个逻辑呢?
                    // 实际测试也确实没有问题
                    itemView.findNavController().navigate(, bundle)

show_item_detail 的定义:

> grep show_item_detail -r app/
app/src/main/res/navigation/primary_details_nav_graph.xml:            android:id="@+id/show_item_detail"

        app:destination="@id/item_detail_fragment" />

detail fragment

override fun onCreate(savedInstanceState: Bundle?) {

    // public final android.os.Bundle getArguments()
    // Return the arguments supplied when the fragment was instantiated, if any.
    arguments?.let {
        if (it.containsKey(ARG_ITEM_ID)) {
            // Load the placeholder content specified by the fragment
            // arguments. In a real-world scenario, use a Loader
            // to load content from a content provider.
            item = PlaceholderContent.ITEM_MAP[it.getString(ARG_ITEM_ID)]


override fun onCreate(savedInstanceState: Bundle?) {
    val navHostFragment =
        supportFragmentManager.findFragmentById( as NavHostFragment
    val navController = navHostFragment.navController
    appBarConfiguration = AppBarConfiguration(navController.graph)
    setupActionBarWithNavController(navController, appBarConfiguration)