mirror of
https://github.com/florisboard/florisboard.git
synced 2024-09-20 03:52:18 +02:00
Implement Kotlin coroutines to load EmojiKeyboardView async
- UI for EmojiKeyboardView is now loaded async upon creating the FlorisBoard UI, so it is ready when the user switches to the media context. - Other small fixes.
This commit is contained in:
parent
a5da7f1529
commit
315e6a3b2c
@ -37,4 +37,6 @@ dependencies {
|
||||
implementation 'com.google.android:flexbox:2.0.1'
|
||||
implementation "com.squareup.moshi:moshi-kotlin:1.9.2"
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7"
|
||||
}
|
||||
|
@ -66,7 +66,13 @@ class MediaInputManager(private val florisboard: FlorisBoard) : FlorisBoard.Even
|
||||
override fun onTabReselected(tab: TabLayout.Tab) {}
|
||||
})
|
||||
|
||||
setActiveTab(Tab.HOME)
|
||||
for (tab in Tab.values()) {
|
||||
val tabView = createTabViewFor(tab)
|
||||
tabViews[tab] = tabView
|
||||
mediaViewFlipper?.addView(tabView)
|
||||
}
|
||||
|
||||
tabLayout?.selectTab(tabLayout?.getTabAt(1))
|
||||
}
|
||||
|
||||
private fun onBottomButtonClick(v: View) {
|
||||
@ -95,11 +101,6 @@ class MediaInputManager(private val florisboard: FlorisBoard) : FlorisBoard.Even
|
||||
}
|
||||
|
||||
fun setActiveTab(newActiveTab: Tab) {
|
||||
if (!tabViews.containsKey(newActiveTab)) {
|
||||
val tabView = createTabViewFor(newActiveTab)
|
||||
tabViews[newActiveTab] = tabView
|
||||
mediaViewFlipper?.addView(tabView)
|
||||
}
|
||||
mediaViewFlipper?.displayedChild =
|
||||
mediaViewFlipper?.indexOfChild(tabViews[newActiveTab]) ?: 0
|
||||
activeTab = newActiveTab
|
||||
|
@ -6,7 +6,6 @@ import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.MotionEvent
|
||||
import android.widget.HorizontalScrollView
|
||||
import androidx.core.content.ContextCompat
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.core.FlorisBoard
|
||||
|
||||
@ -15,13 +14,13 @@ class EmojiKeyView(
|
||||
private val florisboard: FlorisBoard,
|
||||
private val emojiKeyboardView: EmojiKeyboardView,
|
||||
val data: EmojiKeyData
|
||||
) : androidx.appcompat.widget.AppCompatButton(florisboard.context) {
|
||||
) : androidx.appcompat.widget.AppCompatTextView(florisboard.context) {
|
||||
|
||||
private var isCancelled: Boolean = false
|
||||
private val osHandler = Handler()
|
||||
private var osHandler: Handler? = null
|
||||
|
||||
init {
|
||||
setBackgroundColor(ContextCompat.getColor(context, android.R.color.transparent))
|
||||
background = null
|
||||
gravity = Gravity.CENTER
|
||||
setPadding(0, 0, 0, 0)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.emoji_key_textSize))
|
||||
@ -37,7 +36,10 @@ class EmojiKeyView(
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
isCancelled = false
|
||||
val delayMillis = florisboard.prefs!!.longPressDelay
|
||||
osHandler.postDelayed({
|
||||
if (osHandler == null) {
|
||||
osHandler = Handler()
|
||||
}
|
||||
osHandler?.postDelayed({
|
||||
(parent.parent as HorizontalScrollView).requestDisallowInterceptTouchEvent(true)
|
||||
emojiKeyboardView.isScrollBlocked = true
|
||||
emojiKeyboardView.popupManager.show(this)
|
||||
@ -63,7 +65,7 @@ class EmojiKeyView(
|
||||
}
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_CANCEL -> {
|
||||
osHandler.removeCallbacksAndMessages(null)
|
||||
osHandler?.removeCallbacksAndMessages(null)
|
||||
val retData = emojiKeyboardView.popupManager.getActiveEmojiKeyData(this)
|
||||
emojiKeyboardView.popupManager.hide()
|
||||
if (event.actionMasked != MotionEvent.ACTION_CANCEL && retData != null && !isCancelled) {
|
||||
|
@ -14,20 +14,19 @@ import com.google.android.material.tabs.TabLayout
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.core.FlorisBoard
|
||||
import dev.patrickgold.florisboard.ime.popup.KeyPopupManager
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.*
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
class EmojiKeyboardView(
|
||||
private val florisboard: FlorisBoard
|
||||
) : LinearLayout(florisboard.context) {
|
||||
) : LinearLayout(florisboard.context), CoroutineScope by MainScope() {
|
||||
|
||||
private var activeCategory: EmojiCategory = EmojiCategory.SMILEYS_EMOTION
|
||||
private var emojiViewFlipper: ViewFlipper
|
||||
private val emojiKeyWidth = resources.getDimension(R.dimen.emoji_key_width).toInt()
|
||||
private val emojiKeyHeight = resources.getDimension(R.dimen.emoji_key_height).toInt()
|
||||
// TODO: run this task async (coroutines?) to avoid blocking the ui thread
|
||||
private val layouts =
|
||||
parseRawEmojiSpecsFile(context, "ime/emoji/emoji-test.txt")
|
||||
private var layouts: EmojiLayoutDataMap? = null
|
||||
private val uiLayouts = EnumMap<EmojiCategory, HorizontalScrollView>(EmojiCategory::class.java)
|
||||
|
||||
var isScrollBlocked: Boolean = false
|
||||
@ -43,12 +42,6 @@ class EmojiKeyboardView(
|
||||
emojiViewFlipper.measureAllChildren = false
|
||||
addView(emojiViewFlipper)
|
||||
|
||||
for (category in EmojiCategory.values()) {
|
||||
val hsv = buildLayoutForCategory(category)
|
||||
uiLayouts[category] = hsv
|
||||
emojiViewFlipper.addView(hsv)
|
||||
}
|
||||
|
||||
val tabs = ViewGroup.inflate(context, R.layout.media_input_emoji_tabs, null) as TabLayout
|
||||
addView(tabs)
|
||||
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
@ -71,19 +64,37 @@ class EmojiKeyboardView(
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) {}
|
||||
})
|
||||
|
||||
setActiveCategory(EmojiCategory.SMILEYS_EMOTION)
|
||||
launch {
|
||||
layouts = withContext(Dispatchers.IO) {
|
||||
parseRawEmojiSpecsFile(context, "ime/emoji/emoji-test.txt")
|
||||
}
|
||||
buildLayout()
|
||||
setActiveCategory(EmojiCategory.SMILEYS_EMOTION)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun buildLayout() = withContext(Dispatchers.Default) {
|
||||
for (category in EmojiCategory.values()) {
|
||||
val hsv = buildLayoutForCategory(category)
|
||||
uiLayouts[category] = hsv
|
||||
withContext(Dispatchers.Main) {
|
||||
emojiViewFlipper.addView(hsv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun buildLayoutForCategory(category: EmojiCategory): HorizontalScrollView {
|
||||
private suspend fun buildLayoutForCategory(
|
||||
category: EmojiCategory
|
||||
): HorizontalScrollView = withContext(Dispatchers.Default) {
|
||||
val hsv = HorizontalScrollView(context)
|
||||
hsv.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
|
||||
val flexboxLayout = FlexboxLayout(context)
|
||||
flexboxLayout.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, emojiKeyHeight * 3)
|
||||
flexboxLayout.flexDirection = FlexDirection.COLUMN
|
||||
flexboxLayout.flexWrap = FlexWrap.WRAP
|
||||
for (emojiKeyData in layouts[category].orEmpty()) {
|
||||
val emojiKeyView = EmojiKeyView(florisboard, this, emojiKeyData)
|
||||
for (emojiKeyData in layouts.orEmpty()[category].orEmpty()) {
|
||||
val emojiKeyView = EmojiKeyView(florisboard, this@EmojiKeyboardView, emojiKeyData)
|
||||
emojiKeyView.layoutParams = FlexboxLayout.LayoutParams(
|
||||
emojiKeyWidth, emojiKeyHeight
|
||||
)
|
||||
@ -93,7 +104,7 @@ class EmojiKeyboardView(
|
||||
return@setOnTouchListener isScrollBlocked
|
||||
}
|
||||
hsv.addView(flexboxLayout)
|
||||
return hsv
|
||||
return@withContext hsv
|
||||
}
|
||||
|
||||
fun setActiveCategory(newActiveCategory: EmojiCategory) {
|
||||
|
@ -29,6 +29,8 @@ private const val BALD = "1F9B3"
|
||||
private val NAME_JUNK_SPLIT_REGEX = "E([0-9]+)\\.([0-9]+)\\s+".toRegex()
|
||||
private val CODE_POINT_REGEX = "([a-fA-F0-9]+)\\s".toRegex()
|
||||
|
||||
typealias EmojiLayoutDataMap = EnumMap<EmojiCategory, MutableList<EmojiKeyData>>
|
||||
|
||||
private fun listStringToListInt(list: List<String>): List<Int> {
|
||||
val ret: MutableList<Int> = mutableListOf()
|
||||
for (num in list) {
|
||||
@ -41,8 +43,8 @@ private fun listStringToListInt(list: List<String>): List<Int> {
|
||||
|
||||
fun parseRawEmojiSpecsFile(
|
||||
context: Context, path: String
|
||||
): EnumMap<EmojiCategory, MutableList<EmojiKeyData>> {
|
||||
val layouts = EnumMap<EmojiCategory, MutableList<EmojiKeyData>>(EmojiCategory::class.java)
|
||||
): EmojiLayoutDataMap {
|
||||
val layouts = EmojiLayoutDataMap(EmojiCategory::class.java)
|
||||
for (category in EmojiCategory.values()) {
|
||||
layouts[category] = mutableListOf()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user