@@ -21,7 +21,6 @@ import android.content.Context
2121import android.graphics.Canvas
2222import android.graphics.Color
2323import android.graphics.Paint
24- import android.graphics.Typeface
2524import android.graphics.drawable.PaintDrawable
2625import android.util.AttributeSet
2726import android.view.MotionEvent
@@ -35,48 +34,43 @@ import com.osfans.trime.ime.enums.KeyCommandType
3534import com.osfans.trime.ime.enums.SymbolKeyboardType
3635import com.osfans.trime.util.GraphicUtils.drawText
3736import com.osfans.trime.util.GraphicUtils.measureText
38- import com.osfans.trime.util.dp2px
3937import com.osfans.trime.util.sp
38+ import splitties.dimensions.dp
4039import timber.log.Timber
4140import kotlin.math.abs
4241
4342// 这是滑动键盘顶部的view,展示了键盘布局的多个标签。
4443// 为了公用候选栏的皮肤参数以及外观,大部分代码从Candidate.java复制而来。
4544class TabView (context : Context ? , attrs : AttributeSet ? ) : View(context, attrs) {
45+ private val theme = ThemeManager .activeTheme
4646 private var highlightIndex = 0
47- private var tabTags: ArrayList <TabTag >? = null
48- private var candidateHighlight: PaintDrawable ? = null
49- private val separatorPaint: Paint
50- private val candidatePaint: Paint
51- private var candidateFont: Typeface ? = null
52- private var candidateTextColor = 0
53- private var hilitedCandidateTextColor = 0
54- private var candidateViewHeight = 0
55- private var commentHeight = 0
56- private var candidateSpacing = 0
57- private var candidatePadding = 0
58- private var isCommentOnTop = false
59- private var shouldCandidateUseCursor = false
47+ private val tabTags = mutableListOf<TabTag >()
48+ private val candidateHighlight =
49+ PaintDrawable (ColorManager .getColor(" hilited_candidate_back_color" )!! ).apply {
50+ setCornerRadius(theme.style.getFloat(" layout/round_corner" ))
51+ }
52+ private val separatorPaint =
53+ Paint ().apply {
54+ color = ColorManager .getColor(" candidate_separator_color" ) ? : Color .BLACK
55+ }
56+ private val candidatePaint =
57+ Paint ().apply {
58+ isAntiAlias = true
59+ strokeWidth = 0f
60+ textSize = sp(theme.style.getFloat(" candidate_text_size" ))
61+ typeface = candidateFont
62+ }
63+ private val candidateFont = FontManager .getTypeface(" candidate_font" )
64+ private val candidateTextColor = ColorManager .getColor(" candidate_text_color" )!!
65+ private val hilitedCandidateTextColor = ColorManager .getColor(" hilited_candidate_text_color" )!!
66+ private val candidateViewHeight = theme.style.getInt(" candidate_view_height" )
67+ private val commentHeight = theme.style.getInt(" comment_height" )
68+ private val candidateSpacing = theme.style.getFloat(" candidate_spacing" )
69+ private val candidatePadding = theme.style.getFloat(" candidate_padding" )
70+ private val isCommentOnTop = theme.style.getBoolean(" comment_on_top" )
71+ private val shouldCandidateUseCursor = theme.style.getBoolean(" comment_on_top" )
6072
6173 // private final Rect[] tabGeometries = new Rect[MAX_CANDIDATE_COUNT + 2];
62- fun reset () {
63- val theme = ThemeManager .activeTheme
64- candidateHighlight = PaintDrawable (ColorManager .getColor(" hilited_candidate_back_color" )!! )
65- candidateHighlight!! .setCornerRadius(theme.style.getFloat(" layout/round_corner" ))
66- separatorPaint.color = ColorManager .getColor(" candidate_separator_color" )!!
67- candidateSpacing = dp2px(theme.style.getFloat(" candidate_spacing" )).toInt()
68- candidatePadding = dp2px(theme.style.getFloat(" candidate_padding" )).toInt()
69- candidateTextColor = ColorManager .getColor(" candidate_text_color" )!!
70- hilitedCandidateTextColor = ColorManager .getColor(" hilited_candidate_text_color" )!!
71- commentHeight = dp2px(theme.style.getFloat(" comment_height" )).toInt()
72- candidateViewHeight = dp2px(theme.style.getFloat(" candidate_view_height" )).toInt()
73- candidateFont = FontManager .getTypeface(" candidate_font" )
74- candidatePaint.textSize = sp(theme.style.getFloat(" candidate_text_size" ))
75- candidatePaint.setTypeface(candidateFont)
76- isCommentOnTop = theme.style.getBoolean(" comment_on_top" )
77- shouldCandidateUseCursor = theme.style.getBoolean(" candidate_use_cursor" )
78- invalidate()
79- }
8074
8175 override fun onMeasure (
8276 widthMeasureSpec : Int ,
@@ -85,7 +79,7 @@ class TabView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
8579 val h = if (isCommentOnTop) candidateViewHeight + commentHeight else candidateViewHeight
8680 setMeasuredDimension(
8781 MeasureSpec .makeMeasureSpec(widthMeasureSpec, MeasureSpec .UNSPECIFIED ),
88- MeasureSpec .makeMeasureSpec(h , MeasureSpec .AT_MOST ),
82+ MeasureSpec .makeMeasureSpec(dp(h) , MeasureSpec .AT_MOST ),
8983 )
9084 }
9185
@@ -94,62 +88,51 @@ class TabView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
9488 }
9589
9690 val highlightLeft: Int
97- get() = tabTags!! [highlightIndex].geometry.left
91+ get() = tabTags[highlightIndex].geometry.left
9892 val highlightRight: Int
99- get() = tabTags!! [highlightIndex].geometry.right
93+ get() = tabTags[highlightIndex].geometry.right
10094
10195 override fun onDraw (canvas : Canvas ) {
102- if (tabTags == null ) return
96+ if (tabTags.isEmpty() ) return
10397 super .onDraw(canvas)
10498
10599 // Draw highlight background
106100 if (isHighlighted(highlightIndex)) {
107- candidateHighlight!! .bounds = tabTags!! [highlightIndex].geometry
108- candidateHighlight!! .draw(canvas)
101+ candidateHighlight.bounds = tabTags[highlightIndex].geometry
102+ candidateHighlight.draw(canvas)
109103 }
110104 // Draw tab text
111- val tabY = (
112- /* (shouldShowComment && isCommentOnTop)
113- ? tabTags.get(0).geometry.centerY()
114- - (candidatePaint.ascent() + candidatePaint.descent()) / 2.0f
115- + commentHeight / 2.0f
116- : */
117- tabTags!! [0 ].geometry.centerY() -
105+ val tabY =
106+ tabTags[0 ].geometry.centerY() -
118107 (candidatePaint.ascent() + candidatePaint.descent()) / 2.0f
119- )
120- for ((i, computedTab) in tabTags!! .withIndex()) {
108+ for ((i, computedTab) in tabTags.withIndex()) {
121109 // Calculate a position where the text could be centered in the rectangle.
122110 val tabX = computedTab.geometry.centerX().toFloat()
123111 candidatePaint.color = if (isHighlighted(i)) hilitedCandidateTextColor else candidateTextColor
124- canvas.drawText(computedTab.text, tabX, tabY, candidatePaint, candidateFont!! )
112+ canvas.drawText(computedTab.text, tabX, tabY, candidatePaint, candidateFont)
125113 // Draw the separator at the right edge of each candidate.
126114 canvas.drawRect(
127- (
128- computedTab.geometry.right - candidateSpacing
129- ).toFloat(),
115+ computedTab.geometry.right - dp(candidateSpacing),
130116 computedTab.geometry.top.toFloat(),
131- (
132- computedTab.geometry.right + candidateSpacing
133- ).toFloat(),
117+ computedTab.geometry.right + dp(candidateSpacing),
134118 computedTab.geometry.bottom.toFloat(),
135119 separatorPaint,
136120 )
137121 }
138122 }
139123
140124 fun updateTabWidth () {
141- tabTags = TabManager .tabCandidates
125+ tabTags.clear()
126+ tabTags.addAll(TabManager .tabCandidates)
142127 highlightIndex = TabManager .selectedOrZero
143128 var x = 0
144- for ((i, computedTab) in tabTags!! .withIndex()) {
129+ for ((i, computedTab) in tabTags.withIndex()) {
145130 computedTab.geometry.set(x, 0 , (x + getTabWidth(i)).toInt(), height)
146131 x = (x + (getTabWidth(i) + candidateSpacing)).toInt()
147132 }
148133 updateLayoutParams {
149- Timber .d(" updateTabWidth: layoutPrams from: height=$height , width=$width " )
150134 width = x
151- height = if (isCommentOnTop) candidateViewHeight + commentHeight else candidateViewHeight
152- Timber .d(" updateTabWidth: layoutPrams to: height=$height , width=$width " )
135+ height = dp(if (isCommentOnTop) candidateViewHeight + commentHeight else candidateViewHeight)
153136 }
154137 invalidate()
155138 }
@@ -162,24 +145,17 @@ class TabView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
162145 ) {
163146 super .onSizeChanged(w, h, oldw, oldh)
164147 updateTabWidth()
165- Timber .d(" onSizeChanged() w=$w , Height=$oldh =>$h " )
166148 }
167149
168150 override fun performClick (): Boolean {
169151 return super .performClick()
170152 }
171153
172- var x0 = 0
173- var y0 = 0
154+ private var x0 = 0
155+ private var y0 = 0
174156 private var time0: Long = 0
175157
176158 init {
177- candidatePaint = Paint ()
178- candidatePaint.isAntiAlias = true
179- candidatePaint.strokeWidth = 0f
180- separatorPaint = Paint ()
181- separatorPaint.color = Color .BLACK
182- reset()
183159 setWillNotDraw(false )
184160 }
185161
@@ -195,58 +171,32 @@ class TabView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
195171
196172 MotionEvent .ACTION_MOVE -> if (abs(x - x0) > 100 ) time0 = 0
197173 MotionEvent .ACTION_UP -> {
198- val i = getTabIndex (x, y)
174+ val i = tabTags.indexOfFirst { it.geometry.contains (x, y) }
199175 if (i > - 1 ) {
200176 performClick()
201177 val tag = TabManager .tabTags[i]
202178 if (tag.type == SymbolKeyboardType .NO_KEY ) {
203- when (tag.command) {
204- KeyCommandType .EXIT -> TrimeInputMethodService .getService().selectLiquidKeyboard(- 1 )
205- KeyCommandType .DEL_LEFT , KeyCommandType .DEL_RIGHT , KeyCommandType .REDO , KeyCommandType .UNDO -> {}
206- else -> {}
179+ if (tag.command == KeyCommandType .EXIT ) {
180+ TrimeInputMethodService .getService().selectLiquidKeyboard(- 1 )
207181 }
208182 } else if (System .currentTimeMillis() - time0 < 500 ) {
209183 highlightIndex = i
210184 invalidate()
211185 TrimeInputMethodService .getService().selectLiquidKeyboard(i)
212186 }
213- Timber .d(" index=" + i + " length=" + tabTags!! .size)
187+ Timber .d(" index=" + i + " length=" + tabTags.size)
214188 }
215189 }
216190 }
217191 return true
218192 }
219193
220- /* *
221- * 獲得觸摸處候選項序號
222- *
223- * @param x 觸摸點橫座標
224- * @param y 觸摸點縱座標
225- * @return `>=0`: 觸摸點 (x, y) 處候選項序號,從0開始編號; `-1`: 觸摸點 (x, y) 處無候選項;
226- */
227- private fun getTabIndex (
228- x : Int ,
229- y : Int ,
230- ): Int {
231- // Rect r = new Rect();
232- var retIndex = - 1 // Returns -1 if there is no tab in the hitting rectangle.
233- for (computedTab in tabTags!! ) {
234- /* Enlarge the rectangle to be more responsive to user clicks.
235- // r.set(tabGeometries[j++]);
236- //r.inset(0, CANDIDATE_TOUCH_OFFSET); */
237- if (computedTab.geometry.contains(x, y)) {
238- retIndex = tabTags!! .indexOf(computedTab)
239- }
240- }
241- return retIndex
242- }
243-
244194 private fun getTabWidth (i : Int ): Float {
245- val s = tabTags!! [i].text
195+ val s = tabTags[i].text
246196 return if (s.isNotEmpty()) {
247- 2 * candidatePadding + candidatePaint.measureText(s, candidateFont!! )
197+ 2 * dp( candidatePadding) + candidatePaint.measureText(s, candidateFont)
248198 } else {
249- ( 2 * candidatePadding).toFloat( )
199+ 2 * dp(candidatePadding )
250200 }
251201 }
252202}
0 commit comments