[英]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.