Skip to content
CleverKeys Wiki
implemented v1.2.7 User guide

Themes Technical Specification

Overview

The theme system provides customizable color schemes for the keyboard, including built-in themes, custom color options, and system theme integration.

Key Components

ComponentFilePurpose
ThemeManagerThemeManager.ktTheme loading and application
ColorSchemeColorScheme.ktColor definitions
KeyboardViewKeyboardView.ktTheme rendering
ConfigConfig.ktTheme preferences

Data Model

Color Scheme

// ColorScheme.kt
data class ColorScheme(
    val name: String,
    val isDark: Boolean,

    // Background colors
    val keyboardBackground: Int,
    val keyBackground: Int,
    val keyBackgroundPressed: Int,

    // Text colors
    val keyText: Int,
    val keyTextSecondary: Int,
    val subkeyText: Int,

    // Accent colors
    val accent: Int,
    val accentSecondary: Int,

    // Prediction bar
    val predictionBarBackground: Int,
    val predictionText: Int,
    val predictionTextActive: Int,

    // Special keys
    val modifierKeyBackground: Int,
    val enterKeyBackground: Int,

    // Borders and shadows
    val keyBorder: Int?,
    val keyShadow: Int?
)

Built-in Themes

// ThemeManager.kt
object BuiltInThemes {
    val CLEVERKEYS_DARK = ColorScheme(
        name = "CleverKeys Dark",
        isDark = true,
        keyboardBackground = 0xFF1a1a2e.toInt(),
        keyBackground = 0xFF16213e.toInt(),
        keyText = 0xFFe8e8e8.toInt(),
        accent = 0xFF7c3aed.toInt(),  // Purple accent
        // ...
    )

    val MIDNIGHT = ColorScheme(
        name = "Midnight",
        isDark = true,
        keyboardBackground = 0xFF000000.toInt(),
        keyBackground = 0xFF1a1a1a.toInt(),
        keyText = 0xFFffffff.toInt(),
        accent = 0xFF3b82f6.toInt(),  // Blue accent
        // ...
    )

    val OCEAN = ColorScheme(...)
    val FOREST = ColorScheme(...)
    val SUNSET = ColorScheme(...)
    val SNOW = ColorScheme(...)
}

Theme Application

Rendering Pipeline

// KeyboardView.kt:~200
private fun applyTheme(theme: ColorScheme) {
    // Background
    backgroundPaint.color = theme.keyboardBackground

    // Key paints
    keyPaint.color = theme.keyBackground
    keyTextPaint.color = theme.keyText

    // Accent elements
    accentPaint.color = theme.accent

    // Optional effects
    if (theme.keyBorder != null) {
        borderPaint.color = theme.keyBorder
        borderPaint.strokeWidth = 1.dp
    }

    if (theme.keyShadow != null) {
        keyPaint.setShadowLayer(2.dp, 0f, 1.dp, theme.keyShadow)
    }

    invalidate()
}

Key Drawing

// KeyboardView.kt:~300
private fun drawKey(canvas: Canvas, key: Key, bounds: RectF) {
    // Background
    val bgColor = when {
        key.isPressed -> theme.keyBackgroundPressed
        key.isModifier -> theme.modifierKeyBackground
        key.isEnter -> theme.enterKeyBackground
        else -> theme.keyBackground
    }
    keyPaint.color = bgColor

    // Draw rounded rectangle
    canvas.drawRoundRect(bounds, cornerRadius, cornerRadius, keyPaint)

    // Border (optional)
    if (theme.keyBorder != null) {
        canvas.drawRoundRect(bounds, cornerRadius, cornerRadius, borderPaint)
    }

    // Key label
    keyTextPaint.color = theme.keyText
    canvas.drawText(key.label, centerX, centerY, keyTextPaint)

    // Subkey hints
    subkeyTextPaint.color = theme.subkeyText
    drawSubkeyHints(canvas, key, bounds)
}

System Theme Integration

// ThemeManager.kt
fun getSystemTheme(context: Context): ColorScheme {
    val isDarkMode = when (context.resources.configuration.uiMode and
                          Configuration.UI_MODE_NIGHT_MASK) {
        Configuration.UI_MODE_NIGHT_YES -> true
        Configuration.UI_MODE_NIGHT_NO -> false
        else -> false
    }

    return if (isDarkMode) {
        BuiltInThemes.CLEVERKEYS_DARK
    } else {
        BuiltInThemes.SNOW
    }
}

// Listen for system theme changes
private val themeChangeReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (config.theme == "system") {
            applyTheme(getSystemTheme(context))
        }
    }
}

Custom Colors

Color Customization

// ThemeManager.kt
fun createCustomTheme(customColors: Map<String, Int>): ColorScheme {
    val baseTheme = getBaseTheme()

    return baseTheme.copy(
        keyboardBackground = customColors["keyboard_background"]
            ?: baseTheme.keyboardBackground,
        keyBackground = customColors["key_background"]
            ?: baseTheme.keyBackground,
        keyText = customColors["key_text"]
            ?: baseTheme.keyText,
        accent = customColors["accent"]
            ?: baseTheme.accent,
        // ... other customizable colors
    )
}

Storage Format

// Config.kt
// Stored as JSON in SharedPreferences
{
    "theme": "custom",
    "custom_colors": {
        "keyboard_background": "#1a1a2e",
        "key_background": "#16213e",
        "key_text": "#ffffff",
        "accent": "#7c3aed"
    }
}

Opacity Settings

// ThemeManager.kt
fun applyOpacity(color: Int, opacity: Float): Int {
    val alpha = (opacity * 255).toInt()
    return (color and 0x00FFFFFF) or (alpha shl 24)
}

// Applied to key backgrounds
val adjustedKeyBg = applyOpacity(theme.keyBackground, config.key_opacity / 100f)

Configuration

SettingKeyDefaultRange
Themepref_theme”cleverkeys_dark”Theme name
Key Opacitykey_opacity1000-100
Background Opacitybackground_opacity1000-100
Border Stylekey_border_style”none”none/subtle/visible