Android navigasyon ve durum çubuğunu (navigation and status bar, system bars) şeffaf yapmak

Display content edge-to-edge in your app dökümanına göre uygulama arayüzünü sistem çubuklarının(system bars: navigation bar, status bar) arkasına geçirebilmek için şu kodu kullanıyoruz:

WindowCompat.setDecorFitsSystemWindows(window, false)

Ben bunu Activity'de değil Fragment'ta yapıyorum. O yüzden window'u Fragment içinde şu şekilde alabiliriz:

WindowCompat.setDecorFitsSystemWindows(requireActivity().window, false)

Dökümantasyonda bu kodun onCreate() içine yazılması tavsiye edilmiş.

Sistem barlarını şeffaf yapmak için themes.xml dosyalarında bunları ekliyoruz:

<!-- values-v29/themes.xml -->
<style name="Theme.MyApp">
  <item name="android:navigationBarColor">@android:color/transparent</item>

  <!-- Optional: set to transparent if your app is drawing behind the status bar. -->
  <item name="android:statusBarColor">@android:color/transparent</item>

  <!-- Optional: set the status bar light and content dark. -->
  <item name="android:windowLightStatusBar">true</item>
</style>

Artık layout tüm ekranı kaplıyor. Barlarımız da şeffaf. Fakat barların arkasına geçmesini istemediğimiz bazı arayüz öğeleri olabilir. Örneğin:

Büyütmek için tıklayın

Bu bir CardView içerisinde TextView. Benim şuan geliştirdiğim uygulamamın giriş ekranı FrameLayout'tan oluşuyor ve bu ekranda bütün arkaplanı bir ImageView kaplıyor. Haliyle ben bu arkaplanın sistem barlarının arkasına geçmesini fakat diğer öğelerin geçmemesini istiyorum. Bunun için inset ayarı yapılıyor. Dökümantasyondaki kod:

ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets ->
  val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
  view.updateLayoutParams<MarginLayoutParams>(
      leftMargin = insets.left,
      bottomMargin = insets.bottom,
      rightMargin = insets.right,
  )

  WindowInsetsCompat.CONSUMED
}

Buradaki püf nokta, view parametresi olarak barların arkasına geçmesini istemediğimiz herhangi bir arayüz elemanı veya layout yazabiliriz. Burada yaptığımız şey aslında margin ayarlamak. Ben sadece ekran görüntüsündeki owner yazan içinde TextView bulunduran CardView'ın, navigasyon çubuğunun arkasına geçmesini istemiyorum ve view binding kullanıyorum, bu yüzden kodu şu şekilde yazıyorum:

ViewCompat.setOnApplyWindowInsetsListener(binding.ownerIdTextCardView, OnApplyWindowInsetsListener { view, windowInsets ->
            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())

            view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
                bottomMargin = insets.bottom
            }

            WindowInsetsCompat.CONSUMED
        })
Büyütmek için tıklayın

Inset ayarının yapıldığı bu son kod, view binding kullandığım için binding initialization gerçekleştikten sonra çalıştırılabilir. Yani bu kodu pratik olması açısından setDecorToFitSystemWindow() adında yeni bir fonksiyon içine alıp onCreateView() içinde çalıştırabilirim:

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentSearchScreenBinding.inflate(inflater, container, false)
        setDecorToFitSystemWindow()
        return binding.root
    }


Yorumlar