打开浏览器然后导航回来后 BottomNavigation 状态丢失

BottomNavigation State gets lost after opening browser and then navigating back

今天,我在我的应用程序中发现了一个非常奇怪的错误。它如下:当用户导航到“个人资料屏幕”,然后打开“信息屏幕”,然后单击“agb”时,我的应用程序打开浏览器并将用户导航到我的网站。现在奇怪的是:当用户导航回来(到“信息屏幕”,bottomnavigation 表明,他当前在主页选项卡上。再次导航回来(到“个人资料屏幕”),然后解决了这个问题。所以它去:

“个人资料屏幕”->“信息屏幕”->单击 link->“打开浏览器” -> 单击返回 -> 状态丢失 -> “信息屏幕” -> 单击返回 -> 状态恢复 -> “个人资料屏幕”。

我添加了一些显示错误的图片(红色表示状态,蓝色表示动作)

导航

  1. Profile Screen (correct state)
  2. Information Screen (correct state)
  3. Browser (Probably state destroyed now)
  4. Information Screen (state destroyed)
  5. Profile Screen (state restored)

片段(信息画面)

class UserInformationFragment : Fragment(R.layout.fragment_user_information) {
    private var _binding: FragmentUserInformationBinding? = null
    private val binding: FragmentUserInformationBinding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding  =  FragmentUserInformationBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initUserToolbar()

        with(binding) {
            agbCv.setOnClickListener { startBrowser(INTERNET_AGB) }
            dataProtectionCv.setOnClickListener { startBrowser(INTERNET_DATA_PROTECTION) }
            impressumCv.setOnClickListener { startBrowser(INTERNET_IMPRESSUM) }
        }

    }

    private fun startBrowser(url: String) {
        val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
        startActivity(browserIntent)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

我的一个想法是在用户导航回来后再次手动将状态设置为个人资料屏幕。但这将是一个真正的混乱和奇怪的事情..

导航版

navigation_version = 2.3.5

implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"

你必须使用 Deep link。

假设您有要从浏览器返回的片段一。

添加 deep link 标签,如下所示:

mobile_navigation.xml

<fragment
    android:id="@+id/fragment_one"
    android:name="one"
    android:label="one"
     >

    <deepLink
        android:id="@+id/deepLink"
        app:uri="www.Deeplinkuri.com" />
    <action
  

</fragment>

您从后端团队获得 www.Deeplinkuri.com 示例 URI 并添加到您的 fragment

你应该从服务器端询问 link。

现在当您从浏览器返回时,您可以打开自己的页面。

最简单的方法是将您最后选择的状态保存在本地静态变量中,然后 onResume() 从静态变量应用该选择状态。

companion object {
    const val LAST_SELECTED_STATE = SHOULD_BE_LAST_SELECTED_MENU_ID
}

override fun onResume() {
    yourBottomNavigation. setSelectedItemId = LAST_SELECTED_STATE
}

好的,我已经设法解决了这个问题。这个问题与打开浏览器无关,而是与我的 activity 的重新创建和我的 bottomnavigation#menu 的重新膨胀有关。在我有这个之前:

private fun setUpBottomNav(newMenu: Int) {
    with(binding.bottomNavigationView) {
        menu.clear()
        inflateMenu(newMenu)
        setupWithNavController(findNavController(R.id.fragment_container))
        // fix blinking when re selecting bottom nav item
        setOnItemReselectedListener {}
    }
}

问题是 setUpBottomNav() 在从浏览器返回到我的应用程序后被调用,因为 activity 已重新创建。新的解决方案是这样的:

private fun setUpBottomProfile(newMenu: Int) {
    val controller = (supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment).navController

    with(binding.bottomNavigationView) {
        val currentSelectedItem = selectedItemId

        menu.clear()
        inflateMenu(newMenu)

        selectedItemId = currentSelectedItem

        setupWithNavController(controller)
        // fix blinking when re selecting bottom nav item
        setOnItemReselectedListener {}
    }
}