Slide 1

Slide 1 text

Android DarkTheme + CodeLab

Slide 2

Slide 2 text

안성용 SOUP [email protected]

Slide 3

Slide 3 text

Why? Battery Environment Accessibility Up to 60%

Slide 4

Slide 4 text

Why? ✨

Slide 5

Slide 5 text

• Android Q
 Settings > Display > Dark Theme
 
 ( 'যف਍ ప݃' QuickSettingب ୶оؽ ) • Android P
 Settings > System > Developer options > Night mode
 
 ( ࢖ࢿ ױ݈਷ 'ঠр ݽ٘' QuickSetting ઁҕ ) OS Setting New
 in Q

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

٣੗ੋ ܻࣗझܳ ߸҃ೞ૑ ঋҊ, ׮௼ప݃ ޷ܻ ੸ਊ೧ࠁӝ ݾ಴

Slide 9

Slide 9 text

New
 in Q • জਸ ׮௼ ప݃۽ ੗ز ߸ജೞח ӝמ • API 29 ( ) ীࢲ݅ ࢎਊоמ ForceDark

Slide 10

Slide 10 text

Custom Force Dark

Slide 11

Slide 11 text

• ݽٚ জী force-darkܳ ੸ਊೞח ѐߊ੗ ݽ٘ • Android Q Settings > System > Developer options > Override force-dark Override ForceDark • ೞ૑݅ Q Beta4ࠗఠ ز੘ೞ૑ ঋח׮. $ F O R C E D A R K

Slide 12

Slide 12 text

• জ ప݃੄ forceDarkAllowed ࣘࢿਸ true۽ ࢸ੿ೞݶ ഝࢿചػ׮.
 
 
 
 • ױ, Light ప݃݅ ForceDarkо ੸ਊؼ ࣻ ੓׮. Enable ForceDark F O R C E D A R K true</item> <item name="isLightTheme">true</item>

Slide 13

Slide 13 text

• ࠗ࠙੸ਵ۽ ForceDarkܳ ࠺ഝࢿചೡ ࣻب ੓׮. // For Kotlin view.isForceDarkAllowed = false // For Java view.setForceDarkAllowed(false) Disable ForceDark (Partially) F O R C E D A R K

Slide 14

Slide 14 text

After ForceDark

Slide 15

Slide 15 text

After CodeLab

Slide 16

Slide 16 text

CodeLab Android DarkTheme

Slide 17

Slide 17 text

CodeLab ⚠ ௏٘ە਷ ੉ ݃௼о ੓ח ಕ੉૑ܳ ٮۄ ૓೯ؾפ׮. Ѿҗ ޙઁ ࢸݺ ੸ਊ

Slide 18

Slide 18 text

CodeLab • Android Studio 3.4 ੉࢚ • API 21 ੉࢚ Emulator / ױ݈ӝ (STEP7਷ Q ೙ਃ) • Kotlin • DataBinding ળ࠺ $ git clone https://github.com/fornewid/Android-DarkTheme-CodeLab

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Java/Kotlin ࣻ੿ೞ૑ ঋҊ, ׮௼ప݃ ੸ਊೞӝ ௏٘ە ݾ಴

Slide 21

Slide 21 text

CodeLab • ঠр/઱р ݽ٘о ߸҃غ૑ ঋח ޙઁ • AppCompatDelegate API ഐ୹ द,
 AppCompatActivityо ੤द੘غ૑ ঋח׮. Step 1. CodeLab

Slide 22

Slide 22 text

AppCompat 1.1.0 Recreate Activities on Night Mode Changes

Slide 23

Slide 23 text

• Android 4.0 (API14) ੉࢚ ૑ਗ • AppCompat 1.1.0ীࢲ ز੘ ѐࢶ • Night Modeо ߸҃غݶ AppCompatActivityо ੗زਵ۽ ੤द੘ػ׮. AppCompat: Night Mode

Slide 24

Slide 24 text

• MODE_NIGHT_YES
 ೦࢚ যنѱ ಴द • MODE_NIGHT_NO
 ೦࢚ ߋѱ ಴द • MODE_NIGHT_FOLLOW_SYSTEM
 दझమ ࢸ੿ী ٮۄ ߸҃ • MODE_NIGHT_AUTO_BATTERY
 ੺੹ݽ٘ীࢲ যنѱ ಴द Modes N I G H T M O D E App
 Compat 1.1.0 API21 ↑

Slide 25

Slide 25 text

