Slide 1

Slide 1 text

BECOMING A MASTER WINDOW FITTER @chrisbanes

Slide 2

Slide 2 text

BECOMING A MASTER WINDOW FITTER chris.banes.me/dcnyc17

Slide 3

Slide 3 text

What’s a window?

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

12:00

Slide 6

Slide 6 text

12:00

Slide 7

Slide 7 text

12:00

Slide 8

Slide 8 text

12:00 Window

Slide 9

Slide 9 text

12:00 Activity Window Activities have a Window Activity#getWindow()

Slide 10

Slide 10 text

12:00 Window Activity Dialogs have a Window too Dialog#getWindow() Dialog

Slide 11

Slide 11 text

12:00 Activity

Slide 12

Slide 12 text

12:00 Activity Activity

Slide 13

Slide 13 text

Why do I have to
 fit them?

Slide 14

Slide 14 text

12:00

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

S

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Inset

Slide 24

Slide 24 text

Inset How the system tells you where the system ui currently is, or may later be displayed

Slide 25

Slide 25 text

BECOMING A MASTER WINDOW FITTER History

Slide 26

Slide 26 text

Pre-KitKat

Slide 27

Slide 27 text

Pre-KitKat

Slide 28

Slide 28 text

Pre-KitKat Window is placed within system bars

Slide 29

Slide 29 text

Pre-KitKat Window is placed within system bars

Slide 30

Slide 30 text

Pre-KitKat setSystemUiVisibility() Window is placed within system bars

Slide 31

Slide 31 text

setSystemUiVisibility()

Slide 32

Slide 32 text

SYSTEM_UI_FLAG_VISIBLE SYSTEM_UI_FLAG_LOW_PROFILE SYSTEM_UI_FLAG_HIDE_NAVIGATION SYSTEM_UI_FLAG_FULLSCREEN SYSTEM_UI_FLAG_IMMERSIVE_STICKY SYSTEM_UI_FLAG_IMMERSIVE SYSTEM_UI_FLAG_LIGHT_STATUS_BAR SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR SYSTEM_UI_FLAG_LAYOUT_STABLE SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

Slide 33

Slide 33 text

SYSTEM_UI_FLAG_VISIBLE SYSTEM_UI_FLAG_LOW_PROFILE SYSTEM_UI_FLAG_HIDE_NAVIGATION SYSTEM_UI_FLAG_FULLSCREEN SYSTEM_UI_FLAG_IMMERSIVE_STICKY SYSTEM_UI_FLAG_IMMERSIVE SYSTEM_UI_FLAG_LIGHT_STATUS_BAR SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR SYSTEM_UI_FLAG_LAYOUT_STABLE SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

Slide 34

Slide 34 text

SYSTEM_UI_FLAG_VISIBLE SYSTEM_UI_FLAG_LOW_PROFILE SYSTEM_UI_FLAG_HIDE_NAVIGATION SYSTEM_UI_FLAG_FULLSCREEN SYSTEM_UI_FLAG_IMMERSIVE_STICKY SYSTEM_UI_FLAG_IMMERSIVE SYSTEM_UI_FLAG_LIGHT_STATUS_BAR SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR SYSTEM_UI_FLAG_LAYOUT_STABLE SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

Slide 35

Slide 35 text

SYSTEM_UI_FLAG_VISIBLE SYSTEM_UI_FLAG_LOW_PROFILE SYSTEM_UI_FLAG_HIDE_NAVIGATION SYSTEM_UI_FLAG_FULLSCREEN SYSTEM_UI_FLAG_IMMERSIVE_STICKY SYSTEM_UI_FLAG_IMMERSIVE SYSTEM_UI_FLAG_LIGHT_STATUS_BAR SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR SYSTEM_UI_FLAG_LAYOUT_STABLE SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

Slide 36

Slide 36 text

SYSTEM_UI_FLAG_VISIBLE SYSTEM_UI_FLAG_LOW_PROFILE SYSTEM_UI_FLAG_HIDE_NAVIGATION SYSTEM_UI_FLAG_FULLSCREEN SYSTEM_UI_FLAG_IMMERSIVE_STICKY SYSTEM_UI_FLAG_IMMERSIVE SYSTEM_UI_FLAG_LIGHT_STATUS_BAR SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR SYSTEM_UI_FLAG_LAYOUT_STABLE SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

Slide 37

Slide 37 text

SYSTEM_UI_FLAG_VISIBLE SYSTEM_UI_FLAG_LOW_PROFILE SYSTEM_UI_FLAG_HIDE_NAVIGATION SYSTEM_UI_FLAG_FULLSCREEN SYSTEM_UI_FLAG_IMMERSIVE_STICKY SYSTEM_UI_FLAG_IMMERSIVE SYSTEM_UI_FLAG_LIGHT_STATUS_BAR SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR SYSTEM_UI_FLAG_LAYOUT_STABLE SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN chris.banes.me/systemuihelper

Slide 38

Slide 38 text

indow lag W F ransform T s View.SYSTEM_UI_FLAG_LAYOUT_STABLE View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or

Slide 39

Slide 39 text

W F T s View.SYSTEM_UI_FLAG_LAYOUT_STABLE View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or

Slide 40

Slide 40 text

myView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

Slide 41

Slide 41 text

myView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

Slide 42

Slide 42 text

KitKat

Slide 43

Slide 43 text

KitKat

Slide 44

Slide 44 text

KitKat Translucent system bars

Slide 45

Slide 45 text

KitKat Translucent system bars

Slide 46

Slide 46 text

KitKat Translucent system bars android:windowTranslucentStatus android:windowTranslucentNavigation

Slide 47

Slide 47 text

Translucent system bars WTFs are implied KitKat

Slide 48

Slide 48 text

Translucent system bars WTFs are implied System bar backgrounds are drawn by WindowManager KitKat

Slide 49

Slide 49 text

Lollipop

Slide 50

Slide 50 text

Lollipop

Slide 51

Slide 51 text

Lollipop android:windowDrawsSystemBarBackgrounds System bar backgrounds are placed in Window

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

android:navigationBarColor getWindow().setNavigationBarColor()

Slide 54

Slide 54 text

android:statusBarColor getWindow().setStatusBarColor()

Slide 55

Slide 55 text

Lollipop WTFs are not implied

Slide 56

Slide 56 text

Lollipop They take precedence over custom colors Translucent system bars They disable windowDrawsSystemBarBackgrounds

Slide 57

Slide 57 text

BECOMING A MASTER WINDOW FITTER How can you handle this?

Slide 58

Slide 58 text

android:fitSystemWindows="true"

Slide 59

Slide 59 text

android:fitSystemWindows="true" Uses padding to move child views within insets Default View.java behavior:

Slide 60

Slide 60 text

12:00

Slide 61

Slide 61 text

12:00 android:fitSystemWindows="true"

Slide 62

Slide 62 text

12:00 android:fitSystemWindows="true" systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

Slide 63

Slide 63 text

12:00 android:fitSystemWindows="true" systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

Slide 64

Slide 64 text

12:00 android:fitSystemWindows="true" systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN Padding Padding

Slide 65

Slide 65 text

Rule of thumb You probably want to avoid the default behavior of android:fitSystemWindows

Slide 66

Slide 66 text

But the docs say to use it?!

Slide 67

Slide 67 text

But the docs say to use it?! DrawerLayout CoordinatorLayout AppBarLayout CollapsingToolbarLayout

Slide 68

Slide 68 text

DrawerLayout Sets the WTFs for you on API 21+ 12:00

Slide 69

Slide 69 text

12:00 
 >

Slide 70

Slide 70 text

12:00 > fitSystemWindows="true" 


Slide 71

Slide 71 text

12:00 fitSystemWindows="true">

Slide 72

Slide 72 text

DrawerLayout Sets the WTFs for you on API 21+ 12:00 Use fitSystemWindows as a signal from children

Slide 73

Slide 73 text

12:00 fitSystemWindows="true"> />

Slide 74

Slide 74 text

12:00 fitSystemWindows="true"> />

Slide 75

Slide 75 text

fitSystemWindows="true"> /> fitSystemWindows="true" 12:00

