替换,添加,替换片段,然后导航后退按钮不适用于第一个片段

时间:2018-02-23 04:13:12

标签: android android-fragments

我有一个片段堆栈,我在其中使用replace和add。代码(在我的活动中)添加或替换我的片段如下

private fun addFragment(fragment: Fragment, name: String) {
    supportFragmentManager.beginTransaction().add(R.id.container, fragment)
            .addToBackStack(name).commit()
}

private fun replaceFragment(fragment: Fragment, name: String) {
    supportFragmentManager.beginTransaction().replace(R.id.container, fragment)
            .addToBackStack(name).commit()
}

在我的片段中,我有一个带有主菜单背面图标的工具栏。单击后,它应该有助于将我的片段弹出到上一个堆栈。

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    toolbar_actionbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp)
    setHasOptionsMenu(true)
    (activity as AppCompatActivity).setSupportActionBar(toolbar_actionbar)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return if (item.itemId == android.R.id.home) {
        activity?.onBackPressed()
        true
    } else {
        super.onOptionsItemSelected(item)
    }
}

为了清楚起见,我表示活动onBackPressed编码如下

override fun onBackPressed() {
    if (supportFragmentManager.backStackEntryCount > 0) {
        supportFragmentManager.popBackStackImmediate()
    } else {
        super.onBackPressed()
    }
}

现在如果我添加了fragment1,添加了fragment2,添加了fragment3,添加了fragment4,然后按回,向后,向后,向后......一切正常。

同样,如果我用fragment1替换,替换为fragment2,替换为fragment3,替换为fragment4,然后返回,返回,返回,返回,一切正常。

但是,如果我这样做,用片段1替换,添加片段2,并用片段3替换,然后按回,向后,向后......第三次按回不再有效。为什么?

为了更好地说明这一点,我将代码放在github中,如下所示 https://github.com/elye/issue_android_fragment_replace_add_replace

并记录下面的gif(63秒gif)显示,4添加作品,4替换作品,但替换和添加的混合,将导致工具栏后退按钮在几个后退后无法正常工作。

请注意,添加片段显示重叠数,因为背景是透明的。这样做是为了轻松区分添加与替换。

enter image description here

我怀疑这是一个谷歌错误,但我认为应该分享,以防我错过任何重要的事情。

3 个答案:

答案 0 :(得分:1)

经过调查,似乎问题如下所述。

由于每个片段都有自己的操作栏集(在此stackoverflow中,我将其简化为R.id.home单击以便更容易地说明问题)。在添加/删除片段时,每个人都会调用以下代码。

(activity as AppCompatActivity).setSupportActionBar(toolbar_actionbar)

当我们添加add-add-replace(或replace-add-replace)时....我们在backstack中有3个片段,但只有一个可见。因为最后一次替换,将删除前面的2个片段。

当我们点击后退按钮时,最后一个被替换的片段将被弹出,然后系统恢复前两个片段。

在恢复前2个片段期间,以下代码在短时间间隔内调用两个片段

(activity as AppCompatActivity).setSupportActionBar(toolbar_actionbar)

我怀疑这会导致第一个片段的工具栏未完全设置的某些行为(Android SDK错误?)。

为了解决这个问题,当我们再次弹出2个片段时,我们必须强制调用第一个片段

(作为AppCompatActivity的活动).setSupportActionBar(toolbar_actionbar)

因此我对上述问题的解决方法是将上面的代码放在onResume()中。

override fun onResume() {
    super.onResume()
    (activity as AppCompatActivity).setSupportActionBar(toolbar_actionbar)
}

每当片段后台改变时,我都会调用顶部片段的onResume

    supportFragmentManager.addOnBackStackChangedListener {
        val currentFragment = supportFragmentManager.findFragmentById(R.id.container)
        currentFragment?.onResume()
    }

现在这有助于确保无论替换添加堆栈的混合,工具栏菜单将继续工作。

我有示例解决方法代码 https://github.com/elye/issue_android_fragment_replace_add_replace_workaround

这实际上是一种解决方法而非解决方案。我希望发布更好的答案,或者如果这确实是Google Bug,可以在以后的SDK版本中对其进行修复。

答案 1 :(得分:0)

试试这个

if (supportFragmentManager.backStackEntryCount > 1) {
        supportFragmentManager.popBackStackImmediate()
    } else {
        super.onBackPressed()
    }

答案 2 :(得分:0)

您好将工具栏代码及其xml部分放入MainActivity,它是相关布局中删除 fargment 及其布局。 并输入如下代码:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        toolbar_actionbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp)
        setSupportActionBar(toolbar_actionbar)
}

将代码下载到MainActivity中以解决它。

override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return if (item.itemId == android.R.id.home) {
            if (supportFragmentManager.backStackEntryCount > 0) {
                supportFragmentManager.popBackStackImmediate()
            } else {
                super.onBackPressed()
            }
            true
        } else {
            super.onOptionsItemSelected(item)
        }
    }

我已经完成了测试和工作。希望它能帮助你。 如果您有任何疑问请在下面发表评论/留言,我会解释您并解决您的问题。