• ঠрݽ٘ܳ ࢸ੿ೞח ߑߨ੉ 2о૑ ੓׮. Set night mode N I G H T M O D E // AppCompatDelegate.java public abstract void setLocalNightMode(@NightMode int mode); public static void setDefaultNightMode(@NightMode int mode) { ... } • ଵҊ: ч੉ in-memoryী ੷੢غ޲۽, ߹ب۽ чਸ ੷੢/ࠂҳ ೧ঠ ೠ׮.

Slide 26

Slide 26 text

• Configuration ੿ࠁ۽ ঠрݽ٘ ੸ਊ ৈࠗܳ ഛੋೡ ࣻ ੓׮. Get night mode N I G H T M O D E fun isDarkTheme(config: Configuration): Boolean { return config.uiMode and // andח &৬ زੌ Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES }

Slide 27

Slide 27 text

• Activityܳ ੤द੘ೞ૑ ঋҊ, ࣻزਵ۽ DarkThemeܳ ੸ਊೡ ࣻب ੓׮. Manual Night Mode N I G H T M O D E class MainActivity : AppCompatActivity() { override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) val isDarkTheme: Boolean = isDarkTheme(newConfig) ... UI সؘ੉౟ ... } }

Slide 28

Slide 28 text

CodeLab • start/build.gradle S T E P 1 Use AppCompat 1.1.0 (1/1) //TODO: STEP1 - Use AppCompat 1.1.0 implementation 'androidx.appcompat:appcompat:1.1.0-rc01'

Slide 29

Slide 29 text

CodeLab • DarkTheme.kt (Pre-defined) S T E P 1 Done! fun apply(enabled: Boolean = false) { val nightMode = if (enabled) { AppCompatDelegate.MODE_NIGHT_YES } else { AppCompatDelegate.MODE_NIGHT_NO } AppCompatDelegate.setDefaultNightMode(nightMode) }

Slide 30

Slide 30 text

CodeLab • ঠрݽ٘ীࢲ ࢚࢝ ߸҃੉ হח ޙઁ • ঠрݽ٘ ܻࣗझܳ ୶о೧ঠ ೠ׮. Step 2. CodeLab

Slide 31

Slide 31 text

New?

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

Dark Theme

Slide 38

Slide 38 text

• L OS ੉੹ীח ӝࠄ ప݃о Dark Theme৓׮. Dark Theme Dark Theme: Light Theme:

Slide 39

Slide 39 text

• AppCompatীࢲب Dark Themeܳ ઁҕೠ׮. Dark Theme Dark Theme: Light Theme:

Slide 40

Slide 40 text

'-night' Resource Qualifier

Slide 41

Slide 41 text

• Night Modeীࢲח -night resource qualifierо ഝࢿചػ׮. • '-night' ಫ؊ী ܻࣗझܳ ୶о೧ঠ ೠ׮. • ৘) values-night, raw-night ١١ '-night' Resource Qualifier Link: https://developer.android.com/guide/topics/resources/providing-resources#AlternativeResources #000000 #ffffff

Slide 42

Slide 42 text

• ⚠ Resource Qualifier ਋ࢶࣽਤܳ ઱੄೧ঠ ೠ׮. '-night' Resource Qualifier res/drawable-hdpi/ic_example.png res/drawable-night-hdpi/ic_example.png res/drawable-land/ic_example.png res/drawable-land-night/ic_example.png

Slide 43

Slide 43 text

CodeLab • res/values-night/styles.xml S T E P 2 Declare '-night' resources (1/3) ... ...

Slide 44

Slide 44 text

CodeLab • res/values-night/colors.xml S T E P 2 Declare '-night' resources (2/3) #121212 #000000 #00c300 #202020 ... #202020

Slide 45

Slide 45 text

CodeLab • Splash ۽Ҋ ੉ܴ ߸҃ S T E P 2 Declare '-night' resources (3/3) Before: res/drawable-night/ic_logo_soup_night.png After: res/drawable-night/ic_logo_soup.png

Slide 46

Slide 46 text

CodeLab • ঠрݽ٘ীࢲ ࢚࢝੉ ੸੺ೞѱ ࠁੋ׮. S T E P 2 Done!

Slide 47

Slide 47 text

CodeLab • ঠрݽ٘ ই੉௑੄ दੋࢿ੉ ڄয૑ח ޙઁ Step 3.

Slide 48

Slide 48 text

CodeLab • ঠрݽ٘ ই੉௑੄ दੋࢿ੉ ڄয૑ח ޙઁ • Drawable ࢚࢝੉ Ҋ੿غয ੓׮. Step 3.

Slide 49

