Обработчик состояния диспетчера фрагментов

Важно!

В этой статье описаны функциональные возможности общедоступной ознакомительной версии, а также инструкции по ее использованию. Сведения могут быть существенно изменены, прежде чем версия станет общедоступной. Майкрософт не дает никаких гарантий, явных или подразумеваемых, в отношении предоставленной здесь информации.

FragmentManagerStateHandler — это класс, который позволяет реализовать восстановление фрагментов при изменении режима экрана.

При переходе между режимами экрана можно столкнуться с такой проблемой: действия восстановятся, но пользовательский интерфейс будет другим.

Например:

  • Нет необходимости восстанавливать фрагмент из режима одинарного экрана при переходе в режим двойного экрана.
  • Нет необходимости восстанавливать фрагменты из режима двойного экрана при переходе в режим одинарного экрана.

Компонент автоматически определит текущий режим экрана и восстановит только нужные фрагменты в зависимости от этого режима.

Важно!

Компонент работает только с действиями из AndroidX.

Использование

class SampleApp : Application() {
    override fun onCreate() {
        super.onCreate()
        ScreenManagerProvider.init(this)
        FragmentManagerStateHandler.init(this)
    }
}
class SampleActivity : FragmentActivity(), ScreenInfoListener {
    companion object {
        private const val FRAGMENT_DUAL_START = "FragmentDualStart"
        private const val FRAGMENT_DUAL_END = "FragmentDualEnd"
        private const val FRAGMENT_SINGLE_SCREEN = "FragmentSingleScreen"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample)
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        ScreenManagerProvider.getScreenManager().onConfigurationChanged()
    }

    override fun onStart() {
        super.onStart()
        ScreenManagerProvider.getScreenManager().addScreenInfoListener(this)
    }

    override fun onPause() {
        super.onPause()
        ScreenManagerProvider.getScreenManager().removeScreenInfoListener(this)
    }

    /**
     * Called whenever the screen info was changed.
     * @param screenInfo object used to retrieve screen information
     */
    override fun onScreenInfoChanged(screenInfo: ScreenInfo) {
        when {
            screenInfo.isDualMode() -> setupDualScreenFragments()
            else -> setupSingleScreenFragments()
        }
    }

    /**
     * Adds fragments for the single screen mode
     */
    private fun setupSingleScreenFragments() {
        if (supportFragmentManager.findFragmentByTag(FRAGMENT_SINGLE_SCREEN) == null) {
            supportFragmentManager.inTransaction {
                replace(R.id.first_container_id, SingleScreenFragment(), FRAGMENT_SINGLE_SCREEN)
            }
        }
    }

    /**
     * Adds fragments for the dual screen mode
     */
    private fun setupDualScreenFragments() {
        if (supportFragmentManager.findFragmentByTag(FRAGMENT_DUAL_START) == null &&
            supportFragmentManager.findFragmentByTag(FRAGMENT_DUAL_END) == null
        ) {
            supportFragmentManager.inTransaction {
                replace(R.id.first_container_id, DualStartFragment(), FRAGMENT_DUAL_START)
            }

            supportFragmentManager.inTransaction {
                replace(R.id.second_container_id, DualEndFragment(), FRAGMENT_DUAL_END)
            }
        }
    }
}

inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> Unit) {
    val fragmentTransaction = beginTransaction()
    fragmentTransaction.func()
    fragmentTransaction.commit()
}