Skip to content

softartdev/MaterialThemePrefs

Repository files navigation

Material Theme Preferences

Maven Central Build & Publish CI/CD

Kotlin Multiplatform library for easy switching Dark/Light Material themes on Compose. Supported platforms:

  • Android
  • iOS
  • Desktop JVM (MacOS, Linux, Windows)

Android screenshot iOS screenshot Desktop screenshot

More…

Usage

Call composable functions to wrap your app, show theme preference items, and handle dialog state manually.

Show dialog directly: Use ThemeAlertDialog to show a dialog with theme preferences:

@Composable
fun App() = PreferableMaterialTheme {
    var showDialog by remember { mutableStateOf(false) }
    SettingsScaffold(onThemeClick = { showDialog = true }) {
        Column {
            ThemePreferencesCategory() // subtitle
            ThemePreferenceItem(onClick = { showDialog = true }) // menu item
        }
    }
    if (showDialog) {
        ThemeAlertDialog(dismissDialog = { showDialog = false })
    }
}

With navigation frameworks: Use ThemeDialogContent as the content of a dialog destination:

@Composable
fun App() = PreferableMaterialTheme {
    val navController = rememberNavController()
    NavHost(navController = navController) {
        composable<AppNavGraph.Settings> {
            SettingsBody(onThemeClick = { navController.navigate(route = AppNavGraph.ThemeDialog) })
        }
        dialog<AppNavGraph.ThemeDialog> {
            ThemeDialogContent(dismissDialog = navController::popBackStack)
        }
    }
}

Check the sample app for using with Material Design versions 2 & 3.

The NoteDelight app is a real example.

Installation

The latest release is available on Maven Central.

Gradle

  1. Add the Maven Central repository if it is not already there:
repositories {
    mavenCentral()
}
  1. In multiplatform projects, add a dependency to the commonMain source set dependencies
commonMain {
    dependencies {
        implementation("io.github.softartdev:theme-material:$latestVersion") // Material Design 2
        implementation("io.github.softartdev:theme-material3:$latestVersion") // Material Design 3
        implementation("io.github.softartdev:theme-prefs:$latestVersion") // optional, if you need only preferences
    }
}

Implementation

Used compose-multiplatform-resources library for many languages (currently Russian and English are supported).

Persisting preferences is implemented using SharedPreferences on Android, and Java Preference API on JVM Desktop.

// common:
expect var themeEnum: ThemeEnum

// android:
private val preferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)

actual var themeEnum: ThemeEnum
    get() = preferences.getInt(THEME_KEY, ThemeEnum.SystemDefault.ordinal).let(ThemeEnum.values()::get)
    set(value) = preferences.edit().putInt(THEME_KEY, value.ordinal).apply()

// desktop java:
private var preferences: Preferences = Preferences.userNodeForPackage(ThemeEnum::class.java)

actual var themeEnum: ThemeEnum
    get() = preferences.getInt(THEME_KEY, ThemeEnum.SystemDefault.ordinal).let(ThemeEnum.values()::get)
    set(value) = preferences.putInt(THEME_KEY, value.ordinal)

// ios:
private val preferences: NSUserDefaults = NSUserDefaults.standardUserDefaults

actual var themeEnum: ThemeEnum
    get() = preferences.integerForKey(THEME_KEY).let(ThemeEnum.values()::get)
    set(value) = preferences.setInteger(value.ordinal, THEME_KEY)

Also used composition local for access from theme-scoped as an implicit way:

val themePrefs: ThemePrefs = LocalThemePrefs.current

Packages

No packages published