Skip to content

Commit 6e7548d

Browse files
committed
refactor: make candidates window can show at fixed position perfectly
1 parent f835f4a commit 6e7548d

File tree

2 files changed

+60
-50
lines changed

2 files changed

+60
-50
lines changed

app/src/main/java/com/osfans/trime/ime/composition/ComposingPopupWindow.kt

+57-49
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ class ComposingPopupWindow(
3333
private val service: TrimeInputMethodService,
3434
private val rime: RimeSession,
3535
private val theme: Theme,
36-
private val anchorView: View,
36+
private val parentView: View,
3737
) {
3838
val root = CandidatesView(service, rime, theme)
3939

40+
var useVirtualKeyboard: Boolean = true
41+
4042
// 悬浮窗口彈出位置
4143
private val position by AppPrefs.defaultInstance().candidates.position
4244

@@ -72,56 +74,62 @@ class ComposingPopupWindow(
7274

7375
private val positionUpdater =
7476
Runnable {
75-
anchorView.let { anchor ->
76-
val x: Int
77-
val y: Int
78-
root.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
79-
root.requestLayout()
80-
val selfWidth = root.width
81-
val selfHeight = root.height
82-
val parentWidth = anchor.width
83-
val parentHeight = anchor.height
84-
85-
val minX = 0
86-
val minY = 0
87-
val maxX = parentWidth - selfWidth
88-
val maxY = parentHeight - selfHeight
89-
when (position) {
90-
PopupPosition.TOP_RIGHT -> {
91-
x = maxX
92-
y = minY
93-
}
94-
PopupPosition.TOP_LEFT -> {
95-
x = minX
96-
y = minY
97-
}
98-
PopupPosition.BOTTOM_RIGHT -> {
99-
x = maxX
100-
y = maxY
101-
}
102-
PopupPosition.BOTTOM_LEFT -> {
103-
x = minX
104-
y = maxY
105-
}
106-
PopupPosition.FOLLOW -> {
107-
val (horizontal, top, _, bottom) = anchorPosition
108-
x =
109-
if (root.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
110-
val rtlOffset = parentWidth - horizontal
111-
if (rtlOffset + selfWidth > parentWidth) selfWidth - parentWidth else -rtlOffset
112-
} else {
113-
if (horizontal + selfWidth > parentWidth) parentWidth - selfWidth else horizontal
114-
}.toInt()
115-
y = (if (bottom + selfHeight > parentHeight) top - selfHeight else bottom).toInt()
116-
}
117-
}
118-
if (!window.isShowing) {
119-
window.showAtLocation(anchor, Gravity.NO_GRAVITY, x, y)
77+
val x: Int
78+
val y: Int
79+
root.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
80+
root.requestLayout()
81+
val selfWidth = root.width
82+
val selfHeight = root.height
83+
val (horizontal, top, _, bottom) = anchorPosition
84+
val parentWidth = parentView.width
85+
val parentHeight = parentView.height
86+
val (_, inputViewHeight) =
87+
intArrayOf(0, 0)
88+
.also { service.inputView?.keyboardView?.getLocationInWindow(it) }
89+
90+
val minX = 0
91+
val minY = 0
92+
val maxX = parentWidth - selfWidth
93+
val maxY =
94+
if (useVirtualKeyboard) {
95+
inputViewHeight - selfHeight
12096
} else {
121-
/* must use the width and height of popup window itself here directly,
122-
* otherwise the width and height cannot be updated! */
123-
window.update(x, y, -1, -1)
97+
parentHeight - selfHeight
12498
}
99+
when (position) {
100+
PopupPosition.TOP_RIGHT -> {
101+
x = maxX
102+
y = minY
103+
}
104+
PopupPosition.TOP_LEFT -> {
105+
x = minX
106+
y = minY
107+
}
108+
PopupPosition.BOTTOM_RIGHT -> {
109+
x = maxX
110+
y = maxY
111+
}
112+
PopupPosition.BOTTOM_LEFT -> {
113+
x = minX
114+
y = maxY
115+
}
116+
PopupPosition.FOLLOW -> {
117+
x =
118+
if (root.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
119+
val rtlOffset = parentWidth - horizontal
120+
if (rtlOffset + selfWidth > parentWidth) selfWidth - parentWidth else -rtlOffset
121+
} else {
122+
if (horizontal + selfWidth > parentWidth) parentWidth - selfWidth else horizontal
123+
}.toInt()
124+
y = (if (bottom + selfHeight > parentHeight) top - selfHeight else bottom).toInt()
125+
}
126+
}
127+
if (!window.isShowing) {
128+
window.showAtLocation(parentView, Gravity.NO_GRAVITY, x, y)
129+
} else {
130+
/* must use the width and height of popup window itself here directly,
131+
* otherwise the width and height cannot be updated! */
132+
window.update(x, y, -1, -1)
125133
}
126134
}
127135

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ class InputDeviceManager {
2222
private val candidatesMode by AppPrefs.defaultInstance().candidates.mode
2323

2424
private fun setupInputViewCallback(isVirtual: Boolean) {
25-
inputView?.handleCallback = isVirtual
25+
val shouldSetupInputView = isVirtual && candidatesMode != PopupCandidatesMode.FORCE_SHOW
26+
inputView?.handleCallback = shouldSetupInputView
2627
inputView?.visibility = if (isVirtual) View.VISIBLE else View.GONE
2728
}
2829

2930
private fun setupComposingPopupWindowCallback(isVirtual: Boolean) {
3031
val shouldSetupWindow = !isVirtual || candidatesMode == PopupCandidatesMode.FORCE_SHOW
3132
composingPopupWindow?.handleCallback = shouldSetupWindow
33+
composingPopupWindow?.useVirtualKeyboard = isVirtual
3234
// dismiss ComposingPopupWindow when entering virtual keyboard mode,
3335
// but preserve the visibility when entering physical keyboard mode (in case it's empty)
3436
if (!shouldSetupWindow) {

0 commit comments

Comments
 (0)