Slide 49 text

Tint View, VectorDrawable, etc…

Slide 50

Slide 50 text

PorterDuff.Mode Link: https://developer.android.com/reference/android/graphics/PorterDuff.Mode.html

Slide 51

Slide 51 text

BlendMode Link: https://developer.android.com/reference/android/graphics/BlendMode ই݃ب ForceDark??

Slide 52

Slide 52 text

• খࢲ ࠄ Modeܳ ੉ਊೞৈ Drawableী ࢝ઑܳ ੑ൧ ࣻ ੓׮. (ӝࠄ: SRC_IN) • ColorStateList۽ Stateful Tintب оמೞ׮. • API 21 ࠗఠ ୶оغ঻૑݅, Compat APIо ઁҕػ׮. • DrawableCompat • VectorDrawableCompat Tint

Slide 53

Slide 53 text

• Drawable XMLীࢲ android:tint ࣘࢿਸ ࢎਊೡ ࣻ ੓׮. Tinting Drawables

Slide 54

Slide 54 text

• Viewب Tint APIо ઁҕػ׮. Tinting Views imageView.setImageTintList(ColorStateList) view.setBackgroundTintList(ColorStateList) ImageViewCompat.setImageTintList(view, ColorStateList) ViewCompat.setBackgroundTintList(view, ColorStateList)

Slide 55

Slide 55 text

CodeLab • res/drawable/ic_round_favorite_off.xml S T E P 3 Tinting icons (1/2)

Slide 56

Slide 56 text

CodeLab • res/drawable/ic_round_error_outline.xml S T E P 3 Tinting icons (2/2)

Slide 57

Slide 57 text

CodeLab • Drawable ࢚࢝੉ ੸੺ೞѱ ࠁੋ׮. S T E P 3 Done!

Slide 58

Slide 58 text

CodeLab • Lottieо ঠрݽ٘۽ ߄Շ૑ ঋח ޙઁ • Lottie Bug! Step 4.

Slide 59

Slide 59 text

• Animation ࢸ੿ೡ ٸ, زੌ ܻࣗझ IDח সؘ੉౟غ૑ ঋח ੉गо ੓׮. Lottie Issue // LottieComposition.java private static String rawResCacheKey(@RawRes int resId) { return "rawRes_" + resId; } Link: https://github.com/airbnb/lottie-android/issues/1305

Slide 60

Slide 60 text

CodeLab • res/layout/home_card_moop.xml S T E P 4 Set 'Lottie' dynamically (1/2)

Slide 61

Slide 61 text

CodeLab • LottieBindingAdapter.kt S T E P 4 Set 'Lottie' dynamically (2/2) @BindingAdapter("lottie_rawResDay", "lottie_rawResNight") fun setAnimationAsync(view: LottieAnimationView, @RawRes dayRawRes: Int, @RawRes nightRawRes: Int) { if (DarkTheme.isEnabled(view.context)) { view.setAnimation(nightRawRes) } else { view.setAnimation(dayRawRes) } }

Slide 62

Slide 62 text

CodeLab • Lottieо ੸੺൤ ߸҃ػ׮. S T E P 4 Done!

Slide 63

Slide 63 text

CodeLab Step 5. #FF00c300 #FF00b300 #FF00c300 #FFffffff #FF000000 #FF000000 #FFeeeeee #1A000000 #FF121212 #1F000000 #33000000 #dd000000 #FFee4b4b #FFffffff #FF00c300 #FF00b300 #FF00c300 #FFffffff #FF000000 #FF000000 #FFeeeeee #1A000000 #FF121212 #1F000000 #33000000 #dd000000 #FFee4b4b #FFffffff • ҙܻೞח Colorо ݆ই૑ח ޙઁ • Color Attributeܳ ੉ਊೞৈ
 Ӓܛ ױਤ۽ ҙܻೡ ࣻ ੓׮.

Slide 64

Slide 64 text

ColorStateList with 'android:alpha' attribute

Slide 65

Slide 65 text

• android:alpha attributeо API 21 ࠗఠ ୶оغ঻णפ׮. ColorStateList

Slide 66

Slide 66 text

• android:alpha attribute੉ ನೣػ ColorStateList ܻࣗझܳ ੍ਸ ٸ,
 API 23 ੉ೞ ߡ੹ীࢲח AppCompat APIܳ ࢎਊ೧ঠ ೤פ׮. ColorStateList AppCompatResources.getColorStateList(context, R.color.divider)

Slide 67

Slide 67 text

