From 8fe83c89e947443c53e3b3b4b7676a9f58a880e0 Mon Sep 17 00:00:00 2001 From: WhiredPlanck Date: Fri, 29 Mar 2024 03:29:36 +0800 Subject: [PATCH] refactor: automatically switch bar view when board window attach or detach Broadcast the window attach / detach event via InputBroadcaster. --- .../java/com/osfans/trime/ime/bar/QuickBar.kt | 36 ++++++++++------ .../java/com/osfans/trime/ime/bar/TabUi.kt | 38 +++++++++++++++++ .../ime/broadcast/InputBroadcastReceiver.kt | 5 +++ .../trime/ime/broadcast/InputBroadcaster.kt | 9 ++++ .../com/osfans/trime/ime/core/InputView.kt | 5 +-- .../trime/ime/core/TrimeInputMethodService.kt | 17 -------- .../osfans/trime/ime/symbol/LiquidKeyboard.kt | 41 ++++++++----------- .../osfans/trime/ime/symbol/LiquidLayout.kt | 39 ++++++++++++++++++ .../com/osfans/trime/ime/symbol/TabTag.kt | 1 - .../trime/ime/window/BoardWindowManager.kt | 2 + .../main/res/layout/symbol_input_layout.xml | 20 --------- 11 files changed, 136 insertions(+), 77 deletions(-) create mode 100644 app/src/main/java/com/osfans/trime/ime/bar/TabUi.kt create mode 100644 app/src/main/java/com/osfans/trime/ime/symbol/LiquidLayout.kt delete mode 100644 app/src/main/res/layout/symbol_input_layout.xml diff --git a/app/src/main/java/com/osfans/trime/ime/bar/QuickBar.kt b/app/src/main/java/com/osfans/trime/ime/bar/QuickBar.kt index 809810a6ed..2f00ab76b3 100644 --- a/app/src/main/java/com/osfans/trime/ime/bar/QuickBar.kt +++ b/app/src/main/java/com/osfans/trime/ime/bar/QuickBar.kt @@ -8,14 +8,12 @@ import android.widget.ViewAnimator import com.osfans.trime.core.Rime import com.osfans.trime.core.RimeNotification.OptionNotification import com.osfans.trime.data.theme.ColorManager -import com.osfans.trime.data.theme.Theme import com.osfans.trime.databinding.CandidateBarBinding import com.osfans.trime.ime.broadcast.InputBroadcastReceiver import com.osfans.trime.ime.core.TrimeInputMethodService import com.osfans.trime.ime.dependency.InputScope import com.osfans.trime.ime.enums.SymbolKeyboardType -import com.osfans.trime.ime.symbol.LiquidTabsUi -import com.osfans.trime.ime.symbol.TabManager +import com.osfans.trime.ime.window.BoardWindow import me.tatarka.inject.annotations.Inject import splitties.views.dsl.core.add import splitties.views.dsl.core.lParams @@ -23,7 +21,7 @@ import splitties.views.dsl.core.matchParent @InputScope @Inject -class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme) : InputBroadcastReceiver { +class QuickBar(context: Context, service: TrimeInputMethodService) : InputBroadcastReceiver { val oldCandidateBar by lazy { CandidateBarBinding.inflate(LayoutInflater.from(context)).apply { with(root) { @@ -40,10 +38,8 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme) } } - val tabsUi by lazy { - LiquidTabsUi(context, theme).apply { - setTabs(TabManager.tabCandidates) - } + private val tabUi by lazy { + TabUi(context) } enum class State { @@ -51,9 +47,14 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme) Tab, } - fun switchUiByState(state: State) { - if (view.displayedChild == state.ordinal) return - view.displayedChild = state.ordinal + private fun switchUiByState(state: State) { + val index = state.ordinal + if (view.displayedChild == index) return + val new = view.getChildAt(index) + if (new != tabUi.root) { + tabUi.removeExternal() + } + view.displayedChild = index } val view by lazy { @@ -75,7 +76,7 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme) "candidate_border_round", ) add(oldCandidateBar.root, lParams(matchParent, matchParent)) - add(tabsUi.root, lParams(matchParent, matchParent)) + add(tabUi.root, lParams(matchParent, matchParent)) } } @@ -89,4 +90,15 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme) } } } + + override fun onWindowAttached(window: BoardWindow) { + if (window is BoardWindow.BarBoardWindow) { + window.onCreateBarView()?.let { tabUi.addExternal(it) } + switchUiByState(State.Tab) + } + } + + override fun onWindowDetached(window: BoardWindow) { + switchUiByState(State.Candidate) + } } diff --git a/app/src/main/java/com/osfans/trime/ime/bar/TabUi.kt b/app/src/main/java/com/osfans/trime/ime/bar/TabUi.kt new file mode 100644 index 0000000000..a178da9bf8 --- /dev/null +++ b/app/src/main/java/com/osfans/trime/ime/bar/TabUi.kt @@ -0,0 +1,38 @@ +package com.osfans.trime.ime.bar + +import android.content.Context +import android.view.View +import splitties.views.dsl.constraintlayout.centerInParent +import splitties.views.dsl.constraintlayout.constraintLayout +import splitties.views.dsl.constraintlayout.lParams +import splitties.views.dsl.core.Ui +import splitties.views.dsl.core.add +import splitties.views.dsl.core.matchParent + +class TabUi(override val ctx: Context) : Ui { + private var external: View? = null + + override val root = constraintLayout { } + + fun addExternal(view: View) { + if (external != null) { + throw IllegalStateException("TabBar external view is already present") + } + external = view + root.run { + add( + view, + lParams(matchParent, matchParent) { + centerInParent() + }, + ) + } + } + + fun removeExternal() { + external?.let { + root.removeView(it) + external = null + } + } +} diff --git a/app/src/main/java/com/osfans/trime/ime/broadcast/InputBroadcastReceiver.kt b/app/src/main/java/com/osfans/trime/ime/broadcast/InputBroadcastReceiver.kt index 8d1d7d92c9..64506182c5 100644 --- a/app/src/main/java/com/osfans/trime/ime/broadcast/InputBroadcastReceiver.kt +++ b/app/src/main/java/com/osfans/trime/ime/broadcast/InputBroadcastReceiver.kt @@ -1,7 +1,12 @@ package com.osfans.trime.ime.broadcast import com.osfans.trime.core.RimeNotification.OptionNotification +import com.osfans.trime.ime.window.BoardWindow interface InputBroadcastReceiver { fun onRimeOptionUpdated(value: OptionNotification.Value) {} + + fun onWindowAttached(window: BoardWindow) {} + + fun onWindowDetached(window: BoardWindow) {} } diff --git a/app/src/main/java/com/osfans/trime/ime/broadcast/InputBroadcaster.kt b/app/src/main/java/com/osfans/trime/ime/broadcast/InputBroadcaster.kt index e8d75c9db6..1f1dd5b044 100644 --- a/app/src/main/java/com/osfans/trime/ime/broadcast/InputBroadcaster.kt +++ b/app/src/main/java/com/osfans/trime/ime/broadcast/InputBroadcaster.kt @@ -2,6 +2,7 @@ package com.osfans.trime.ime.broadcast import com.osfans.trime.core.RimeNotification.OptionNotification import com.osfans.trime.ime.dependency.InputScope +import com.osfans.trime.ime.window.BoardWindow import me.tatarka.inject.annotations.Inject import java.util.concurrent.ConcurrentLinkedQueue @@ -29,4 +30,12 @@ class InputBroadcaster : InputBroadcastReceiver { override fun onRimeOptionUpdated(value: OptionNotification.Value) { receivers.forEach { it.onRimeOptionUpdated(value) } } + + override fun onWindowAttached(window: BoardWindow) { + receivers.forEach { it.onWindowAttached(window) } + } + + override fun onWindowDetached(window: BoardWindow) { + receivers.forEach { it.onWindowDetached(window) } + } } diff --git a/app/src/main/java/com/osfans/trime/ime/core/InputView.kt b/app/src/main/java/com/osfans/trime/ime/core/InputView.kt index 9d37ee88f1..b0dced8f15 100644 --- a/app/src/main/java/com/osfans/trime/ime/core/InputView.kt +++ b/app/src/main/java/com/osfans/trime/ime/core/InputView.kt @@ -305,10 +305,9 @@ class InputView( fun switchBoard(board: Board) { when (board) { - Board.Main -> windowManager.attachWindow(keyboardWindow) - Board.Symbol -> windowManager.attachWindow(liquidKeyboard) + Board.Main -> windowManager.attachWindow(KeyboardWindow) + Board.Symbol -> windowManager.attachWindow(LiquidKeyboard) } - quickBar.switchUiByState(QuickBar.State.entries[board.ordinal]) } private var showingDialog: Dialog? = null diff --git a/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt b/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt index 19aa1b0dde..f7afb366b1 100644 --- a/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt +++ b/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt @@ -55,7 +55,6 @@ import com.osfans.trime.data.theme.ThemeManager import com.osfans.trime.ime.broadcast.IntentReceiver import com.osfans.trime.ime.enums.FullscreenMode import com.osfans.trime.ime.enums.InlinePreeditMode -import com.osfans.trime.ime.enums.KeyCommandType import com.osfans.trime.ime.enums.Keycode import com.osfans.trime.ime.enums.SymbolKeyboardType import com.osfans.trime.ime.keyboard.Event @@ -64,7 +63,6 @@ import com.osfans.trime.ime.keyboard.InputFeedbackManager import com.osfans.trime.ime.keyboard.Key import com.osfans.trime.ime.keyboard.KeyboardSwitcher import com.osfans.trime.ime.keyboard.KeyboardView -import com.osfans.trime.ime.symbol.LiquidTabsUi import com.osfans.trime.ime.symbol.TabManager import com.osfans.trime.ime.text.Candidate import com.osfans.trime.ime.text.CompositionPopupWindow @@ -89,7 +87,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { get() = AppPrefs.defaultInstance() private var mainKeyboardView: KeyboardView? = null // 主軟鍵盤 private var mCandidate: Candidate? = null // 候選 - private var liquidTabsUi: LiquidTabsUi? = null var inputView: InputView? = null private var initializationUi: InitializationUi? = null private var eventListeners = WeakHashSet() @@ -271,7 +268,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { if (tabIndex >= 0) { inputView!!.switchBoard(InputView.Board.Symbol) symbolKeyboardType = inputView!!.liquidKeyboard.select(tabIndex) - liquidTabsUi?.activateTab(TabManager.selectedOrZero) mCompositionPopupWindow?.composition?.compositionView?.changeToLiquidKeyboardToolbar() showCompositionView(false) } else { @@ -319,17 +315,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { mainKeyboardView = inputView!!.keyboardWindow.oldMainInputView.mainKeyboardView // 初始化候选栏 mCandidate = inputView!!.quickBar.oldCandidateBar.candidates - liquidTabsUi = - inputView!!.quickBar.tabsUi.apply { - setOnTabClickListener { - val tag = TabManager.tabTags[it] - if (tag.type == SymbolKeyboardType.NO_KEY && tag.command == KeyCommandType.EXIT) { - selectLiquidKeyboard(-1) - } else { - selectLiquidKeyboard(it) - } - } - } mCompositionPopupWindow = CompositionPopupWindow(this, ThemeManager.activeTheme).apply { @@ -1134,8 +1119,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { } else { mCandidate!!.setText(0) } - // 刷新候选词后,如果候选词超出屏幕宽度,滚动候选栏 -// mTabRoot?.move(mCandidate!!.highlightLeft, mCandidate!!.highlightRight) } mainKeyboardView?.invalidateComposingKeys() if (!onEvaluateInputViewShown()) setCandidatesViewShown(textInputManager!!.isComposable) // 實體鍵盤打字時顯示候選欄 diff --git a/app/src/main/java/com/osfans/trime/ime/symbol/LiquidKeyboard.kt b/app/src/main/java/com/osfans/trime/ime/symbol/LiquidKeyboard.kt index 5cf3b0e3cc..a0cebdda71 100644 --- a/app/src/main/java/com/osfans/trime/ime/symbol/LiquidKeyboard.kt +++ b/app/src/main/java/com/osfans/trime/ime/symbol/LiquidKeyboard.kt @@ -2,7 +2,6 @@ package com.osfans.trime.ime.symbol import android.content.Context import android.view.View -import androidx.core.view.setPadding import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.StaggeredGridLayoutManager @@ -21,19 +20,12 @@ import com.osfans.trime.ime.core.TrimeInputMethodService import com.osfans.trime.ime.dependency.InputScope import com.osfans.trime.ime.enums.KeyCommandType import com.osfans.trime.ime.enums.SymbolKeyboardType -import com.osfans.trime.ime.keyboard.KeyboardSwitcher import com.osfans.trime.ime.text.TextInputManager import com.osfans.trime.ime.window.BoardWindow import com.osfans.trime.ime.window.ResidentWindow import kotlinx.coroutines.launch import me.tatarka.inject.annotations.Inject import splitties.dimensions.dp -import splitties.views.dsl.constraintlayout.centerInParent -import splitties.views.dsl.constraintlayout.constraintLayout -import splitties.views.dsl.constraintlayout.lParams -import splitties.views.dsl.core.add -import splitties.views.dsl.core.matchParent -import splitties.views.dsl.recyclerview.recyclerView import timber.log.Timber @InputScope @@ -42,7 +34,8 @@ class LiquidKeyboard( private val context: Context, private val service: TrimeInputMethodService, private val theme: Theme, -) : BoardWindow.NoBarBoardWindow(), ResidentWindow, ClipboardHelper.OnClipboardUpdateListener { +) : BoardWindow.BarBoardWindow(), ResidentWindow, ClipboardHelper.OnClipboardUpdateListener { + private lateinit var liquidLayout: LiquidLayout private val symbolHistory = SymbolHistory(180) private var adapterType: AdapterType = AdapterType.INIT private val simpleAdapter by lazy { @@ -81,23 +74,22 @@ class LiquidKeyboard( override val key: ResidentWindow.Key get() = LiquidKeyboard - private val keyboardView = - context.recyclerView { - val space = dp(3) - addItemDecoration(SpacesItemDecoration(space)) - setPadding(space) - } + private val keyboardView by lazy { + liquidLayout.boardView + } - override fun onCreateView(): View { - return context.constraintLayout { - add( - keyboardView, - lParams(matchParent, KeyboardSwitcher.currentKeyboard.keyboardHeight) { - centerInParent() - }, - ) + override fun onCreateView(): View = + LiquidLayout(context, theme).apply { + liquidLayout = this + tabsUi.apply { + setTabs(TabManager.tabTags) + setOnTabClickListener { i -> + select(i) + } + } } - } + + override fun onCreateBarView() = liquidLayout.tabsUi.root override fun onAttached() {} @@ -128,6 +120,7 @@ class LiquidKeyboard( fun select(i: Int): SymbolKeyboardType { val tag = TabManager.tabTags[i] + liquidLayout.tabsUi.activateTab(i) symbolHistory.load() when (tag.type) { SymbolKeyboardType.CLIPBOARD, diff --git a/app/src/main/java/com/osfans/trime/ime/symbol/LiquidLayout.kt b/app/src/main/java/com/osfans/trime/ime/symbol/LiquidLayout.kt new file mode 100644 index 0000000000..0712d74370 --- /dev/null +++ b/app/src/main/java/com/osfans/trime/ime/symbol/LiquidLayout.kt @@ -0,0 +1,39 @@ +package com.osfans.trime.ime.symbol + +import android.annotation.SuppressLint +import android.content.Context +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.setPadding +import com.osfans.trime.data.theme.Theme +import com.osfans.trime.ime.keyboard.KeyboardSwitcher +import splitties.dimensions.dp +import splitties.views.dsl.constraintlayout.bottomOfParent +import splitties.views.dsl.constraintlayout.centerHorizontally +import splitties.views.dsl.constraintlayout.lParams +import splitties.views.dsl.constraintlayout.matchConstraints +import splitties.views.dsl.constraintlayout.topOfParent +import splitties.views.dsl.core.add +import splitties.views.dsl.recyclerview.recyclerView + +@SuppressLint("ViewConstructor") +class LiquidLayout(context: Context, theme: Theme) : ConstraintLayout(context) { + val boardView = + recyclerView { + val space = dp(3) + addItemDecoration(SpacesItemDecoration(space)) + setPadding(space) + } + + val tabsUi = LiquidTabsUi(context, theme) + + init { + add( + boardView, + lParams(matchConstraints, KeyboardSwitcher.currentKeyboard.keyboardHeight) { + topOfParent() + centerHorizontally() + bottomOfParent() + }, + ) + } +} diff --git a/app/src/main/java/com/osfans/trime/ime/symbol/TabTag.kt b/app/src/main/java/com/osfans/trime/ime/symbol/TabTag.kt index e53bde2209..eea3262ed6 100644 --- a/app/src/main/java/com/osfans/trime/ime/symbol/TabTag.kt +++ b/app/src/main/java/com/osfans/trime/ime/symbol/TabTag.kt @@ -1,6 +1,5 @@ package com.osfans.trime.ime.symbol -import android.graphics.Rect import com.osfans.trime.ime.enums.KeyCommandType import com.osfans.trime.ime.enums.SymbolKeyboardType diff --git a/app/src/main/java/com/osfans/trime/ime/window/BoardWindowManager.kt b/app/src/main/java/com/osfans/trime/ime/window/BoardWindowManager.kt index 302ff54367..7e096f13af 100644 --- a/app/src/main/java/com/osfans/trime/ime/window/BoardWindowManager.kt +++ b/app/src/main/java/com/osfans/trime/ime/window/BoardWindowManager.kt @@ -62,6 +62,7 @@ class BoardWindowManager( val oldView = currentView!! oldWindow.onDetached() view.removeView(oldView) + broadcaster.onWindowDetached(oldWindow) Timber.d("Detach $oldWindow") if (oldWindow !is ResidentWindow) { broadcaster.removeReceiver(oldWindow) @@ -75,6 +76,7 @@ class BoardWindowManager( Timber.d("Attach $window") window.onAttached() currentWindow = window + broadcaster.onWindowAttached(window) } val view: FrameLayout by lazy { context.frameLayout() } diff --git a/app/src/main/res/layout/symbol_input_layout.xml b/app/src/main/res/layout/symbol_input_layout.xml deleted file mode 100644 index 96672164b4..0000000000 --- a/app/src/main/res/layout/symbol_input_layout.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - -