Skip to content

Instantly share code, notes, and snippets.

@zach-klippenstein
Created May 13, 2021 20:09
Show Gist options
  • Save zach-klippenstein/9f19292525e19852f28d4118babb8eb0 to your computer and use it in GitHub Desktop.
Save zach-klippenstein/9f19292525e19852f28d4118babb8eb0 to your computer and use it in GitHub Desktop.
Custom fork of ContextThemeWrapper that does some extra stuff to support overriding configurations better.
/**
* Fork of AppCompat ContextThemeWrapper (barely) to correctly support applying override
* configurations – all the features we don't need are dropped, it always extends the base context's
* theme, the theme can't be set explicitly, and it adds one critical piece of functionality: the new
* theme is [rebased][Theme.rebase] after being cloned from the base context's theme.
*/
open class ContextConfigThemeWrapper(
base: Context,
private val overrideConfiguration: Configuration
) : ContextWrapper(base) {
private val layoutInflater: LayoutInflater by lazy(NONE) {
LayoutInflater.from(baseContext)
.cloneInContext(this)
}
private val resourceContext: Context by lazy(NONE) {
createConfigurationContext(overrideConfiguration)
}
private val _theme: Theme by lazy(NONE) {
resources.newTheme().apply {
setTo(baseContext.theme)
// I don't know why this is required, but without it, child ContextThemeWrappers that use a
// different theme will fail to resolve attributes specified by this theme.
if (VERSION.SDK_INT >= VERSION_CODES.Q) {
rebase()
}
}
}
// Ensure we're returning assets with the correct configuration.
override fun getAssets(): AssetManager = resources.assets
override fun getResources(): Resources = resourceContext.resources
override fun setTheme(resid: Int) {
throw UnsupportedOperationException()
}
override fun getTheme(): Theme = _theme
override fun getSystemService(name: String): Any =
if (LAYOUT_INFLATER_SERVICE == name) layoutInflater else baseContext.getSystemService(name)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment