Skip to content

3: Advanced Usage

Kieron Quinn edited this page Jun 27, 2021 · 4 revisions

Replicating MonetCompatActivity

If for whatever reason you are unable to extend from MonetCompatActivity, you can replicate it in your own base activity:

Make sure you implement MonetColorsChangedListener:

abstract class BaseActivity: AppCompatActivity, MonetColorsChangedListener

Declare mutable and force-unwrapping fields for MonetCompat:

private var _monet: MonetCompat? = null
val monet: MonetCompat
    get() {
	return if(_monet == null) throw MonetActivityAccessException()
	else _monet!!
    }

Set up Monet in your onCreate:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //This only sets up if needed, otherwise it'll do nothing
    MonetCompat.setup(this)
    _monet = MonetCompat.getInstance()
    //Pass notifySelf=true here for onMonetColorsChanged to be called as soon as colors are available 
    monet.addMonetColorsChangedListener(this, false)
    monet.updateMonetColors()
}

And tear it down in onDestroy:

override fun onDestroy() {
    super.onDestroy()
    monet.removeMonetColorsChangedListener(this)
    _monet = null
}

To recreate the activity when Monet colors change, call recreate() in onMonetColorsChanged:

override fun onMonetColorsChanged(monet: MonetCompat, monetColors: DynamicColorScheme, isInitialChange: Boolean) {
    //Only recreate if this isn't the initial change, ie. the user has likely changed wallpaper
    if(!isInitialChange){
        recreate()
    }
}

Note: If you'd prefer to not recreate the activity when colors change, you may handle the change yourself in onMonetColorsChanged or in your fragments, rather than calling recreate(). Note that onMonetColorsChanged will also be called when the colors are initially loaded, with isInitialChange = false

User-selected Wallpaper Colors

By default, MonetCompat will use the first color returned from WallpaperManager.getWallpaperColors() or from Palette when in Palette compatibility mode as the color for Monet to generate swatches. This is usually the most prominent color from the user's wallpaper, but occasionally it may not be what the user wants. In Android 12, with native Monet, the user is able to override the color picked from their wallpaper, and MonetCompat provides this option too.

MonetCompat.wallpaperColorPicker (static field): Set a custom handler for picking from a list of wallpaper colors

Example:

MonetCompat.wallpaperColorPicker = { colors ->
    val selectedColor = settings.monetColor
    if(selectedColor != Integer.MAX_VALUE && colors?.contains(selectedColor) == true) selectedColor
    else colors?.firstOrNull()
}

In the example, we have an instance of a Settings class which wraps SharedPreferences, saving the user's overridden color (if they have chosen one) as an Int, with the default value of Integer.MAX_VALUE. If the colors list contains the selected color, it will be used. Otherwise, the first color in the list will be used, as normal. If the colors list is null (which is the case when the wallpaper colors could not be extracted, for example if there's an incompatible live wallpaper in use), null will be returned and MonetCompat will use the default color.

Providing a UI for picking colors

It's up to you how you wish to show the color options to the user (though this is supported by the sample, if you want a basic example). MonetCompat does however provide you with two helper method that may help you:

getAvailableWallpaperColors() (suspend fun): Returns a list of colors picked from the user's wallpaper

This will return null if colors could not be extracted from the wallpaper, for example if an incompatible live wallpaper is in use.

getSelectedWallpaperColor() (suspend fun): Returns the currently selected wallpaper color, run through wallpaperColorPicker

This will return null if colors could not be extracted from the wallpaper, for example if an incompatible live wallpaper is in use.

Chroma Multiplier

chromaMultiplier: Set the multiplier apply to the chroma value of generated colors. Defaults to 1.0

Wallpaper Source

wallpaperSource: Set which wallpaper to use for color extraction

Available options:

WallpaperTypes.WALLPAPER_SYSTEM: The home screen (system) wallpaper - Default

WallpaperTypes.WALLPAPER_LOCK_SCREEN: The lock screen wallpaper

Note: Due to system limitations, this option will be ignored on Android 8.0 or below (AOSP did not support lock screen wallpapers before this time)

MonetCompatActivity

applyBackgroundColorToWindow: Automatically applies the Monet generated background color to the window**

updateOnCreate: (defaults to enabled): Disable to prevent calling MonetCompat.updateMonetColors() automatically when the activity is created. In a multi-activity app, you may wish to set this to false on activities other than your root to save CPU usage (onMonetColorsChanged and recreate will not be called if the colors don't change, but Monet will still re-generate colors for all activities if this is enabled on them all)

applyBackgroundColorToMenu: Automatically applies the Monet generated secondary background color to any Toolbar menus, or the main background color if the secondary background isn't available

Note: Due to how Toolbar popup menus work, it's not possible with the default implementation to only apply to some menus. You may wish to copy and modify the implementation in your own activity to make it specific to your requirments.

MonetFragment

updateOnCreate: (defaults to disabled): Similar to the above, enable to call MonetCompat.updateMonetColors automatically when the fragment is created. You may wish to enable this if you are not using MonetCompatActivity`.