Skip to content

Commit 8fe83c8

Browse files
committed
refactor: automatically switch bar view when board window attach or detach
Broadcast the window attach / detach event via InputBroadcaster.
1 parent 281d31a commit 8fe83c8

11 files changed

Lines changed: 136 additions & 77 deletions

File tree

app/src/main/java/com/osfans/trime/ime/bar/QuickBar.kt

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,20 @@ import android.widget.ViewAnimator
88
import com.osfans.trime.core.Rime
99
import com.osfans.trime.core.RimeNotification.OptionNotification
1010
import com.osfans.trime.data.theme.ColorManager
11-
import com.osfans.trime.data.theme.Theme
1211
import com.osfans.trime.databinding.CandidateBarBinding
1312
import com.osfans.trime.ime.broadcast.InputBroadcastReceiver
1413
import com.osfans.trime.ime.core.TrimeInputMethodService
1514
import com.osfans.trime.ime.dependency.InputScope
1615
import com.osfans.trime.ime.enums.SymbolKeyboardType
17-
import com.osfans.trime.ime.symbol.LiquidTabsUi
18-
import com.osfans.trime.ime.symbol.TabManager
16+
import com.osfans.trime.ime.window.BoardWindow
1917
import me.tatarka.inject.annotations.Inject
2018
import splitties.views.dsl.core.add
2119
import splitties.views.dsl.core.lParams
2220
import splitties.views.dsl.core.matchParent
2321

2422
@InputScope
2523
@Inject
26-
class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme) : InputBroadcastReceiver {
24+
class QuickBar(context: Context, service: TrimeInputMethodService) : InputBroadcastReceiver {
2725
val oldCandidateBar by lazy {
2826
CandidateBarBinding.inflate(LayoutInflater.from(context)).apply {
2927
with(root) {
@@ -40,20 +38,23 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme)
4038
}
4139
}
4240

43-
val tabsUi by lazy {
44-
LiquidTabsUi(context, theme).apply {
45-
setTabs(TabManager.tabCandidates)
46-
}
41+
private val tabUi by lazy {
42+
TabUi(context)
4743
}
4844

4945
enum class State {
5046
Candidate,
5147
Tab,
5248
}
5349

54-
fun switchUiByState(state: State) {
55-
if (view.displayedChild == state.ordinal) return
56-
view.displayedChild = state.ordinal
50+
private fun switchUiByState(state: State) {
51+
val index = state.ordinal
52+
if (view.displayedChild == index) return
53+
val new = view.getChildAt(index)
54+
if (new != tabUi.root) {
55+
tabUi.removeExternal()
56+
}
57+
view.displayedChild = index
5758
}
5859

5960
val view by lazy {
@@ -75,7 +76,7 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme)
7576
"candidate_border_round",
7677
)
7778
add(oldCandidateBar.root, lParams(matchParent, matchParent))
78-
add(tabsUi.root, lParams(matchParent, matchParent))
79+
add(tabUi.root, lParams(matchParent, matchParent))
7980
}
8081
}
8182

@@ -89,4 +90,15 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme)
8990
}
9091
}
9192
}
93+
94+
override fun onWindowAttached(window: BoardWindow) {
95+
if (window is BoardWindow.BarBoardWindow) {
96+
window.onCreateBarView()?.let { tabUi.addExternal(it) }
97+
switchUiByState(State.Tab)
98+
}
99+
}
100+
101+
override fun onWindowDetached(window: BoardWindow) {
102+
switchUiByState(State.Candidate)
103+
}
92104
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.osfans.trime.ime.bar
2+
3+
import android.content.Context
4+
import android.view.View
5+
import splitties.views.dsl.constraintlayout.centerInParent
6+
import splitties.views.dsl.constraintlayout.constraintLayout
7+
import splitties.views.dsl.constraintlayout.lParams
8+
import splitties.views.dsl.core.Ui
9+
import splitties.views.dsl.core.add
10+
import splitties.views.dsl.core.matchParent
11+
12+
class TabUi(override val ctx: Context) : Ui {
13+
private var external: View? = null
14+
15+
override val root = constraintLayout { }
16+
17+
fun addExternal(view: View) {
18+
if (external != null) {
19+
throw IllegalStateException("TabBar external view is already present")
20+
}
21+
external = view
22+
root.run {
23+
add(
24+
view,
25+
lParams(matchParent, matchParent) {
26+
centerInParent()
27+
},
28+
)
29+
}
30+
}
31+
32+
fun removeExternal() {
33+
external?.let {
34+
root.removeView(it)
35+
external = null
36+
}
37+
}
38+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
package com.osfans.trime.ime.broadcast
22

33
import com.osfans.trime.core.RimeNotification.OptionNotification
4+
import com.osfans.trime.ime.window.BoardWindow
45

56
interface InputBroadcastReceiver {
67
fun onRimeOptionUpdated(value: OptionNotification.Value) {}
8+
9+
fun onWindowAttached(window: BoardWindow) {}
10+
11+
fun onWindowDetached(window: BoardWindow) {}
712
}

app/src/main/java/com/osfans/trime/ime/broadcast/InputBroadcaster.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.osfans.trime.ime.broadcast
22

33
import com.osfans.trime.core.RimeNotification.OptionNotification
44
import com.osfans.trime.ime.dependency.InputScope
5+
import com.osfans.trime.ime.window.BoardWindow
56
import me.tatarka.inject.annotations.Inject
67
import java.util.concurrent.ConcurrentLinkedQueue
78

@@ -29,4 +30,12 @@ class InputBroadcaster : InputBroadcastReceiver {
2930
override fun onRimeOptionUpdated(value: OptionNotification.Value) {
3031
receivers.forEach { it.onRimeOptionUpdated(value) }
3132
}
33+
34+
override fun onWindowAttached(window: BoardWindow) {
35+
receivers.forEach { it.onWindowAttached(window) }
36+
}
37+
38+
override fun onWindowDetached(window: BoardWindow) {
39+
receivers.forEach { it.onWindowDetached(window) }
40+
}
3241
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,9 @@ class InputView(
305305

306306
fun switchBoard(board: Board) {
307307
when (board) {
308-
Board.Main -> windowManager.attachWindow(keyboardWindow)
309-
Board.Symbol -> windowManager.attachWindow(liquidKeyboard)
308+
Board.Main -> windowManager.attachWindow(KeyboardWindow)
309+
Board.Symbol -> windowManager.attachWindow(LiquidKeyboard)
310310
}
311-
quickBar.switchUiByState(QuickBar.State.entries[board.ordinal])
312311
}
313312

314313
private var showingDialog: Dialog? = null

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

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ import com.osfans.trime.data.theme.ThemeManager
5555
import com.osfans.trime.ime.broadcast.IntentReceiver
5656
import com.osfans.trime.ime.enums.FullscreenMode
5757
import com.osfans.trime.ime.enums.InlinePreeditMode
58-
import com.osfans.trime.ime.enums.KeyCommandType
5958
import com.osfans.trime.ime.enums.Keycode
6059
import com.osfans.trime.ime.enums.SymbolKeyboardType
6160
import com.osfans.trime.ime.keyboard.Event
@@ -64,7 +63,6 @@ import com.osfans.trime.ime.keyboard.InputFeedbackManager
6463
import com.osfans.trime.ime.keyboard.Key
6564
import com.osfans.trime.ime.keyboard.KeyboardSwitcher
6665
import com.osfans.trime.ime.keyboard.KeyboardView
67-
import com.osfans.trime.ime.symbol.LiquidTabsUi
6866
import com.osfans.trime.ime.symbol.TabManager
6967
import com.osfans.trime.ime.text.Candidate
7068
import com.osfans.trime.ime.text.CompositionPopupWindow
@@ -89,7 +87,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
8987
get() = AppPrefs.defaultInstance()
9088
private var mainKeyboardView: KeyboardView? = null // 主軟鍵盤
9189
private var mCandidate: Candidate? = null // 候選
92-
private var liquidTabsUi: LiquidTabsUi? = null
9390
var inputView: InputView? = null
9491
private var initializationUi: InitializationUi? = null
9592
private var eventListeners = WeakHashSet<EventListener>()
@@ -271,7 +268,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
271268
if (tabIndex >= 0) {
272269
inputView!!.switchBoard(InputView.Board.Symbol)
273270
symbolKeyboardType = inputView!!.liquidKeyboard.select(tabIndex)
274-
liquidTabsUi?.activateTab(TabManager.selectedOrZero)
275271
mCompositionPopupWindow?.composition?.compositionView?.changeToLiquidKeyboardToolbar()
276272
showCompositionView(false)
277273
} else {
@@ -319,17 +315,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
319315
mainKeyboardView = inputView!!.keyboardWindow.oldMainInputView.mainKeyboardView
320316
// 初始化候选栏
321317
mCandidate = inputView!!.quickBar.oldCandidateBar.candidates
322-
liquidTabsUi =
323-
inputView!!.quickBar.tabsUi.apply {
324-
setOnTabClickListener {
325-
val tag = TabManager.tabTags[it]
326-
if (tag.type == SymbolKeyboardType.NO_KEY && tag.command == KeyCommandType.EXIT) {
327-
selectLiquidKeyboard(-1)
328-
} else {
329-
selectLiquidKeyboard(it)
330-
}
331-
}
332-
}
333318

334319
mCompositionPopupWindow =
335320
CompositionPopupWindow(this, ThemeManager.activeTheme).apply {
@@ -1134,8 +1119,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
11341119
} else {
11351120
mCandidate!!.setText(0)
11361121
}
1137-
// 刷新候选词后,如果候选词超出屏幕宽度,滚动候选栏
1138-
// mTabRoot?.move(mCandidate!!.highlightLeft, mCandidate!!.highlightRight)
11391122
}
11401123
mainKeyboardView?.invalidateComposingKeys()
11411124
if (!onEvaluateInputViewShown()) setCandidatesViewShown(textInputManager!!.isComposable) // 實體鍵盤打字時顯示候選欄

app/src/main/java/com/osfans/trime/ime/symbol/LiquidKeyboard.kt

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.osfans.trime.ime.symbol
22

33
import android.content.Context
44
import android.view.View
5-
import androidx.core.view.setPadding
65
import androidx.lifecycle.lifecycleScope
76
import androidx.recyclerview.widget.LinearLayoutManager
87
import androidx.recyclerview.widget.StaggeredGridLayoutManager
@@ -21,19 +20,12 @@ import com.osfans.trime.ime.core.TrimeInputMethodService
2120
import com.osfans.trime.ime.dependency.InputScope
2221
import com.osfans.trime.ime.enums.KeyCommandType
2322
import com.osfans.trime.ime.enums.SymbolKeyboardType
24-
import com.osfans.trime.ime.keyboard.KeyboardSwitcher
2523
import com.osfans.trime.ime.text.TextInputManager
2624
import com.osfans.trime.ime.window.BoardWindow
2725
import com.osfans.trime.ime.window.ResidentWindow
2826
import kotlinx.coroutines.launch
2927
import me.tatarka.inject.annotations.Inject
3028
import splitties.dimensions.dp
31-
import splitties.views.dsl.constraintlayout.centerInParent
32-
import splitties.views.dsl.constraintlayout.constraintLayout
33-
import splitties.views.dsl.constraintlayout.lParams
34-
import splitties.views.dsl.core.add
35-
import splitties.views.dsl.core.matchParent
36-
import splitties.views.dsl.recyclerview.recyclerView
3729
import timber.log.Timber
3830

3931
@InputScope
@@ -42,7 +34,8 @@ class LiquidKeyboard(
4234
private val context: Context,
4335
private val service: TrimeInputMethodService,
4436
private val theme: Theme,
45-
) : BoardWindow.NoBarBoardWindow(), ResidentWindow, ClipboardHelper.OnClipboardUpdateListener {
37+
) : BoardWindow.BarBoardWindow(), ResidentWindow, ClipboardHelper.OnClipboardUpdateListener {
38+
private lateinit var liquidLayout: LiquidLayout
4639
private val symbolHistory = SymbolHistory(180)
4740
private var adapterType: AdapterType = AdapterType.INIT
4841
private val simpleAdapter by lazy {
@@ -81,23 +74,22 @@ class LiquidKeyboard(
8174
override val key: ResidentWindow.Key
8275
get() = LiquidKeyboard
8376

84-
private val keyboardView =
85-
context.recyclerView {
86-
val space = dp(3)
87-
addItemDecoration(SpacesItemDecoration(space))
88-
setPadding(space)
89-
}
77+
private val keyboardView by lazy {
78+
liquidLayout.boardView
79+
}
9080

91-
override fun onCreateView(): View {
92-
return context.constraintLayout {
93-
add(
94-
keyboardView,
95-
lParams(matchParent, KeyboardSwitcher.currentKeyboard.keyboardHeight) {
96-
centerInParent()
97-
},
98-
)
81+
override fun onCreateView(): View =
82+
LiquidLayout(context, theme).apply {
83+
liquidLayout = this
84+
tabsUi.apply {
85+
setTabs(TabManager.tabTags)
86+
setOnTabClickListener { i ->
87+
select(i)
88+
}
89+
}
9990
}
100-
}
91+
92+
override fun onCreateBarView() = liquidLayout.tabsUi.root
10193

10294
override fun onAttached() {}
10395

@@ -128,6 +120,7 @@ class LiquidKeyboard(
128120

129121
fun select(i: Int): SymbolKeyboardType {
130122
val tag = TabManager.tabTags[i]
123+
liquidLayout.tabsUi.activateTab(i)
131124
symbolHistory.load()
132125
when (tag.type) {
133126
SymbolKeyboardType.CLIPBOARD,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.osfans.trime.ime.symbol
2+
3+
import android.annotation.SuppressLint
4+
import android.content.Context
5+
import androidx.constraintlayout.widget.ConstraintLayout
6+
import androidx.core.view.setPadding
7+
import com.osfans.trime.data.theme.Theme
8+
import com.osfans.trime.ime.keyboard.KeyboardSwitcher
9+
import splitties.dimensions.dp
10+
import splitties.views.dsl.constraintlayout.bottomOfParent
11+
import splitties.views.dsl.constraintlayout.centerHorizontally
12+
import splitties.views.dsl.constraintlayout.lParams
13+
import splitties.views.dsl.constraintlayout.matchConstraints
14+
import splitties.views.dsl.constraintlayout.topOfParent
15+
import splitties.views.dsl.core.add
16+
import splitties.views.dsl.recyclerview.recyclerView
17+
18+
@SuppressLint("ViewConstructor")
19+
class LiquidLayout(context: Context, theme: Theme) : ConstraintLayout(context) {
20+
val boardView =
21+
recyclerView {
22+
val space = dp(3)
23+
addItemDecoration(SpacesItemDecoration(space))
24+
setPadding(space)
25+
}
26+
27+
val tabsUi = LiquidTabsUi(context, theme)
28+
29+
init {
30+
add(
31+
boardView,
32+
lParams(matchConstraints, KeyboardSwitcher.currentKeyboard.keyboardHeight) {
33+
topOfParent()
34+
centerHorizontally()
35+
bottomOfParent()
36+
},
37+
)
38+
}
39+
}

app/src/main/java/com/osfans/trime/ime/symbol/TabTag.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.osfans.trime.ime.symbol
22

3-
import android.graphics.Rect
43
import com.osfans.trime.ime.enums.KeyCommandType
54
import com.osfans.trime.ime.enums.SymbolKeyboardType
65

app/src/main/java/com/osfans/trime/ime/window/BoardWindowManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class BoardWindowManager(
6262
val oldView = currentView!!
6363
oldWindow.onDetached()
6464
view.removeView(oldView)
65+
broadcaster.onWindowDetached(oldWindow)
6566
Timber.d("Detach $oldWindow")
6667
if (oldWindow !is ResidentWindow) {
6768
broadcaster.removeReceiver(oldWindow)
@@ -75,6 +76,7 @@ class BoardWindowManager(
7576
Timber.d("Attach $window")
7677
window.onAttached()
7778
currentWindow = window
79+
broadcaster.onWindowAttached(window)
7880
}
7981

8082
val view: FrameLayout by lazy { context.frameLayout() }

0 commit comments

Comments
 (0)