Android Primary Detail Flow 模板

更新日期: 2022-10-28 阅读次数: 1774 字数: 469 分类: Android

想实现一个 Android APP 扫描附近 BLE 蓝牙设备,并显示其服务、特性 UUID,及对应 Handle,CCCD。 尽量能自动化,并加快目前一个项目中用到的蓝牙网关配对的过程。

界面展示类似于列表加详情页的形式,恰好 Android Studio 里内置了这种模板,即 Primary/Detail Flow。

里面的列表页与详情页是用两个独立的 Fragment 实现的。

入口在哪里

因为 Fragment 并不能单独使用,他需要嵌套在 Activity 中使用。

> tree app/src/main/java/com/sunzhongwei/ble/
app/src/main/java/com/sunzhongwei/ble/
├── ItemDetailFragment.kt       // 详情页
├── ItemDetailHostActivity.kt   // 主 Activity
├── ItemListFragment.kt         // 列表页
└── placeholder
    └── PlaceholderContent.kt   // 填充用的测试数据

1 directory, 4 files

猜测是 ItemDetailHostActivity.kt,但是这个文件名有极大的歧义,所以我不是很确定。

实际上在 AndroidManifest.xml 中就能看到入口的 Activity。

<activity
		android:name=".ItemDetailHostActivity"
		android:exported="true"
		android:label="@string/app_name"
		android:resizeableActivity="true"
		tools:targetApi="24">
		<intent-filter>
				<action android:name="android.intent.action.MAIN" />

				<category android:name="android.intent.category.LAUNCHER" />
		</intent-filter>

		<meta-data
				android:name="android.app.lib_name"
				android:value="" />
</activity>

填充的测试数据在哪里

placeholder/PlaceholderContent.kt

object PlaceholderContent {
    val ITEMS: MutableList<PlaceholderItem> = ArrayList()
    val ITEM_MAP: MutableMap<String, PlaceholderItem> = HashMap()

    private val COUNT = 25

    init {
        // Add some sample items.
        for (i in 1..COUNT) {
            addItem(createPlaceholderItem(i))
        }
    }

    private fun addItem(item: PlaceholderItem) {
        ITEMS.add(item)
        ITEM_MAP.put(item.id, item)
    }

    private fun createPlaceholderItem(position: Int): PlaceholderItem {
        return PlaceholderItem(position.toString(), "Item " + position, makeDetails(position))
    }

    private fun makeDetails(position: Int): String {
    }

    data class PlaceholderItem(val id: String, val content: String, val details: String) {
        override fun toString(): String = content
    }
}

tips:kotlin 中 object 与 class 的区别

navigation router 在哪里

activity layout xml 中有个:

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/nav_host_fragment_item_detail"
    android:name="androidx.navigation.fragment.NavHostFragment"
    app:defaultNavHost="true"
    app:navGraph="@navigation/primary_details_nav_graph"
    tools:layout="@layout/fragment_item_detail" />

FragmentContainerView 用来切换 list 与 detail fragment。

  • FragmentContainerView 使用 android:name 指定的名字创建一个 Fragment。
  • app:navGraph 指向了 graph。这里面就是 router 逻辑。

而不需要切换的则如下面这种布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">
    <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list" />
    <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer" />
</LinearLayout>

activity 中的逻辑:

val navHostFragment =
    supportFragmentManager.findFragmentById(R.id.nav_host_fragment_item_detail) as NavHostFragment
val navController = navHostFragment.navController
appBarConfiguration = AppBarConfiguration(navController.graph)
setupActionBarWithNavController(navController, appBarConfiguration)

tips: 其他内容可以参考之前整理的 Android Navigation 组件

参考

  • https://developer.android.com/reference/androidx/fragment/app/FragmentContainerView

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式