Skip to content
CleverKeys Wiki
implemented v1.2.10 User guide

Emoji Technical Specification

Overview

Emoji keyboard implementation with suggestion bar-based search, category navigation, and recent history.

Key Components

ComponentFilePurpose
EmojiSearchManagerEmojiSearchManager.ktSearch state and query routing
EmojiGridViewEmojiGridView.ktEmoji grid rendering
EmojiEmoji.ktEmoji data with 500+ searchable names
EmojiGroupButtonsBarEmojiGroupButtonsBar.ktCategory navigation
SuggestionBarSuggestionBar.ktSearch status display
KeyValueKeyValue.ktEmoji as KeyValue.Char
SharedPreferences-Recent emoji storage

Architecture

User types → KeyEventHandler → KeyboardReceiver → EmojiSearchManager

SuggestionBar ← showEmojiSearchStatus() ← updateSearchDisplay()

EmojiGridView ← searchEmojis() ← Emoji.searchByName()

Search Manager

// EmojiSearchManager.kt
class EmojiSearchManager(
    private val suggestionBarProvider: () -> SuggestionBar?,
    private val emojiGridProvider: () -> EmojiGridView?
) {
    fun enterSearchMode(initialQuery: String? = null)
    fun exitSearchMode()
    fun appendToSearch(text: String)
    fun deleteFromSearch()
    fun extractWordBeforeCursor(textBeforeCursor: CharSequence?): String?
}

Name Mapping

// Emoji.kt initNameMap()
// 500+ emoji name mappings organized by category:
// - Faces: smile, happy, sad, angry, cry, love, etc.
// - Gestures: thumbs, wave, clap, pray, etc.
// - Animals: dog, cat, bird, fish, etc.
// - Food: pizza, burger, apple, etc.
// Supports partial matching with lowercase normalization

Emoji Categories

// EmojiCategory.kt
enum class EmojiCategory(val icon: Int, val label: String) {
    RECENT(R.drawable.ic_recent, "Recent"),
    SMILEYS(R.drawable.ic_smiley, "Smileys"),
    PEOPLE(R.drawable.ic_people, "People"),
    ANIMALS(R.drawable.ic_animals, "Animals"),
    FOOD(R.drawable.ic_food, "Food"),
    ACTIVITIES(R.drawable.ic_activities, "Activities"),
    TRAVEL(R.drawable.ic_travel, "Travel"),
    OBJECTS(R.drawable.ic_objects, "Objects"),
    SYMBOLS(R.drawable.ic_symbols, "Symbols"),
    FLAGS(R.drawable.ic_flags, "Flags")
}

Recent Emoji Storage

// Storage format in SharedPreferences
// Key: "recent_emoji"
// Value: JSON array of recent emoji codepoints
// ["😀", "🎉", "❤️", "👍", ...]
// Max size: 50 entries (configurable)

Emoji Insertion

// EmojiGridView.kt:~120
fun onEmojiSelected(emoji: String) {
    // Add to recent
    addToRecent(emoji)

    // Send to input connection
    val ic = inputConnection ?: return
    ic.commitText(emoji, 1)

    // Trigger haptic
    triggerHaptic(HapticEvent.KEY_PRESS)
}

Skin Tone Variants

Emoji with skin tone support use Unicode modifiers:

ModifierUnicodeSkin Tone
🏻U+1F3FBLight
🏼U+1F3FCMedium-Light
🏽U+1F3FDMedium
🏾U+1F3FEMedium-Dark
🏿U+1F3FFDark
// Stored preference per base emoji
// Key: "emoji_skin_tone_{codepoint}"
// Value: modifier codepoint or null

Layout Integration

Emoji key defined in layout XML:

<!-- bottom_row.xml -->
<key key0="loc emoji" ... />

KeyValue type: KeyValue.Event(Event.SWITCH_EMOJI)

Configuration

SettingKeyDefault
Recent Countemoji_recent_count50
Show Skin Variantsemoji_skin_variantstrue
Default Categoryemoji_default_categoryRECENT

EmojiCompat Integration

Uses AndroidX EmojiCompat for consistent rendering:

// Application.kt
EmojiCompat.init(
    BundledEmojiCompatConfig(this)
        .setReplaceAll(false)
)