1 package com.android.setupwizardlib.util; 2 3 import android.app.Activity; 4 import android.content.Intent; 5 import androidx.annotation.Nullable; 6 import androidx.annotation.StyleRes; 7 import com.android.setupwizardlib.R; 8 9 /** 10 * A resolver to resolve the theme from a string or an activity intent, setting options like the 11 * default theme and the oldest supported theme. Apps can share the resolver across the entire 12 * process by calling {@link #setDefault(ThemeResolver)} in {@link 13 * android.app.Application#onCreate()}. If an app needs more granular sharing of the theme default 14 * values, additional instances of {@link ThemeResolver} can be created using the builder. 15 */ 16 public class ThemeResolver { 17 @StyleRes private final int defaultTheme; 18 @Nullable private final String oldestSupportedTheme; 19 private final boolean useDayNight; 20 21 @Nullable private static ThemeResolver defaultResolver; 22 23 /** 24 * Sets the default instance used for the whole process. Can be null to reset the default to the 25 * preset one. 26 */ setDefault(@ullable ThemeResolver resolver)27 public static void setDefault(@Nullable ThemeResolver resolver) { 28 defaultResolver = resolver; 29 } 30 31 /** 32 * Returns the default instance, which can be changed using {@link #setDefault(ThemeResolver)}. 33 */ getDefault()34 public static ThemeResolver getDefault() { 35 if (defaultResolver == null) { 36 defaultResolver = 37 new ThemeResolver.Builder() 38 .setDefaultTheme(R.style.SuwThemeGlif_DayNight) 39 .setUseDayNight(true) 40 .build(); 41 } 42 return defaultResolver; 43 } 44 ThemeResolver( int defaultTheme, @Nullable String oldestSupportedTheme, boolean useDayNight)45 private ThemeResolver( 46 int defaultTheme, @Nullable String oldestSupportedTheme, boolean useDayNight) { 47 this.defaultTheme = defaultTheme; 48 this.oldestSupportedTheme = oldestSupportedTheme; 49 this.useDayNight = useDayNight; 50 } 51 52 /** 53 * Returns the style for the theme specified in the intent extra. If the specified string theme is 54 * older than the oldest supported theme, the default will be returned instead. Note that the 55 * default theme is returned without processing -- it may not be a DayNight theme even if {@link 56 * #useDayNight} is true. 57 */ 58 @StyleRes resolve(Intent intent)59 public int resolve(Intent intent) { 60 return resolve( 61 intent.getStringExtra(WizardManagerHelper.EXTRA_THEME), 62 /* suppressDayNight= */ WizardManagerHelper.isSetupWizardIntent(intent)); 63 } 64 65 /** 66 * Returns the style for the given string theme. If the specified string theme is older than the 67 * oldest supported theme, the default will be returned instead. Note that the default theme is 68 * returned without processing -- it may not be a DayNight theme even if {@link #useDayNight} is 69 * true. 70 */ 71 @StyleRes resolve(@ullable String theme)72 public int resolve(@Nullable String theme) { 73 return resolve(theme, /* suppressDayNight= */ false); 74 } 75 76 @StyleRes resolve(@ullable String theme, boolean suppressDayNight)77 private int resolve(@Nullable String theme, boolean suppressDayNight) { 78 int themeResource = 79 useDayNight && !suppressDayNight ? getDayNightThemeRes(theme) : getThemeRes(theme); 80 if (themeResource == 0) { 81 return defaultTheme; 82 } 83 84 if (oldestSupportedTheme != null && compareThemes(theme, oldestSupportedTheme) < 0) { 85 return defaultTheme; 86 } 87 return themeResource; 88 } 89 90 /** Reads the theme from the intent, and applies the resolved theme to the activity. */ applyTheme(Activity activity)91 public void applyTheme(Activity activity) { 92 activity.setTheme(resolve(activity.getIntent())); 93 } 94 95 /** 96 * Returns the corresponding DayNight theme resource ID for the given string theme. DayNight 97 * themes are themes that will be either light or dark depending on the system setting. For 98 * example, the string {@link WizardManagerHelper#THEME_GLIF_LIGHT} will return 99 * {@code @style/SuwThemeGlif.DayNight}. 100 */ 101 @StyleRes getDayNightThemeRes(@ullable String theme)102 private static int getDayNightThemeRes(@Nullable String theme) { 103 if (theme != null) { 104 switch (theme) { 105 case WizardManagerHelper.THEME_GLIF_V3_LIGHT: 106 case WizardManagerHelper.THEME_GLIF_V3: 107 return R.style.SuwThemeGlifV3_DayNight; 108 case WizardManagerHelper.THEME_GLIF_V2_LIGHT: 109 case WizardManagerHelper.THEME_GLIF_V2: 110 return R.style.SuwThemeGlifV2_DayNight; 111 case WizardManagerHelper.THEME_GLIF_LIGHT: 112 case WizardManagerHelper.THEME_GLIF: 113 return R.style.SuwThemeGlif_DayNight; 114 case WizardManagerHelper.THEME_MATERIAL_LIGHT: 115 case WizardManagerHelper.THEME_MATERIAL: 116 return R.style.SuwThemeMaterial_DayNight; 117 default: 118 // fall through 119 } 120 } 121 return 0; 122 } 123 124 /** 125 * Returns the theme resource ID for the given string theme. For example, the string {@link 126 * WizardManagerHelper#THEME_GLIF_LIGHT} will return {@code @style/SuwThemeGlif.Light}. 127 */ 128 @StyleRes getThemeRes(@ullable String theme)129 private static int getThemeRes(@Nullable String theme) { 130 if (theme != null) { 131 switch (theme) { 132 case WizardManagerHelper.THEME_GLIF_V3_LIGHT: 133 return R.style.SuwThemeGlifV3_Light; 134 case WizardManagerHelper.THEME_GLIF_V3: 135 return R.style.SuwThemeGlifV3; 136 case WizardManagerHelper.THEME_GLIF_V2_LIGHT: 137 return R.style.SuwThemeGlifV2_Light; 138 case WizardManagerHelper.THEME_GLIF_V2: 139 return R.style.SuwThemeGlifV2; 140 case WizardManagerHelper.THEME_GLIF_LIGHT: 141 return R.style.SuwThemeGlif_Light; 142 case WizardManagerHelper.THEME_GLIF: 143 return R.style.SuwThemeGlif; 144 case WizardManagerHelper.THEME_MATERIAL_LIGHT: 145 return R.style.SuwThemeMaterial_Light; 146 case WizardManagerHelper.THEME_MATERIAL: 147 return R.style.SuwThemeMaterial; 148 default: 149 // fall through 150 } 151 } 152 return 0; 153 } 154 155 /** Compares whether the versions of {@code theme1} and {@code theme2} to check which is newer. */ compareThemes(String theme1, String theme2)156 private static int compareThemes(String theme1, String theme2) { 157 return Integer.valueOf(getThemeVersion(theme1)).compareTo(getThemeVersion(theme2)); 158 } 159 160 /** 161 * Returns the version of the theme. The absolute number of the theme version is not defined, but 162 * a larger number in the version indicates a newer theme. 163 */ getThemeVersion(String theme)164 private static int getThemeVersion(String theme) { 165 if (theme != null) { 166 switch (theme) { 167 case WizardManagerHelper.THEME_GLIF_V3_LIGHT: 168 case WizardManagerHelper.THEME_GLIF_V3: 169 return 4; 170 case WizardManagerHelper.THEME_GLIF_V2_LIGHT: 171 case WizardManagerHelper.THEME_GLIF_V2: 172 return 3; 173 case WizardManagerHelper.THEME_GLIF_LIGHT: 174 case WizardManagerHelper.THEME_GLIF: 175 return 2; 176 case WizardManagerHelper.THEME_MATERIAL_LIGHT: 177 case WizardManagerHelper.THEME_MATERIAL: 178 return 1; 179 default: 180 // fall through 181 } 182 } 183 return -1; 184 } 185 186 /** Builder class for {@link ThemeResolver}. */ 187 public static class Builder { 188 @StyleRes private int defaultTheme = R.style.SuwThemeGlif_DayNight; 189 @Nullable private String oldestSupportedTheme = null; 190 private boolean useDayNight = true; 191 Builder()192 public Builder() {} 193 Builder(ThemeResolver themeResolver)194 public Builder(ThemeResolver themeResolver) { 195 this.defaultTheme = themeResolver.defaultTheme; 196 this.oldestSupportedTheme = themeResolver.oldestSupportedTheme; 197 this.useDayNight = themeResolver.useDayNight; 198 } 199 setDefaultTheme(@tyleRes int defaultTheme)200 public Builder setDefaultTheme(@StyleRes int defaultTheme) { 201 this.defaultTheme = defaultTheme; 202 return this; 203 } 204 setOldestSupportedTheme(String oldestSupportedTheme)205 public Builder setOldestSupportedTheme(String oldestSupportedTheme) { 206 this.oldestSupportedTheme = oldestSupportedTheme; 207 return this; 208 } 209 setUseDayNight(boolean useDayNight)210 public Builder setUseDayNight(boolean useDayNight) { 211 this.useDayNight = useDayNight; 212 return this; 213 } 214 build()215 public ThemeResolver build() { 216 return new ThemeResolver(defaultTheme, oldestSupportedTheme, useDayNight); 217 } 218 } 219 } 220