Pro Yearly is on sale from $80 to $50! »

ContextThemeWrapperでthemeをより賢く

 ContextThemeWrapperでthemeをより賢く

Android開発において欠かせないthemeをContextThemeWrapperを使ってさらに便利に使っていきましょうという発表です。

サンプルコードも書いてみたのでご興味があれば以下をご覧ください。
https://github.com/rmakiyama/android-theme-study

E6d26a51159a7863cac28e9d12ccd389?s=128

rmakiyama

April 27, 2020
Tweet

Transcript

  1. ContextThemeWrapperͰ themeΛΑΓݡ͘ potatotips #69 2020/04/27 rmakiyama

  2. ɹɹࣗݾ঺հ •຀ࢁྎ •Radiotalkגࣜձࣾ •AndroidΤϯδχΞ • @_rmakiyama • rmakiyama

  3. theme × ContextThemeWrapper

  4. theme

  5. theme """<!-- AndroidManifest.xml ""--> <application … android:theme="@style/AppTheme"> <activity … android:label=“@string/app_name"

    android:theme=“@style/AppTheme.Hoge”> … "</application>
  6. theme """<!-- themes.xml ""--> <style name="AppTheme" parent=“…”> <item name="colorPrimary">@color/app_purple_500"</item> <item

    name="colorPrimaryVariant">@color/app_purple_700"</item> <item name="colorSecondary">@color/app_teal_500"</item> <item name="colorSecondaryVariant">@color/app_teal_700"</item> "</style> UIFNFBUUSJCVUFT
  7. theme attributes <com.google.android.material.button.MaterialButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:text="@string/button_save" android:textColor="?attr/colorOnPrimary" "/>

  8. theme attributes """<!-- values/themes.xml ""--> <style name="AppTheme" parent=“…”> <item name=“colorSecondary">@color/app_purple_500"</item>

    … "</style> """<!-- values-night/themes.xml ""--> <style name="AppTheme" parent=“…”> <item name=“colorSecondary">@color/app_purple_200"</item> … "</style>
  9. theme attributes """<!-- values/themes.xml ""--> <style name="AppTheme" parent=“…”> <item name=“colorSecondary">@color/app_purple_500"</item>

    … "</style> """<!-- values-night/themes.xml ""--> <style name="AppTheme" parent=“…”> <item name=“colorSecondary">@color/app_purple_200"</item> … "</style>
  10. theme attributes tips <com.google.android.material.button.MaterialButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background=“@color/app_purple_500“ android:text="@string/button_save" android:textColor="@android:color/white" "/>

  11. theme attributes tips <com.google.android.material.button.MaterialButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background=“?attr/colorPrimary“ android:text="@string/button_save" android:textColor=“?attr/colorOnPrimary” "/>

  12. ContextThemeWrapper

  13. ContextThemeWrapper java.lang.Object ↳ android.content.Context ↳ android.content.ContextWrapper ↳ android.view.ContextThemeWrapper ↳ android.app.Activity

  14. ContextThemeWrapperͱ͸ l"DPOUFYUXSBQQFSUIBUBMMPXTZPV UPNPEJGZPSSFQMBDFUIFUIFNFPGUIFXSBQQFEDPOUFYUl SFGIUUQTEFWFMPQFSBOESPJEDPNSFGFSFODFBOESPJEWJFX$POUFYU5IFNF8SBQQFS

  15. ContextThemeWrapperͱ͸ ςʔϚΛஔ͖׵͑ΒΕΔΑʂ

  16. ςʔϚΛஔ͖׵͑ͯΈΔ ϓϩεςʔλεʹͳͬͨΒ *NBHF7JFXͷ
 CBDLHSPVOEͷ৭Λม͑Δ

  17. ςʔϚΛஔ͖׵͑ͯΈΔ """<!-- themes.xml ""--> <style name=“AppTheme”> <item name="colorPrimary">@color/app_purple_500"</item> … "</style>

    """<!-- fragment_layout.xml ""--> <ImageView … android:background="?attr/colorPrimarySurface" … app:srcCompat="@drawable/ic_launcher_foreground" … "/>
  18. ςʔϚΛஔ͖׵͑ͯΈΔ """<!-- themes.xml ""--> <style name=“AppTheme”> <item name="colorPrimary">@color/app_purple_500"</item> … "</style>

    <style name=“AppTheme.Pro”> <item name="colorPrimary">@color/app_orange_500#</item> … #</style>
  19. ςʔϚΛஔ͖׵͑ͯΈΔ """<!-- ProCaseFragment.kt ""--> class ProCaseFragment : DaggerFragment(R.layout.fragment_pro_case) { @Inject

    lateinit var status: UserStatusSetting override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val themedInflater: LayoutInflater = if (status.isProMode) { inflater.cloneInContext( ContextThemeWrapper(requireContext(), R.style.AppTheme_Pro) ) } else inflater return super.onCreateView(themedInflater, container, savedInstanceState) } }
  20. ςʔϚΛஔ͖׵͑ͯΈΔ val themedInflater: LayoutInflater = if (status.isProMode) { inflater.cloneInContext( ContextThemeWrapper(requireContext(),

    R.style.AppTheme_Pro) ) } else inflater return super.onCreateView(themedInflater, container, savedInstanceState)
  21. ςʔϚΛஔ͖׵͑ͯΈΔ val themedInflater: LayoutInflater = if (status.isProMode) { inflater.cloneInContext( ContextThemeWrapper(requireContext(),

    R.style.AppTheme_Pro) ) } else inflater return super.onCreateView(themedInflater, container, savedInstanceState)
  22. ςʔϚΛஔ͖׵͑ͯΈΔ val themedInflater: LayoutInflater = if (status.isProMode) { inflater.cloneInContext( ContextThemeWrapper(requireContext(),

    R.style.AppTheme_Pro) ) } else inflater return super.onCreateView(themedInflater, container, savedInstanceState)
  23. ςʔϚΛஔ͖׵͑ͯΈΔ val themedInflater: LayoutInflater = if (status.isProMode) { inflater.cloneInContext( ContextThemeWrapper(requireContext(),

    R.style.AppTheme_Pro) ) } else inflater return super.onCreateView(themedInflater, container, savedInstanceState)
  24. ςʔϚΛஔ͖׵͑ͯΈΔ """<!-- themes.xml ""--> <style name=“AppTheme”> <item name="colorPrimary">@color/app_purple_500"</item> … "</style>

    <style name=“AppTheme.Pro”> <item name="colorPrimary">@color/app_orange_500"</item> … "</style> """<!-- fragment_layout.xml ""--> <ImageView … android:background="?attr/colorPrimarySurface" … app:srcCompat="@drawable/ic_launcher_foreground" … "/>
  25. ςʔϚΛஔ͖׵͑ͯΈΔ """<!-- ProCaseFragment.kt ""--> class ProCaseFragment : DaggerFragment(R.layout.fragment_pro_case) { @Inject

    lateinit var status: UserStatusSetting override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val themedInflater: LayoutInflater = if (status.isProMode) { inflater.cloneInContext( ContextThemeWrapper(requireContext(), R.style.AppTheme_Pro) ) } else inflater return super.onCreateView(themedInflater, container, savedInstanceState) } }
  26. ςʔϚΛஔ͖׵͑ͯΈΔ """<!-- ProCaseFragment.kt ""--> class ProCaseFragment : DaggerFragment(R.layout.fragment_pro_case) { @Inject

    lateinit var status: UserStatusSetting override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val themedInflater: LayoutInflater = if (status.isProMode) { inflater.cloneInContext( ContextThemeWrapper(requireContext(), R.style.AppTheme_Pro) ) } else inflater return super.onCreateView(themedInflater, container, savedInstanceState) } }
  27. ·ͱΊ • theme attributesΛ׆༻͠Α͏ • ContextThemeWrapperΛ׆༻͠Α͏

  28. appendix • https:"//github.com/rmakiyama/android-theme-study • https:"//mixi-inc.github.io/AndroidTraining/introductions/1.04.basic- knowledge.html#context%E3%81%A8%E3%81%AF%EF%BC%9F • https:"//developer.android.com/reference/android/view/ContextThemeWrapper • https:"//developer.android.com/guide/topics/ui/themes

    • https:"//speakerdeck.com/nickbutcher/developing-themes-with- style-7d0571e3-6008-4ec5-99c6-aa5669520124