CodeLab • res/values/attrs.xml S T E P 5 Use color attribute (1/5)

Slide 68

Slide 68 text

CodeLab • res/values/styles.xml S T E P 5 Use color attribute (2/5) ... <!-- TODO: STEP5 - Use color attribute --> <item name="colorOnBackground">@android:color/black</item>

Slide 69

Slide 69 text

CodeLab • res/values-night/styles.xml S T E P 5 Use color attribute (3/5) ... <!-- TODO: STEP5 - Use color attribute --> <item name="colorOnBackground">@android:color/white</item> <style>

Slide 70

Slide 70 text

CodeLab • res/color/divider.xml S T E P 5 Use color attribute (4/5)

Slide 71

Slide 71 text

CodeLab • res/layout/home_card_soup.xml • res/layout/home_card_moop.xml S T E P 5 Use color attribute (5/5)

Slide 72

Slide 72 text

CodeLab • زੌೠ ࢚࢝ਵ۽ ੸ਊػ׮. S T E P 5 Done!

Slide 73

Slide 73 text

Color Attributes in Material Design Components

Slide 74

Slide 74 text

Pre-Defined Color Attributes in MDC

Slide 75

Slide 75 text

CodeLab • AppThemeܳ ࢎਊೞ૑ ঋח ࠗ࠙਷
 ঠрݽ٘ীࢲ ߋѱ ࠁ੉ח ޙઁ • android:theme ࣘࢿਸ ੜ ഛੋ೧ࠁ੗. Step 6.

Slide 76

Slide 76 text

DayNight Themes AppCompat, MDC

Slide 77

Slide 77 text

• AppCompatীࢲ DayNight themeܳ ઁҕೠ׮. DayNight Theme values/theme.xml values-night/theme.xml

Slide 78

Slide 78 text

• AppCompatীࢶ ThemeOverlayب DayNight themeܳ ઁҕೠ׮. DayNight Theme values/theme.xml values-night/theme.xml

Slide 79

Slide 79 text

• MDCীب DayNight themeܳ ઁҕೠ׮. DayNight Theme values/theme.xml values-night/theme.xml

Slide 80

Slide 80 text

• ೞ૑݅ MDCী ThemeOverlayח DayNight themeܳ ૑ਗೞ૑ ঋח׮. DayNight Theme values/theme.xml values-night/theme.xml

Slide 81

Slide 81 text

CodeLab • res/layout/home_activity.xml S T E P 6 Use DayNight theme (1/1)

Slide 82

Slide 82 text

CodeLab • ݫ׏ ࢚࢝੉ ੸੺ೞѱ ࠁੋ׮. S T E P 6 Done!

Slide 83

Slide 83 text

CodeLab • WebViewח ೦࢚ ߋѱ ࠁ੉ח ޙઁ • ForceDarkܳ ੉ਊೞৈ যنѱ ಴द೧ࠁ੗. Step 7. Optional

Slide 84

Slide 84 text

"Developing Themes with Style" #3. Layer your themes for re-use Link: https://j.mp/themes-styles?slide=176

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

No content

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

No content

Slide 90

Slide 90 text

CodeLab • start/build.gradle S T E P 7. O P T I O N A L Layer your themes (1/4) //TODO: STEP7 - Layer your themes android { compileSdkVersion 29 buildToolsVersion "29.0.0" defaultConfig { applicationId "soup.codelab.darktheme" minSdkVersion 21 targetSdkVersion 29 ...

Slide 91

Slide 91 text

CodeLab • res/values/themes.xml S T E P 7. O P T I O N A L Layer your themes (2/4)

Slide 92

Slide 92 text

CodeLab • res/values-v29/themes.xml S T E P 7. O P T I O N A L Layer your themes (3/4) <item name="android:isLightTheme">true</item> <item name="android:forceDarkAllowed">true</item>

Slide 93

Slide 93 text

CodeLab • res/values/styles.xml • res/values-night/styles.xml S T E P 7. O P T I O N A L Layer your themes (4/4)

Slide 94

Slide 94 text

CodeLab • Web Contents ࢚࢝੉ ߈੹غয ࠁੋ׮. S T E P 7. O P T I O N A L Done!

Slide 95

Slide 95 text

CodeLab • ׮௼ప݃ীࢲ BottomSheet दੋࢿ ޙઁ • Elevationਵ۽ ੋೠ Ӓܿ੗о ੜ উࠁੋ׮.
 
 Black Bg + Black Shadow = Black Step 8. Optional

Slide 96

Slide 96 text

MDC 1.1.0 Elevation Overlays for Dark Theme

