Поделиться через


Диспетчер экрана Surface Duo

Внимание!

Этот компонент устарел и больше не поддерживается.

Чтобы получить сведения об области просмотра и функции свертывания, следует использовать Jetpack Window Manager.

В качестве альтернативы можно использовать один из этих элементов управления и макетов для двух экранов, которые могут автоматически адаптироваться к устройствам с двумя экранами и складным устройствам.

SurfaceDuoScreenManager — это общий протокол для двух разных реализаций диспетчеров экранов: первый использует библиотеку Microsoft DisplayMask, а второй — библиотеку Google WindowManager. Этот интерфейс определяет методы, которые нужно использовать для регистрации и отмены регистрации прослушивателей данных экрана.

Чтобы создать диспетчер экрана, используйте функцию ScreenManagerProvider.getScreenManager(), которая возвращает отдельный экземпляр реализации SurfaceDuoScreenManager. Перед вызовом этого метода необходимо вызвать ScreenManagerProvider.init(Application) в своей функции Application.onCreate(), чтобы инициализировать отдельный экземпляр SurfaceDuoScreenManager. Этот вызов обязательно нужно выполнить. Иначе будет создано исключение IllegalStateException("SurfaceDuoScreenManager must be initialized inside Application#onCreate()"). Если у вас есть экземпляр SurfaceDuoScreenManager, вы можете зарегистрировать обратный вызов ScreenInfoListener с помощью SurfaceDuoScreenManager.addScreenInfoListener(ScreenInfoListener?), чтобы получать оповещения об изменении режима экрана. Учитывайте, что вы можете добавить и несколько прослушивателей. Поэтому отмените их регистрацию с помощью SurfaceDuoScreenManager.removeScreenInfoListener(ScreenInfoListener?), чтобы избежать утечек памяти.

Кроме того, если вы решите обрабатывать изменения конфигурации, вызовите SurfaceDuoScreenManager.onConfigurationChanged(Configuration) из Activity. В противном случае обратный вызов не сработает.

class SampleApp : Application() {
    override fun onCreate() {
        super.onCreate()
        ScreenManagerProvider.init(this)
    }
}
class SampleActivity : AppCompatActivity(), ScreenInfoListener {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample)
    }

    override fun onScreenInfoChanged(screenInfo: ScreenInfo) {
        if (screenInfo.isDualMode()) {
            // TODO: Add dual-screen behavior.
        } else {
            // TODO: Add single-screen behavior.
        }
    }

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

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

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

Еще один вариант получения объекта ScreenInfo без необходимости регистрировать обратный вызов — использовать метод ScreenInfoProvider.getScreenInfo(Context). Учитывайте, что этот метод следует вызывать после присоединения представления к окну. Иначе некоторые методы из ScreenInfo будут возвращать значение null или создавать исключения.

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

        window?.decorView?.rootView?.let { rootView ->
            if (ViewCompat.isAttachedToWindow(rootView)) {
                val screenInfo = ScreenInfoProvider.getScreenInfo(this)
            } else {
                rootView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
                    override fun onViewAttachedToWindow(view: View) {
                        rootView.removeOnAttachStateChangeListener(this)
                        val screenInfo = ScreenInfoProvider.getScreenInfo(this)
                    }

                    override fun onViewDetachedFromWindow(view: View) {}
                })
            }
        }
    }
}

Если вы применяете библиотеку Core Ktx, используйте следующий код:

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

        window?.decorView?.rootView?.doOnAttach {
            val screenInfo = ScreenInfoProvider.getScreenInfo(this)
        }
    }
}