@@ -21,7 +21,6 @@ import android.content.Context
21
21
import android.graphics.Canvas
22
22
import android.graphics.Color
23
23
import android.graphics.Paint
24
- import android.graphics.Typeface
25
24
import android.graphics.drawable.PaintDrawable
26
25
import android.util.AttributeSet
27
26
import android.view.MotionEvent
@@ -35,48 +34,43 @@ import com.osfans.trime.ime.enums.KeyCommandType
35
34
import com.osfans.trime.ime.enums.SymbolKeyboardType
36
35
import com.osfans.trime.util.GraphicUtils.drawText
37
36
import com.osfans.trime.util.GraphicUtils.measureText
38
- import com.osfans.trime.util.dp2px
39
37
import com.osfans.trime.util.sp
38
+ import splitties.dimensions.dp
40
39
import timber.log.Timber
41
40
import kotlin.math.abs
42
41
43
42
// 这是滑动键盘顶部的view,展示了键盘布局的多个标签。
44
43
// 为了公用候选栏的皮肤参数以及外观,大部分代码从Candidate.java复制而来。
45
44
class TabView (context : Context ? , attrs : AttributeSet ? ) : View(context, attrs) {
45
+ private val theme = ThemeManager .activeTheme
46
46
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" )
60
72
61
73
// 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
- }
80
74
81
75
override fun onMeasure (
82
76
widthMeasureSpec : Int ,
@@ -85,7 +79,7 @@ class TabView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
85
79
val h = if (isCommentOnTop) candidateViewHeight + commentHeight else candidateViewHeight
86
80
setMeasuredDimension(
87
81
MeasureSpec .makeMeasureSpec(widthMeasureSpec, MeasureSpec .UNSPECIFIED ),
88
- MeasureSpec .makeMeasureSpec(h , MeasureSpec .AT_MOST ),
82
+ MeasureSpec .makeMeasureSpec(dp(h) , MeasureSpec .AT_MOST ),
89
83
)
90
84
}
91
85
@@ -94,62 +88,51 @@ class TabView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
94
88
}
95
89
96
90
val highlightLeft: Int
97
- get() = tabTags!! [highlightIndex].geometry.left
91
+ get() = tabTags[highlightIndex].geometry.left
98
92
val highlightRight: Int
99
- get() = tabTags!! [highlightIndex].geometry.right
93
+ get() = tabTags[highlightIndex].geometry.right
100
94
101
95
override fun onDraw (canvas : Canvas ) {
102
- if (tabTags == null ) return
96
+ if (tabTags.isEmpty() ) return
103
97
super .onDraw(canvas)
104
98
105
99
// Draw highlight background
106
100
if (isHighlighted(highlightIndex)) {
107
- candidateHighlight!! .bounds = tabTags!! [highlightIndex].geometry
108
- candidateHighlight!! .draw(canvas)
101
+ candidateHighlight.bounds = tabTags[highlightIndex].geometry
102
+ candidateHighlight.draw(canvas)
109
103
}
110
104
// 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() -
118
107
(candidatePaint.ascent() + candidatePaint.descent()) / 2.0f
119
- )
120
- for ((i, computedTab) in tabTags!! .withIndex()) {
108
+ for ((i, computedTab) in tabTags.withIndex()) {
121
109
// Calculate a position where the text could be centered in the rectangle.
122
110
val tabX = computedTab.geometry.centerX().toFloat()
123
111
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)
125
113
// Draw the separator at the right edge of each candidate.
126
114
canvas.drawRect(
127
- (
128
- computedTab.geometry.right - candidateSpacing
129
- ).toFloat(),
115
+ computedTab.geometry.right - dp(candidateSpacing),
130
116
computedTab.geometry.top.toFloat(),
131
- (
132
- computedTab.geometry.right + candidateSpacing
133
- ).toFloat(),
117
+ computedTab.geometry.right + dp(candidateSpacing),
134
118
computedTab.geometry.bottom.toFloat(),
135
119
separatorPaint,
136
120
)
137
121
}
138
122
}
139
123
140
124
fun updateTabWidth () {
141
- tabTags = TabManager .tabCandidates
125
+ tabTags.clear()
126
+ tabTags.addAll(TabManager .tabCandidates)
142
127
highlightIndex = TabManager .selectedOrZero
143
128
var x = 0
144
- for ((i, computedTab) in tabTags!! .withIndex()) {
129
+ for ((i, computedTab) in tabTags.withIndex()) {
145
130
computedTab.geometry.set(x, 0 , (x + getTabWidth(i)).toInt(), height)
146
131
x = (x + (getTabWidth(i) + candidateSpacing)).toInt()
147
132
}
148
133
updateLayoutParams {
149
- Timber .d(" updateTabWidth: layoutPrams from: height=$height , width=$width " )
150
134
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)
153
136
}
154
137
invalidate()
155
138
}
@@ -162,24 +145,17 @@ class TabView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
162
145
) {
163
146
super .onSizeChanged(w, h, oldw, oldh)
164
147
updateTabWidth()
165
- Timber .d(" onSizeChanged() w=$w , Height=$oldh =>$h " )
166
148
}
167
149
168
150
override fun performClick (): Boolean {
169
151
return super .performClick()
170
152
}
171
153
172
- var x0 = 0
173
- var y0 = 0
154
+ private var x0 = 0
155
+ private var y0 = 0
174
156
private var time0: Long = 0
175
157
176
158
init {
177
- candidatePaint = Paint ()
178
- candidatePaint.isAntiAlias = true
179
- candidatePaint.strokeWidth = 0f
180
- separatorPaint = Paint ()
181
- separatorPaint.color = Color .BLACK
182
- reset()
183
159
setWillNotDraw(false )
184
160
}
185
161
@@ -195,58 +171,32 @@ class TabView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
195
171
196
172
MotionEvent .ACTION_MOVE -> if (abs(x - x0) > 100 ) time0 = 0
197
173
MotionEvent .ACTION_UP -> {
198
- val i = getTabIndex (x, y)
174
+ val i = tabTags.indexOfFirst { it.geometry.contains (x, y) }
199
175
if (i > - 1 ) {
200
176
performClick()
201
177
val tag = TabManager .tabTags[i]
202
178
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 )
207
181
}
208
182
} else if (System .currentTimeMillis() - time0 < 500 ) {
209
183
highlightIndex = i
210
184
invalidate()
211
185
TrimeInputMethodService .getService().selectLiquidKeyboard(i)
212
186
}
213
- Timber .d(" index=" + i + " length=" + tabTags!! .size)
187
+ Timber .d(" index=" + i + " length=" + tabTags.size)
214
188
}
215
189
}
216
190
}
217
191
return true
218
192
}
219
193
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
-
244
194
private fun getTabWidth (i : Int ): Float {
245
- val s = tabTags!! [i].text
195
+ val s = tabTags[i].text
246
196
return if (s.isNotEmpty()) {
247
- 2 * candidatePadding + candidatePaint.measureText(s, candidateFont!! )
197
+ 2 * dp( candidatePadding) + candidatePaint.measureText(s, candidateFont)
248
198
} else {
249
- ( 2 * candidatePadding).toFloat( )
199
+ 2 * dp(candidatePadding )
250
200
}
251
201
}
252
202
}
0 commit comments