Slide 97

Slide 97 text

• Higher elevation, lighter surface • ߋӝח ߈ైݺೠ ൟ࢝ overlay۽ ઑ੺ػ׮. • Elevation (0dp ~ 24dp) • Overlay Transparency (0% ~ 16%) Elevation Surface Elevation Overlay

Slide 98

Slide 98 text

Shadow Surface

Slide 99

Slide 99 text

• MDC Componentsח ইې ࣘࢿী ٮۄ Elevation Overlaysо ੸ਊػ׮.
 
 
 
 • MaterialShapeDrawable, ElevationOverlayProviderܳ ੉ਊೞݶ
 Custom Viewب Elevation Overlaysܳ ࣚऔѱ ੸ਊೡ ࣻ ੓׮. • ਗ஖ ঋח ҃਋, elevationOverlaysEnabled ࣘࢿਸ false۽ ߸҃ೞݶ ػ׮. Elevation Overlays E L E V A T I O N <item name="elevationOverlaysEnabled">true</item> <item name="elevationOverlaysColor">?attr/colorOnSurface</item>

Slide 100

Slide 100 text

• Elevationী ٮۄ Overlay ࢚࢝җ ߓ҃࢝ਸ ੸੺൤ ࢴযળ׮. ElevationOverlayProvider E L E V A T I O N MDC 1.1.0 @ColorInt // layered color, if elevationOverlaysEnabled == true public int layerOverlayIfNeeded(@ColorInt int bgColor, float elevation) @ColorInt // layered color, always public int layerOverlay(@ColorInt int bgColor, float elevation) @ColorInt // layered color, of attr/colorSurface public int getSurfaceColorWithOverlayIfNeeded(float elevation) C

Slide 101

Slide 101 text

• MDCীࢲ ߓ҃ী ࢎਊغח Drawable۽,
 ղࠗ੸ਵ۽ ElevationOverlayProviderܳ ࢎਊೠ׮.
 
 
 
 • ز੸ਵ۽ Elevation ߸҃੉ оמೞ׮. MaterialShapeDrawable E L E V A T I O N private val bgDrawable = MaterialShapeDrawable().apply { initializeElevationOverlay(context) fillColor = context.getColorAttr(R.attr.colorSurface) } bgDrawable.setElevation(float elevation) C

Slide 102

Slide 102 text

• MDC Guideline: WCAG’s AA ળࣻܳ ӂ੢ • ੘਷ ఫझ౟ - ୭ࣗ 4.5:1 • ௾ ఫझ౟ - ୭ࣗ 3.0:1 • Text, BG р ؀࠺о ୭ࣗ 15.8:1 ח غযঠ
 24dp elevationীࢲ body textо AAܳ ݅઒ • 24dp = ୭؀ elevation (MDC) Accessibility E L E V A T I O N #121212 8% Primary Dark Primary #1F1B24 Link: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html

Slide 103

Slide 103 text

CodeLab • start/build.gradle S T E P 8. O P T I O N A L Get Lighter Surface (1/4) //TODO: STEP8 - Get Lighter Surface implementation 'com.google.android.material:material:1.1.0-alpha08'

Slide 104

Slide 104 text

CodeLab • res/values/styles.xml S T E P 8. O P T I O N A L Get Lighter Surface (2/4) <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="colorSurface">@color/colorBackground</item>

Slide 105

Slide 105 text

CodeLab • MaterialViewBindingAdapter.kt S T E P 8. O P T I O N A L Get Lighter Surface (3/4) /* TODO: STEP8 - Get Lighter Surface */ @BindingAdapter("elevationOverlaysEnabled") fun setElevationOverlaysEnabled(view: View, enabled: Boolean) { view.background = if (enabled) { MaterialShapeDrawable.createWithElevationOverlay( view.context, view.elevation) } else { ... } }

Slide 106

Slide 106 text

CodeLab • res/layout/home_bottom_sheet.xml S T E P 8. O P T I O N A L Get Lighter Surface (4/4)

Slide 107

Slide 107 text

CodeLab • BottomSheet ಴ݶ੉ ߋѱ ࠁੋ׮. S T E P 8. O P T I O N A L Done!

Slide 108

Slide 108 text

Others

Slide 109

Slide 109 text

• Notification਷ ੗ز ੸ਊػ׮. • Custom Notification਷ ইې styleਸ ࢎਊೡ Ѫ • TextAppearance.Compat.Notification • ױ, ࢖ࢿ P OSח ੸ਊ ؀࢚੉ ইפ׮. Notification