Slide 76

Slide 76 text

fitSystemWindows="true"> /> fitSystemWindows="true" 12:00

Slide 77

Slide 77 text

fitSystemWindows="true"> /> fitSystemWindows="true" 12:00

Slide 78

Slide 78 text

fitSystemWindows="true"> /> fitSystemWindows="true" 12:00

Slide 79

Slide 79 text

fitSystemWindows="true"> /> fitSystemWindows="true" 12:00

Slide 80

Slide 80 text

fitSystemWindows="true"> /> fitSystemWindows="true" > 12:00

Slide 81

Slide 81 text

fitSystemWindows="true"> /> fitSystemWindows="true" fitSystemWindows="true"> 12:00

Slide 82

Slide 82 text

fitSystemWindows="true"> /> fitSystemWindows="true" 12:00 fitSystemWindows="true">

Slide 83

Slide 83 text

12:00 fitSystemWindows="true"> fitSystemWindows="true"> /> fitSystemWindows="true"

Slide 84

Slide 84 text

CoordinatorLayout + AppBarLayout + CollapsingToolbarLayout

Slide 85

Slide 85 text

12:00 Sets the WTFs for you on API 21+ Use fitSystemWindows as a signal from children CoordinatorLayout + AppBarLayout + CollapsingToolbarLayout

Slide 86

Slide 86 text

Slide 87

Slide 87 text

Slide 88

Slide 88 text

BECOMING A MASTER WINDOW FITTER Manual handling

Slide 89

Slide 89 text

BECOMING A MASTER WINDOW FITTER What not to do…

Slide 90

Slide 90 text

Fixed dimension for status bar What not to do…

Slide 91

Slide 91 text

24dp

Slide 92

Slide 92 text

24dp res/values-v23 25dp res/values

Slide 93

Slide 93 text

What if the status bar size changes?

Slide 94

Slide 94 text

Slide 95

Slide 95 text

No content

Slide 96

Slide 96 text

What happens if devices have different status bar sizes?

Slide 97

Slide 97 text

53dp 24dp

Slide 98

Slide 98 text

Retrieve internal system resources What not to do…

Slide 99

Slide 99 text

192dp 192dp 60% 240 48dip 64dip 24dp 48dp 48dp 48dp frameworks/base/core/res/values/dimens.xml

Slide 100

Slide 100 text

frameworks/base/core/res/values/dimens.xml 192dp 192dp 60% 240 48dip 64dip 24dp 48dp 48dp 48dp

Slide 101

Slide 101 text

var resourceId = resources.getIdentifier(
 "status_bar_height", "dimen", "android")
 return resources.getDimensionPixelSize(resourceId)

Slide 102

Slide 102 text

What happens if the internal resource name changes?

Slide 103

Slide 103 text

No content

Slide 104

Slide 104 text

What if the device does not let you draw behind the status bar?

Slide 105

Slide 105 text

No content

Slide 106

Slide 106 text

No content

Slide 107

Slide 107 text

No content

Slide 108

Slide 108 text

BECOMING A MASTER WINDOW FITTER The supported way: WindowInsets

Slide 109

Slide 109 text

BECOMING A MASTER WINDOW FITTER WindowInsets getSystemWindowInsetLeft() getSystemWindowInsetTop() getSystemWindowInsetRight() getSystemWindowInsetBottom()

Slide 110

Slide 110 text

BECOMING A MASTER WINDOW FITTER WindowInsets getSystemWindowInsetLeft() getSystemWindowInsetTop() getSystemWindowInsetRight() getSystemWindowInsetBottom() Compat

Slide 111

Slide 111 text

12:00 getSystemWindowInsetLeft() getSystemWindowInsetTop() getSystemWindowInsetRight() getSystemWindowInsetBottom()

Slide 112

Slide 112 text

12:00 getSystemWindowInsetLeft() getSystemWindowInsetTop() getSystemWindowInsetRight() getSystemWindowInsetBottom() 0

Slide 113

Slide 113 text

12:00 getSystemWindowInsetLeft() getSystemWindowInsetTop() getSystemWindowInsetRight() getSystemWindowInsetBottom() 72 0

