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

Avatar for Le Dinh Trung

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