Androidのフルスクリーンと没入型ディスプレイ

アプリの開発では、より良い視覚効果を提供するために、フルスクリーン表示と没入型表示の両方が一般的です。私の過去の開発経験では、これを実現するために、通常、サードパーティのライブラリであるImmersionBarを使用しています。今日は、公式APIを使って実装する方法を紹介します。

没入型ディスプレイ

没入型の表示とは、ステータスバーを引き続き表示できることを意味しますが、ステータスバーの背景は透明であり、アプリのUIから明確に分離されていません。

非没入型画像:

no_full_screen.png

没入型コードは次のように実装されます。

//修改全局主题中statusBarColor和navigationBarColor为透明
<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.ExampleDemo" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:navigationBarColor">@android:color/transparent</item>
        <!-- Customize your theme here. -->
    </style>
</resources>

class ImmersionActivity : AppCompatActivity() {

    private lateinit var windowInsetsController: WindowInsetsControllerCompat

    lateinit var binding: LayoutImmersionActivityBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.layout_immersion_activity)

        WindowCompat.setDecorFitsSystemWindows(window, false)
        windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
        windowInsetsController.isAppearanceLightNavigationBars = false

        binding.btnChangeToLightBar.setOnClickListener {
            //顶部布局为亮色
            lightBar()
        }

        binding.btnChangeToDarkBar.setOnClickListener {
            //顶部布局为深色
            darkBar()
        }
    }

    private fun lightBar() {
        binding.topView.setBackgroundColor(ContextCompat.getColor(this, R.color.white))
        binding.tvTitle.setTextColor(ContextCompat.getColor(this, R.color.black))
        setBarStatus(true)
    }

    private fun darkBar() {
        binding.topView.setBackgroundColor(ContextCompat.getColor(this, R.color.color_23242a))
        binding.tvTitle.setTextColor(ContextCompat.getColor(this, R.color.white))
        setBarStatus(false)
    }

    //改变状态栏文字和图标的颜色(根据顶部布局的背景色来决定)
    private fun setBarStatus(light: Boolean) {
        windowInsetsController.isAppearanceLightStatusBars = light
    }
}

効果は図のようになります。

1e9c7603289e48be8c4b52997b25e525_.gif

間隔を設定する

アプリの上部にあるタイトルとステータスバーが非常に小さいことがわかります。これは私が望む効果とは異なり、下部のドットコントロールも透明なナビゲーションバーによってブロックされています。オフィシャルは、これらの状況に対処するための対応するAPIを提供します。

コードは次のように表示されます。

//重复的部分省略了
class ImmersionActivity : AppCompatActivity() {
    ...
    private var hadChange = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...

        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
            //此回调会触发多次,所以用布尔值来控制仅触发一次
            if (!hadChange) {
                hadChange = true
                val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
                //状态栏高度
                val statusBarHeight = insets.top
                //调整顶部控件的高度
                binding.topView.run {
                    updateLayoutParams<ConstraintLayout.LayoutParams> {
                        height += statusBarHeight
                    }
                    updatePadding(top = paddingTop + statusBarHeight)
                }
                binding.tvTitle.run {
                    updateLayoutParams<ConstraintLayout.LayoutParams> {
                        topMargin += statusBarHeight
                    }
                }

                //导航栏高度
                val navigationBarHeight = insets.bottom
                //调整圆点控件不被导航栏遮挡
                binding.bottomView.run {
                    updateLayoutParams<ConstraintLayout.LayoutParams> {
                        bottomMargin += navigationBarHeight
                    }
                }
            }
            WindowInsetsCompat.CONSUMED
        }
        ...
    }
    ...
}

効果は図のようになります。

スクリーンショット_20220716_111503.png

フルスクリーンディスプレイ

フルスクリーン表示とは、ステータスバーとナビゲーションバーを非表示にすることを意味します。最新の公式APIは非常にシンプルです。

コードは次のように表示されます。

class FullScreenActivity : AppCompatActivity() {

    lateinit var binding: LayoutFullScreenActivityBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.layout_full_screen_activity)
        
        val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
        //控制系统栏的行为
        windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
    }
}

注:systemBarsBehaviorユーザーの動作を制御するために使用されるシステムバーへの変更には、次の3つのタイプがあります。

  • WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH
  • WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE
  • WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE

BEHAVIOR_SHOW_BARS_BY_TOUCHとBEHAVIOR_SHOW_BARS_BY_SWIPEはどちらもタッチまたはスワイプで表示されるため、表示後にシステムバーが自動的に非表示になることはありません。効果は次のとおりです。

22c78146cb8ec9e453add4b805029574_.gif

BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPEは、システムバーを表示するタッチまたはスライドとして表示され、短時間で自動的に非表示になります。効果は次のとおりです。

3275d5d9ae9de444422a627b9451995a_.gif

おすすめ

転載: juejin.im/post/7120815750880690190