Slide 114

Slide 114 text

12:00 getSystemWindowInsetLeft() getSystemWindowInsetTop() getSystemWindowInsetRight() getSystemWindowInsetBottom() 72 0 0

Slide 115

Slide 115 text

12:00 getSystemWindowInsetLeft() getSystemWindowInsetTop() getSystemWindowInsetRight() getSystemWindowInsetBottom() 144 72 0 0

Slide 116

Slide 116 text

BECOMING A MASTER WINDOW FITTER myView.setOnApplyWindowInsetsListener { view, insets -> // TODO handle insets return insets.consumeSystemWindowInsets() }

Slide 117

Slide 117 text

BECOMING A MASTER WINDOW FITTER ViewCompat.setOnApplyWindowInsetsListener(view) { view, insets -> // TODO handle insets return insets.consumeSystemWindowInsets() }

Slide 118

Slide 118 text

BECOMING A MASTER WINDOW FITTER class CustomLayout : LinearLayout { // yadda yadda override fun onApplyWindowInsets( insets: WindowInsets): WindowInsets { // TODO handle the insets return insets.consumeSystemWindowInsets() } }

Slide 119

Slide 119 text

BECOMING A MASTER WINDOW FITTER class CustomLayout : LinearLayout { // yadda yadda override fun onApplyWindowInsets( insets: WindowInsets): WindowInsets { // TODO handle the insets return insets.consumeSystemWindowInsets() } }

Slide 120

Slide 120 text

BECOMING A MASTER WINDOW FITTER WindowInsets will be passed down until it has been consumed

Slide 121

Slide 121 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child dispatchApplyWindowInsets()

Slide 122

Slide 122 text

BECOMING A MASTER WINDOW FITTER Window Decor dispatchApplyWindowInsets() LinearLayout Child Child

Slide 123

Slide 123 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child Left: Top: Right: Bottom: 0 72 0 144 dispatchApplyWindowInsets()

Slide 124

Slide 124 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child Left: Top: Right: Bottom: 0 72 0 144 onApplyWindowInsets()

Slide 125

Slide 125 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child Left: Top: Right: Bottom: 0 0 0 144 onApplyWindowInsets() Consumes top

Slide 126

Slide 126 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child WindowInsets.isConsumed() Left: Top: Right: Bottom: 0 0 0 144 false

Slide 127

Slide 127 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child dispatchApplyWindowInsets() Left: Top: Right: Bottom: 0 0 0 144

Slide 128

Slide 128 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child Left: Top: Right: Bottom: 0 0 0 144 onApplyWindowInsets()

Slide 129

Slide 129 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child Left: Top: Right: Bottom: 0 0 0 144 WindowInsets.isConsumed() false

Slide 130

Slide 130 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child dispatchApplyWindowInsets() Left: Top: Right: Bottom: 0 0 0 144

Slide 131

Slide 131 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child Left: Top: Right: Bottom: 0 0 0 144 onApplyWindowInsets()

Slide 132

Slide 132 text

BECOMING A MASTER WINDOW FITTER Window Decor LinearLayout Child Child Left: Top: Right: Bottom: 0 0 0 0 WindowInsets.isConsumed() true

Slide 133

Slide 133 text

BECOMING A MASTER WINDOW FITTER TL;DW

Slide 134

Slide 134 text

BECOMING A MASTER WINDOW FITTER If you’re using DrawerLayout or CoordinatorLayout Use android:fitSystemWindows="true" on direct children which you want to be displayed behind the system bars

Slide 135

Slide 135 text

BECOMING A MASTER WINDOW FITTER Avoid translucent system bars #80000000 #80000000

Slide 136

Slide 136 text

BECOMING A MASTER WINDOW FITTER If you need to get access to the status bar size myView.setOnApplyWindowInsetsListener { view, insets -> val statusBarSize = insets.systemWindowInsetTop return insets }

Slide 137

Slide 137 text

BECOMING A MASTER WINDOW FITTER Repeat once per week I will never store or retrieve the status bar size from resources ever again

Slide 138

Slide 138 text

Over and out… @chrisbanes