Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WindowInsets, the way for Android app to offer ...

WindowInsets, the way for Android app to offer edge-to-edge experience

Le Dinh Trung

February 04, 2021
Tweet

Other Decks in Programming

Transcript

  1. “The backdrop for app’s user interface and the object that

    dispatches events to views” Wi & e2e What is a window?
  2. Screen Every view on screen is in a window Layout

    Inspector Wi & e2e Window 1 (DecorView) Window 2 (DecorView) WindowManager
  3. Screen Every view on screen is in a window Layout

    Inspector Wi & e2e Window 1 (DecorView) LinearLayout … FrameLayout … ContentFrameLayout Ac#vity/Dialog’s view setContentView(view) android.R.id.content
  4. What is Insets? “How the system tells you where the

    system ui currently is, or may later be displayed”
  5. 16:58 Just avoid Status Bar at the top, and Bottom

    Navigation Bar at the bottom, quite.. ez J Status Bar Bottom Navigation Bar
  6. Wi & e2e WindowInsets is an object that contains window’s

    insets, it’s dispatched to all views in layout tree. Window Insets
  7. Wi & e2e Touch Events Window Insets View#onApplyWindowInsets(insets) View#onTouchEvent(event) Dispatch

    to childs until there’s a “consumed” view Dispatch to childs until there’s a “handled” view View#setOnApplyWindowInsetListener( listener) View#setOnTouchListener(listener)
  8. Wi & e2e // onCreate or onViewCreated View.setOnApplyWindowInsetListener(view) { v,

    windowInsets " { // receive WindowInsets object here }
  9. API Level E2E with Dark Theme E2E with Light Theme

    E2E with Gestural Navigation Light Status Bar Light Bottom Navigation Bar E2E 21 -> 22 TRANSLUCENT NO PARTIAL NO 23 -> 25 YES NO PARTIAL - 26 -> 28 - - 29 -> 30 - - Edge to edge availability
  10. // 3. light or dark icons in system bars val

    darkIcons = true WindowInsetsControllerCompat(window, Setting up // onCreate() // 1. make system bars transparently window.navigationBarColor = Color.TRANSPARENT window.statusBarColor = Color.TRANSPARENT 12:30 // 2. ”edge-to-edge” flags WindowCompat.setDecorFitsSystemWindows(window, false)
  11. // 2. ”edge-to-edge” flags WindowCompat.setDecorFitsSystemWindows(window, false) // onCreate() // 1.

    make system bars transparently window.navigationBarColor = Color.TRANSPARENT window.statusBarColor = Color.TRANSPARENT // 3. light or dark icons in system bars val darkIcons = true WindowInsetsControllerCompat(window, window.peekDecorView()).apply { isAppearanceLightNavigationBars = darkIcons isAppearanceLightStatusBars = darkIcons } Setting up 12:30 // 4. drawing behind the cutout area window.attributes.layoutInDisplayCutoutMode =
  12. val darkIcons = true WindowInsetsControllerCompat(window, window.peekDecorView()).apply { isAppearanceLightNavigationBars = darkIcons

    isAppearanceLightStatusBars = darkIcons } Setting up 12:30 // 4. drawing behind the cutout area window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams. LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES window.requestLayout();
  13. Fix visual overlaps // 3. listen to insets ViewCompat.setOnApplyWindowInsetsListener(view) {

    v, windowInsets-> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() windownInsets } // now add some padding or margin to conflict views …
  14. Use an “invisible view” to constraint others Safe Area View

    class SafeAreaView : View { override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets { val lp = layoutParams as ViewGroup.MarginLayoutParams? insets?.apply { lp.topMargin = systemWindowInsetTop lp.leftMargin = systemWindowInsetLeft lp.rightMargin = systemWindowInsetRight lp.bottomMargin = systemWindowInsetBottom } return super.onApplyWindowInsets(insets) }
  15. Use an “invisible view” to constraint others app:layout_constraintStart_toStartOf="parent"" “id/safeAreaView” app:layout_constraintTop_toTopOf=“parent”

    " “id/safeAreaView” app:layout_constraintEnd_toEndOf=“parent” " “id/safeAreaView” app:layout_constraintEnd_toEndOf=“parent” " “id/safeAreaView” https://shorturl.at/jnHX5
  16. Padding instead of margin Scrollable view ScrollView ListView RecyclerView //

    caching initial padding val initialPadding = view.paddingBottom // applying insets view.apply { paddingBottom = initialPadding + inset.bottom }
  17. Request window insets // Ask for a new dispatch of

    WindowInsets // to be performed View#requestApplyInsets()
  18. For more docs • Keyword “Going edge-to-edge” • “How to

    become a master window fitter” – Chris bane • “Gesture Navigation and the edge-to-edge experience” – Google CodeLab • Youtube Android Developer