首页 > 解决方案 > Android - 根据活动主机方向添加不同的片段

问题描述

我从一周没有成功就面临这个问题。我正在尝试加载两个不同的片段:PortraitTestFrag.java并且LandscapeTestFrag.java取决于Activity主机方向。

这些在/layout/activity_main.xml和/layout-land/activity_main.xmlFragments中加载,如下所示:

     <fragment
    android:id="@+id/navigationContainerFragment"      
    android:name="class name#"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

我想要的是当我的Activity主机是肖像时,PortraitTestFrag加载并显示。当我Activity是风景时,LandscapeTestFrag应该加载并显示。

问题是PortraitTestFrag在启动时可见但是当设备旋转时LandscapeTestFrag永远不会显示甚至Activity被破坏和重新创建。似乎第一个加载Fragment的优先级。

可能是什么问题呢?

标签: android

解决方案


我不建议您至少在方向更改时替换片段,因为您将丢失保存到捆绑包或持久保存在 ViewModel/Presenter/etc 中的数据。
使用 DI 或结构来更改片段内部特定方向逻辑的实现可能会更好。
如果你真的想改变整个片段,你可以创建一个代理片段来管理切换逻辑:

abstract class BaseSwitchFragment : Fragment() {

    companion object {
        private const val KEY_ORIENTATION = "ORIENTATION"
        private const val CHILD_TAG = "CHILD_TAG"
    }

    private var prevOrientation: Int? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_switch, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        prevOrientation = savedInstanceState?.getInt(BaseSwitchFragment.KEY_ORIENTATION)

        if (prevOrientation != resources.configuration.orientation) {
            childFragmentManager.beginTransaction()
                    .replace(R.id.fragmentContainer, buildFragment(), CHILD_TAG)
                    .commit()
        }

        prevOrientation = resources.configuration.orientation

        super.onViewCreated(view, savedInstanceState)
    }

    override fun onSaveInstanceState(outState: Bundle) {
        outState.putInt(KEY_ORIENTATION, resources.configuration.orientation)
        super.onSaveInstanceState(outState)
    }

    private fun buildFragment(): Fragment {
        if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
            return buildPortraitFragment()
        } else {
            return buildLandscapeFragment()
        }
    }

    protected abstract fun buildPortraitFragment(): Fragment

    protected abstract fun buildLandscapeFragment(): Fragment

}

我没有测试过这段代码,但它应该可以工作。此外,我相信可以优化此代码以防止重新创建子片段(如果要删除它)。


推荐阅读