Skip to content

File tree

12 files changed

+250
-139
lines changed

12 files changed

+250
-139
lines changed

app/src/main/java/com/osfans/trime/data/theme/ColorManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ object ColorManager {
351351
key: String,
352352
border: Int = 0,
353353
borderColorKey: String = "",
354-
roundCorner: Int = 0,
354+
roundCorner: Float = 0f,
355355
alpha: Int = 255,
356356
): Drawable? {
357357
val value = getColorValue(key)
@@ -363,7 +363,7 @@ object ColorManager {
363363
if (value is Int) {
364364
val gradient = GradientDrawable().apply { setColor(value) }
365365
if (roundCorner > 0) {
366-
gradient.cornerRadius = roundCorner.toFloat()
366+
gradient.cornerRadius = roundCorner
367367
}
368368
if (borderColorKey.isNotEmpty() && border > 0) {
369369
val borderPx = context.dp(border)

app/src/main/java/com/osfans/trime/data/theme/mapper/GeneralStyleMapper.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class GeneralStyleMapper(
1717
val backgroundDimAmount = getFloat("background_dim_amount")
1818

1919
val candidateBorder = getInt("candidate_border")
20-
val candidateBorderRound = getInt("candidate_border_round")
20+
val candidateBorderRound = getFloat("candidate_border_round")
2121

2222
val candidateFont = getStringList("candidate_font")
2323

@@ -123,13 +123,13 @@ class GeneralStyleMapper(
123123

124124
val previewOffset = getInt("preview_offset")
125125

126-
val previewTextSize = getInt("preview_text_size")
126+
val previewTextSize = getFloat("preview_text_size")
127127

128128
val proximityCorrection = getBoolean("proximity_correction")
129129

130130
val resetASCIIMode = getBoolean("reset_ascii_mode")
131131

132-
val roundCorner = getInt("round_corner")
132+
val roundCorner = getFloat("round_corner")
133133

134134
val shadowRadius = getFloat("shadow_radius")
135135

app/src/main/java/com/osfans/trime/data/theme/mapper/LayoutStyleMapper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class LayoutStyleMapper(
5151

5252
val spacing = getInt("spacing")
5353

54-
val roundCorner = getInt("round_corner")
54+
val roundCorner = getFloat("round_corner")
5555

5656
val alpha = getInt("alpha")
5757
val elevation = getInt("elevation")

app/src/main/java/com/osfans/trime/data/theme/model/GeneralStyle.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ data class GeneralStyle(
1010
val autoCaps: String,
1111
val backgroundDimAmount: Float,
1212
val candidateBorder: Int,
13-
val candidateBorderRound: Int,
13+
val candidateBorderRound: Float,
1414
val candidateFont: List<String>,
1515
val candidatePadding: Int,
1616
val candidateSpacing: Float,
@@ -60,10 +60,10 @@ data class GeneralStyle(
6060
val previewFont: List<String>,
6161
val previewHeight: Int,
6262
val previewOffset: Int,
63-
val previewTextSize: Int,
63+
val previewTextSize: Float,
6464
val proximityCorrection: Boolean,
6565
val resetASCIIMode: Boolean,
66-
val roundCorner: Int,
66+
val roundCorner: Float,
6767
val shadowRadius: Float,
6868
val speechOpenccConfig: String,
6969
val symbolFont: List<String>,

app/src/main/java/com/osfans/trime/data/theme/model/Layout.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ data class Layout(
2525
val lineSpacingMultiplier: Float,
2626
val realMargin: Int,
2727
val spacing: Int,
28-
val roundCorner: Int,
28+
val roundCorner: Float,
2929
val alpha: Int,
3030
val elevation: Int,
3131
val movable: String,

app/src/main/java/com/osfans/trime/ime/core/InputView.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import com.osfans.trime.ime.dependency.InputComponent
3636
import com.osfans.trime.ime.dependency.create
3737
import com.osfans.trime.ime.keyboard.KeyboardPrefs.isLandscapeMode
3838
import com.osfans.trime.ime.keyboard.KeyboardWindow
39+
import com.osfans.trime.ime.preview.KeyPreviewChoreographer
3940
import com.osfans.trime.ime.symbol.LiquidKeyboard
4041
import com.osfans.trime.util.ColorUtils
4142
import com.osfans.trime.util.styledFloat
@@ -109,6 +110,7 @@ class InputView(
109110
private val keyboardWindow: KeyboardWindow = inputComponent.keyboardWindow
110111
private val liquidKeyboard: LiquidKeyboard = inputComponent.liquidKeyboard
111112
private val compactCandidate: CompactCandidateModule = inputComponent.compactCandidate
113+
private val preview: KeyPreviewChoreographer = inputComponent.preview
112114

113115
private fun addBroadcastReceivers() {
114116
broadcaster.addReceiver(quickBar)
@@ -263,6 +265,13 @@ class InputView(
263265
bottomOfParent()
264266
},
265267
)
268+
269+
add(
270+
preview.root,
271+
lParams(matchParent, matchParent) {
272+
centerInParent()
273+
},
274+
)
266275
}
267276

268277
private fun updateKeyboardSize() {
@@ -409,6 +418,7 @@ class InputView(
409418
// implies that InputView should not be attached again after detached.
410419
callbackHandlerJob.cancel()
411420
updateWindowViewHeightJob.cancel()
421+
preview.root.removeAllViews()
412422
broadcaster.clear()
413423
super.onDetachedFromWindow()
414424
}

app/src/main/java/com/osfans/trime/ime/dependency/InputComponent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import com.osfans.trime.ime.core.InputView
1616
import com.osfans.trime.ime.core.TrimeInputMethodService
1717
import com.osfans.trime.ime.keyboard.CommonKeyboardActionListener
1818
import com.osfans.trime.ime.keyboard.KeyboardWindow
19+
import com.osfans.trime.ime.preview.KeyPreviewChoreographer
1920
import com.osfans.trime.ime.symbol.LiquidKeyboard
2021
import com.osfans.trime.ime.window.BoardWindowManager
2122
import me.tatarka.inject.annotations.Component
@@ -36,6 +37,7 @@ abstract class InputComponent(
3637
abstract val quickBar: QuickBar
3738
abstract val composition: CompositionPopupWindow
3839
abstract val windowManager: BoardWindowManager
40+
abstract val preview: KeyPreviewChoreographer
3941
abstract val keyboardWindow: KeyboardWindow
4042
abstract val liquidKeyboard: LiquidKeyboard
4143
abstract val compactCandidate: CompactCandidateModule

app/src/main/java/com/osfans/trime/ime/keyboard/KeyboardView.kt

Lines changed: 29 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,18 @@ import android.graphics.drawable.StateListDrawable
1919
import android.os.Message
2020
import android.view.GestureDetector
2121
import android.view.GestureDetector.SimpleOnGestureListener
22-
import android.view.Gravity
2322
import android.view.MotionEvent
2423
import android.view.View
25-
import android.view.ViewGroup
26-
import android.widget.PopupWindow
27-
import androidx.core.view.updateLayoutParams
2824
import com.osfans.trime.core.Rime
2925
import com.osfans.trime.data.prefs.AppPrefs
3026
import com.osfans.trime.data.theme.ColorManager
3127
import com.osfans.trime.data.theme.FontManager
3228
import com.osfans.trime.data.theme.Theme
29+
import com.osfans.trime.ime.preview.KeyPreviewChoreographer
3330
import com.osfans.trime.util.LeakGuardHandlerWrapper
3431
import com.osfans.trime.util.indexOfStateSet
3532
import com.osfans.trime.util.sp
3633
import com.osfans.trime.util.stateDrawableAt
37-
import splitties.dimensions.dp
38-
import splitties.views.dsl.core.textView
39-
import splitties.views.dsl.core.wrapContent
40-
import splitties.views.gravityBottomCenter
4134
import timber.log.Timber
4235
import java.util.Arrays
4336
import kotlin.math.abs
@@ -51,6 +44,7 @@ class KeyboardView(
5144
context: Context,
5245
private val theme: Theme,
5346
private val keyboard: Keyboard,
47+
private val keyPreviewChoreographer: KeyPreviewChoreographer,
5448
) : View(context) {
5549
private var mCurrentKeyIndex = NOT_A_KEY
5650
private val keyTextSize = theme.generalStyle.keyTextSize
@@ -85,32 +79,8 @@ class KeyboardView(
8579
private val mShadowRadius = theme.generalStyle.shadowRadius
8680
private val mShadowColor = ColorManager.getColor("shadow_color")!!
8781

88-
private val mPreviewText =
89-
textView {
90-
textSize = theme.generalStyle.previewTextSize.toFloat()
91-
typeface = FontManager.getTypeface("preview_font")
92-
ColorManager.getColor("preview_text_color")?.let { setTextColor(it) }
93-
ColorManager.getColor("preview_back_color")?.let {
94-
background =
95-
GradientDrawable().apply {
96-
setColor(it)
97-
cornerRadius = theme.generalStyle.roundCorner.toFloat()
98-
}
99-
}
100-
gravity = gravityBottomCenter
101-
layoutParams = ViewGroup.LayoutParams(wrapContent, wrapContent)
102-
}
103-
private val mPreviewPopup =
104-
PopupWindow(context).apply {
105-
contentView = mPreviewText
106-
isTouchable = false
107-
}
108-
private val mPreviewOffset = theme.generalStyle.previewOffset
109-
private val mPreviewHeight = theme.generalStyle.previewHeight
110-
11182
// Working variable
112-
private val mCoordinates = IntArray(2)
113-
private var mPopupParent: View = this
83+
private val originCoords = intArrayOf(0, 0)
11484
private val mKeys get() = keyboard.keys
11585

11686
var keyboardActionListener: KeyboardActionListener? = null
@@ -199,8 +169,7 @@ class KeyboardView(
199169
val mKeyboardView = getOwnerInstanceOrNull() ?: return
200170
val repeatInterval by AppPrefs.defaultInstance().keyboard.repeatInterval
201171
when (msg.what) {
202-
MSG_SHOW_PREVIEW -> mKeyboardView.showKey(msg.arg1, KeyBehavior.entries[msg.arg2])
203-
MSG_REMOVE_PREVIEW -> mKeyboardView.mPreviewPopup.dismiss()
172+
MSG_REMOVE_PREVIEW -> mKeyboardView.dismissKeyPreviewWithoutDelay(msg.obj as Key)
204173
MSG_REPEAT ->
205174
if (mKeyboardView.repeatKey()) {
206175
val repeat = Message.obtain(this, MSG_REPEAT)
@@ -216,7 +185,6 @@ class KeyboardView(
216185
}
217186

218187
init {
219-
setKeyboardBackground()
220188
computeProximityThreshold(keyboard)
221189
invalidateAllKeys()
222190
}
@@ -356,12 +324,28 @@ class KeyboardView(
356324
},
357325
).apply { setIsLongpressEnabled(false) }
358326

359-
private fun setKeyboardBackground() {
360-
val d = mPreviewText.background
361-
if (d is GradientDrawable) {
362-
d.cornerRadius = keyboard.roundCorner
363-
mPreviewText.background = d
327+
private fun showKeyPreview(
328+
key: Key,
329+
behavior: KeyBehavior,
330+
) {
331+
getLocationInWindow(originCoords)
332+
keyPreviewChoreographer.placeAndShowKeyPreview(key, key.getPreviewText(behavior), width, originCoords)
333+
}
334+
335+
private fun dismissKeyPreviewWithoutDelay(key: Key) {
336+
keyPreviewChoreographer.dismissKeyPreview(key)
337+
invalidateKey(key)
338+
}
339+
340+
private fun dismissKeyPreview(key: Key) {
341+
if (isHardwareAccelerated) {
342+
keyPreviewChoreographer.dismissKeyPreview(key)
343+
return
364344
}
345+
mHandler.sendMessageDelayed(
346+
mHandler.obtainMessage(MSG_REMOVE_PREVIEW, key),
347+
DELAY_AFTER_PREVIEW,
348+
)
365349
}
366350

367351
/**
@@ -714,7 +698,6 @@ class KeyboardView(
714698
behavior: KeyBehavior = KeyBehavior.COMPOSING,
715699
) {
716700
val oldKeyIndex = mCurrentKeyIndex
717-
val previewPopup = mPreviewPopup
718701
mCurrentKeyIndex = keyIndex
719702
// Release the old key and press the new key
720703
val keys = mKeys
@@ -732,88 +715,12 @@ class KeyboardView(
732715
}
733716
// If key changed and preview is on ...
734717
if (oldKeyIndex != mCurrentKeyIndex && showPreview) {
735-
mHandler.removeMessages(MSG_SHOW_PREVIEW)
736-
if (previewPopup.isShowing) {
737-
if (keyIndex == NOT_A_KEY) {
738-
mHandler.sendMessageDelayed(
739-
mHandler.obtainMessage(MSG_REMOVE_PREVIEW),
740-
DELAY_AFTER_PREVIEW.toLong(),
741-
)
742-
}
743-
}
744-
if (keyIndex != -1) {
745-
if (previewPopup.isShowing && mPreviewText.visibility == VISIBLE) {
746-
// Show right away, if it's already visible and finger is moving around
747-
showKey(keyIndex, behavior)
748-
} else {
749-
mHandler.sendMessageDelayed(
750-
mHandler.obtainMessage(MSG_SHOW_PREVIEW, keyIndex, behavior.ordinal),
751-
DELAY_BEFORE_PREVIEW.toLong(),
752-
)
753-
}
754-
}
755-
}
756-
}
757-
758-
private fun showKey(
759-
index: Int,
760-
behavior: KeyBehavior,
761-
) {
762-
val previewPopup = mPreviewPopup
763-
if (index !in mKeys.indices) return
764-
val key = mKeys[index]
765-
mPreviewText.setCompoundDrawables(null, null, null, null)
766-
mPreviewText.text = key.getPreviewText(behavior)
767-
mPreviewText.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
768-
val popupWidth =
769-
max(
770-
mPreviewText.measuredWidth,
771-
key.width + mPreviewText.paddingLeft + mPreviewText.paddingRight,
772-
)
773-
val popupHeight = dp(mPreviewHeight)
774-
mPreviewText.updateLayoutParams {
775-
width = popupWidth
776-
height = popupHeight
777-
}
778-
var mPopupPreviewY: Int
779-
var mPopupPreviewX: Int
780-
val mPreviewCentered = false
781-
if (!mPreviewCentered) {
782-
mPopupPreviewX = key.x - mPreviewText.paddingLeft + paddingLeft
783-
mPopupPreviewY = key.y - popupHeight + dp(mPreviewOffset)
784-
} else {
785-
// TODO: Fix this if centering is brought back
786-
mPopupPreviewX = 160 - mPreviewText.measuredWidth / 2
787-
mPopupPreviewY = -mPreviewText.measuredHeight
788-
}
789-
mHandler.removeMessages(MSG_REMOVE_PREVIEW)
790-
getLocationInWindow(mCoordinates)
791-
792-
// Set the preview background state
793-
mPreviewText.background.setState(EMPTY_STATE_SET)
794-
mPopupPreviewX += mCoordinates[0]
795-
mPopupPreviewY += mCoordinates[1]
796-
797-
// If the popup cannot be shown above the key, put it on the side
798-
getLocationOnScreen(mCoordinates)
799-
if (mPopupPreviewY + mCoordinates[1] < 0) {
800-
// If the key you're pressing is on the left side of the keyboard, show the popup on
801-
// the right, offset by enough to see at least one key to the left/right.
802-
if (key.x + key.width <= width / 2) {
803-
mPopupPreviewX += (key.width * 2.5).toInt()
718+
if (keyIndex == NOT_A_KEY) {
719+
dismissKeyPreview(keys[oldKeyIndex])
804720
} else {
805-
mPopupPreviewX -= (key.width * 2.5).toInt()
721+
showKeyPreview(keys[keyIndex], behavior)
806722
}
807-
mPopupPreviewY += popupHeight
808-
}
809-
if (previewPopup.isShowing) {
810-
// previewPopup.update(mPopupPreviewX, mPopupPreviewY, popupWidth, popupHeight);
811-
previewPopup.dismiss() // 禁止窗口動畫
812723
}
813-
previewPopup.width = popupWidth
814-
previewPopup.height = popupHeight
815-
previewPopup.showAtLocation(mPopupParent, Gravity.NO_GRAVITY, mPopupPreviewX, mPopupPreviewY)
816-
mPreviewText.visibility = VISIBLE
817724
}
818725

819726
/**
@@ -1157,13 +1064,9 @@ class KeyboardView(
11571064
private fun removeMessages() {
11581065
mHandler.removeMessages(MSG_REPEAT)
11591066
mHandler.removeMessages(MSG_LONGPRESS)
1160-
mHandler.removeMessages(MSG_SHOW_PREVIEW)
11611067
}
11621068

11631069
fun onDetach() {
1164-
if (mPreviewPopup.isShowing) {
1165-
mPreviewPopup.dismiss()
1166-
}
11671070
removeMessages()
11681071
freeDrawingBuffer()
11691072
}
@@ -1192,12 +1095,10 @@ class KeyboardView(
11921095

11931096
companion object {
11941097
private const val NOT_A_KEY = -1
1195-
private const val MSG_SHOW_PREVIEW = 1
11961098
private const val MSG_REMOVE_PREVIEW = 2
11971099
private const val MSG_REPEAT = 3
11981100
private const val MSG_LONGPRESS = 4
1199-
private const val DELAY_BEFORE_PREVIEW = 0
1200-
private const val DELAY_AFTER_PREVIEW = 70
1101+
private const val DELAY_AFTER_PREVIEW = 100L
12011102
private const val DEBOUNCE_TIME = 70
12021103
private const val MAX_NEARBY_KEYS = 12
12031104
}

0 commit comments

Comments
 (0)