知識(shí)
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X(jué)表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營(yíng)銷(xiāo)的便利,運(yùn)營(yíng)的高效,讓網(wǎng)站成為營(yíng)銷(xiāo)工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!
自定義Navigator切換fragment
發(fā)表時(shí)間:2020-10-18
發(fā)布人:葵宇科技
瀏覽次數(shù):123
使用場(chǎng)景:
使用Navigation完成fragment間的跳轉(zhuǎn)操作。
問(wèn)題描述:
Navigation 實(shí)現(xiàn) fragment 間的跳轉(zhuǎn)用的是replace()方法,此方法會(huì)移除原來(lái)的fragment,再添加新的fragment,所以回到上一個(gè)fragment時(shí)就需要重新走一遍生命周期流程,重新加載數(shù)據(jù)。
解決方案:
分析 NavController類(lèi) 中的navigate 源碼
private void navigate(@NonNull NavDestination node, @Nullable Bundle args,
@Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
...
Navigator<NavDestination> navigator = mNavigatorProvider.getNavigator(
node.getNavigatorName()); 根據(jù)節(jié)點(diǎn)名稱(chēng)生成不同的navigator
Bundle finalArgs = node.addInDefaultArgs(args);
NavDestination newDest = navigator.navigate(node, finalArgs,
navOptions, navigatorExtras); 調(diào)用navigator 中的 navigate方法
...
}
getNavigator 源碼如下
private final HashMap<String, Navigator<? extends NavDestination>> mNavigators =
new HashMap<>();
public <T extends Navigator<?>> T getNavigator(@NonNull String name) {
if (!validateName(name)) {
throw new IllegalArgumentException("navigator name cannot be an empty string");
}
Navigator<? extends NavDestination> navigator = mNavigators.get(name); // 根據(jù)傳入的node獲取不同的navigator
if (navigator == null) {
throw new IllegalStateException("Could not find Navigator with name \"" + name
+ "\". You must call NavController.addNavigator() for each navigation type.");
}
return (T) navigator;
}
因此,想要調(diào)用自定義navigate()方法就需要 自定義一個(gè)Navigator類(lèi),同時(shí)改變fragment節(jié)點(diǎn)名稱(chēng),將fragment節(jié)點(diǎn)名稱(chēng)與Navigator類(lèi)作為key,value 添加到 HashMap類(lèi)型的mNavigators中。
自定義Navigator
@Navigator.Name("custom_fragment") // 節(jié)點(diǎn)名稱(chēng)定義為custom_fragment,作為 mNavigatorProvider 變量的 key
class CustomNavigator( //作為 mNavigatorProvider 變量的 value
private val context: Context,
private val manager: FragmentManager,
private val containerId: Int
) : FragmentNavigator(context, manager, containerId) {
override fun navigate( // 重寫(xiě) navigate 方法
destination: Destination,
args: Bundle?,
navOptions: NavOptions?,
navigatorExtras: Navigator.Extras?
): NavDestination? {
val tag = destination.id.toString() // 跳轉(zhuǎn)目的地
val transaction = manager.beginTransaction() // 開(kāi)啟fragment事務(wù)
val currentFragment = manager.primaryNavigationFragment // navigation 頂層fragment
if (currentFragment != null) {
transaction.hide(currentFragment) // 隱藏當(dāng)前fragment
}
var fragment = manager.findFragmentByTag(tag) // 找到目的地fragment
if (fragment == null) { // fragment未被初始化
val className = destination.className
fragment = manager.fragmentFactory.instantiate(context.classLoader, className) // 實(shí)例化 fragment
transaction.add(containerId, fragment, tag) // 將碎片添加到容器中
} else { // fragment 已經(jīng)初始化過(guò)了
transaction.show(fragment) // 顯示fragment
}
transaction.setPrimaryNavigationFragment(fragment) //將fragment 設(shè)置為頂層fragment
transaction.setReorderingAllowed(true)
transaction.commitNow() // 提交事務(wù)
return destination // 返回目的地,用于監(jiān)聽(tīng)
}
}
修改節(jié)點(diǎn)名稱(chēng)
因?yàn)楣?jié)點(diǎn)名稱(chēng)定義為custom_fragment,所以修改為<custom_fragment>
<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/my_nav"
app:startDestination="@id/home_dest"
tools:ignore="UnusedNavigation">
<custom_fragment
android:id="@+id/home_dest"
android:name="com.cl.androidstudy.ui.home.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" />
<custom_fragment
android:id="@+id/system_dest"
android:name="com.cl.navicationtest.SystemFragment"
android:label="fragment_system"
tools:layout="@layout/fragment_system" />
<custom_fragment
android:id="@+id/square_dest"
android:name="com.cl.navicationtest.SquareFragment"
android:label="fragment_square"
tools:layout="@layout/fragment_square" />
<custom_fragment
android:id="@+id/me_dest"
android:name="com.cl.androidstudy.ui.me.MeFragment"
android:label="fragment_me"
tools:layout="@layout/fragment_me" />
</navigation>
邏輯代碼
val navController = Navigation.findNavController(this, R.id.fragment) // 創(chuàng)建navController
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment)!!
val navigator = CustomNavigator(
this,
navHostFragment.childFragmentManager,
R.id.fragment
)// 生成自定義Navigator對(duì)象
navController.navigatorProvider.addNavigator("custom_fragment", navigator) // 添加 key, value
navController.setGraph(R.navigation.my_nav) // 要在 CustomNavigator 類(lèi)被加載之后添加graph,不然找不到 custom_fragment節(jié)點(diǎn)
參考博客: https://juejin.im/post/6844903896104747022#heading-2
相關(guān)案例查看更多
相關(guān)閱讀
- 小程序設(shè)計(jì)
- 汽車(chē)報(bào)廢回收管理軟件
- 網(wǎng)站開(kāi)發(fā)公司哪家好
- 昆明網(wǎng)絡(luò)公司
- 汽車(chē)回收管理
- 云南網(wǎng)站建設(shè)費(fèi)用
- 云南網(wǎng)站建設(shè)案例
- 云南建設(shè)廳網(wǎng)站首頁(yè)
- 小程序的開(kāi)發(fā)公司
- 跳轉(zhuǎn)小程序
- 小程序用戶(hù)登錄
- 網(wǎng)絡(luò)公司排名
- 前端技術(shù)
- 百度排名
- 網(wǎng)站建設(shè)專(zhuān)業(yè)品牌
- 云南省建設(shè)廳網(wǎng)站
- 云南網(wǎng)站建設(shè)報(bào)價(jià)
- 云南網(wǎng)站建設(shè) 網(wǎng)絡(luò)服務(wù)
- 人人商城
- 昆明小程序開(kāi)發(fā)
- 網(wǎng)站制作
- 云南網(wǎng)站建設(shè)快速優(yōu)化
- 小程序
- 文山小程序開(kāi)發(fā)
- 百度推廣
- 云南小程序被騙
- 網(wǎng)頁(yè)制作
- 小程序開(kāi)發(fā)費(fèi)用
- 汽車(chē)報(bào)廢回收
- 汽車(chē)報(bào)廢回收管理系統(tǒng)