![](/img/trans.png)
[英]How can I use deep link with animation in Android Navigation Component
[英]How can I link two fragments with Android Navigation component?
我正在使用帶有底部導航欄的 Android Jetpack 的導航組件,如下所示:
讓我們關注 Home 和 Dashboard 目的地,Dashboard 顯示部門列表,每個部門顯示產品列表,每個產品顯示詳細描述。 到目前為止一切正常。
但是Home 應該直接顯示完整的產品列表,這里有一個問題:如何在應用程序啟動時(以及每次訪問 Home 時)直接在 Home 上顯示product_list
片段?
請注意,我不能將product_list
代碼直接放入 Home 片段,因為從儀表板導航將 go 到 Home。
另外,如果我將findNavController().navigate(HomeFragmentDirections.nextAction())
放在主頁片段onCreateView(...)
上,每次我 go 到主頁時,它都會顯示產品列表,而且還會顯示應用欄上的向上按鈕,它不會去任何地方(它會轉到再次重定向到product_list
的 Home)。
通過儀表板上的部門列表訪問product_list
時,我只需要向上按鈕。 product_list
應該顯示在 Home 上,就好像它是 Home 本身一樣。
因此,我正在尋找一種方法來直接鏈接這兩個片段,無需任何事務,或者避免應用程序欄上的向上按鈕(可能通過避免將事務添加到事務返回堆棧)。
<?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/bottom_nav"
app:startDestination="@+id/navigation_home">
<fragment
android:id="@+id/navigation_home"
android:name="cu.lcnicolau.ui.home.HomeFragment"
android:label="@string/title_home"
tools:layout="@layout/fragment_home">
<action
android:id="@+id/next_action"
app:destination="@id/product_list">
<argument
android:name="departmentId"
android:defaultValue="0" />
</action>
</fragment>
<fragment
android:id="@+id/navigation_departments"
android:name="cu.lcnicolau.ui.departments.DepartmentsFragment"
android:label="@string/title_departments"
tools:layout="@layout/fragment_departments">
<action
android:id="@+id/next_action"
app:destination="@id/product_list" />
</fragment>
<fragment
android:id="@+id/product_list"
android:name="cu.lcnicolau.ui.products.ItemListFragment"
android:label="@string/title_products"
tools:layout="@layout/item_list">
<action
android:id="@+id/next_action"
app:destination="@id/product_detail" />
<argument
android:name="departmentId"
app:argType="integer" />
</fragment>
<fragment
android:id="@+id/product_detail"
android:name="cu.lcnicolau.ui.products.ItemDetailFragment"
android:label="@string/title_product_detail"
tools:layout="@layout/item_detail">
<argument
android:name="item"
app:argType="cu.lcnicolau.dummy.Product" />
</fragment>
</navigation>
這種方式可能會滿足您的需求:
1.設置bottom_nav
創建可在導航圖中的任何位置使用的全局操作。 DepartmentsFragment
將使用它導航到ItemListFragment
。
在navigation_home
中創建操作。 這里的重要屬性是app:popUpTo="@+id/bottom_nav
(你的圖 id),當從其他 Fragment 調用 onBackPressed 時,它將從 backstack 中刪除 HomeFragment 並影響到 BottomNavigationView。我們將使用 ActivityCallback 來解決這個問題。
<?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/bottom_nav" app:startDestination="@+id/navigation_home"> <action android:id="@+id/to_product_list" app:destination="@id/product_list" /> <fragment android:id="@+id/navigation_home" android:name="com.example.stackoverflowhelps.ui.home.HomeFragment" android:label="@string/title_home" tools:layout="@layout/fragment_home"> <action android:id="@+id/home_to_product_list" app:destination="@id/product_list" app:popUpTo="@+id/bottom_nav" /> </fragment> <fragment android:id="@+id/product_list" android:name="com.example.stackoverflowhelps.ui.products.ProductsFragment" android:label="@string/title_products" tools:layout="@layout/fragment_products" > <argument android:name="departmentId" app:argType="long" /> </fragment>... </navigation>
DepartmentsFragment
調用全局操作 findNavController().navigate(toProductList(departementId))
HomeFragment
初始回調中的任何位置 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) findNavController().navigate(homeToProductList(-1)) }
2.設置MainActivity和NavCallback
此回調的目的是在從其他兩個底部菜單 onBackPressed 時將 BottomNavigationView 導航到 Home。 由於我們在后台堆棧中丟失了 HomeFragment,因此我們每次從 Home 輸入 ItemListFragment。
NavCallback.java
interface NavCallback { enum class Nav { HOME, DASHBOARD, OFFERS } fun navigateToMenu(nav: Nav) }
MainActivity.java
class MainActivity: AppCompatActivity(), NavCallback { private lateinit var navView: BottomNavigationView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) navView = findViewById(R.id.nav_view) val navController = findNavController(R.id.nav_host_fragment) // optional: if you want to permanently remove default ActionBar BackButton from ItemListFragment, add product_list navigation id to appBarConfiguration val appBarConfiguration = AppBarConfiguration( setOf( R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_offers, R.id.product_list ) ) setupActionBarWithNavController(navController, appBarConfiguration) navView.setupWithNavController(navController) } override fun navigateToMenu(nav: NavCallback.Nav) { val dest: Int = when(nav) { NavCallback.Nav.HOME -> R.id.navigation_home NavCallback.Nav.DASHBOARD -> R.id.navigation_home NavCallback.Nav.OFFERS -> R.id.navigation_notifications } navView.selectedItemId = dest } }
在DepartmentsFragment
和OffersFragment
NavCallback
我們將手動將 select 底部導航菜單轉到 Home,請參閱NavCallback.Nav.HOME
class DepartmentsFragment: Fragment() { private var navCallback: NavCallback? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val callback = object: OnBackPressedCallback(true) { override fun handleOnBackPressed() { navCallback?.navigateToMenu(NavCallback.Nav.HOME) } } requireActivity().onBackPressedDispatcher.addCallback(this, callback) } override fun onAttach(context: Context) { super.onAttach(context) try { navCallback = context as NavCallback } catch (e: ClassCastException) { activity.toString() + " must implements NavCallback" } } override fun onDetach() { navCallback = null super.onDetach() }... }
到這里為止,我們已經得到了想要的 UI 流程。
3、確定ItemListFragment
中的Product List數據和Back Button的可見性
出於方便的原因,我更喜歡使用自定義工具欄視圖和后退按鈕。 這時候我們將使用參數departmentId
來確定返回按鈕的可見性
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val departmentId: Long = arguments?.getLong("departmentId")?: 0 if (departmentId > 0) { textView.text = departmentId.toString() back.visibility = View.VISIBLE back.setOnClickListener { requireActivity().onBackPressed() } // from fetch the data with given id } else { back.visibility = View.GONE // come from HomeFragment, fetch all data } }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.