20
20
21
21
import android .content .Context ;
22
22
import android .graphics .Canvas ;
23
+ import android .graphics .Color ;
23
24
import android .graphics .Paint ;
24
25
import android .graphics .Rect ;
25
26
import android .graphics .Typeface ;
26
- import android .graphics .drawable .Drawable ;
27
27
import android .graphics .drawable .PaintDrawable ;
28
+ import android .text .TextUtils ;
28
29
import android .util .AttributeSet ;
29
30
import android .view .MotionEvent ;
30
31
import android .view .View ;
31
32
import android .view .ViewGroup .LayoutParams ;
33
+
34
+ import androidx .annotation .NonNull ;
35
+
32
36
import com .osfans .trime .ime .core .Trime ;
33
37
import com .osfans .trime .ime .enums .SymbolKeyboardType ;
34
38
import com .osfans .trime .setup .Config ;
@@ -42,115 +46,103 @@ public class TabView extends View {
42
46
private static final int CANDIDATE_TOUCH_OFFSET = -12 ;
43
47
44
48
private int highlightIndex ;
45
- private TabTag [] candidates ;
46
- private int num_candidates ;
47
-
48
- private Drawable candidateHighlight , candidateSeparator ;
49
- private final Paint paintCandidate ;
50
- private final Paint paintSymbol ;
51
- private final Paint paintComment ;
52
- private Typeface tfCandidate ;
53
- private Typeface tfHanB ;
54
- private Typeface tfLatin ;
55
- private int candidate_text_color , hilited_candidate_text_color ;
56
- private int candidate_view_height , comment_height , candidate_spacing , candidate_padding ;
57
- private final boolean show_comment = true ;
58
- private boolean comment_on_top ;
59
- private boolean candidate_use_cursor ;
60
-
61
- private final Rect [] candidateRect = new Rect [MAX_CANDIDATE_COUNT + 2 ];
49
+ private TabTag [] tabTags ;
50
+
51
+ private PaintDrawable candidateHighlight ;
52
+ private final Paint separatorPaint ;
53
+ private final Paint candidatePaint ;
54
+ private Typeface candidateFont ;
55
+ private Typeface hanBFont ;
56
+ private Typeface latinFont ;
57
+ private int candidateTextColor , hilitedCandidateTextColor ;
58
+ private int candidateViewHeight , commentHeight , candidateSpacing , candidatePadding ;
59
+ private final boolean shouldShowComment = true ;
60
+ private boolean isCommentOnTop ;
61
+ private boolean shouldCandidateUseCursor ;
62
+
63
+ private final Rect [] tabGeometries = new Rect [MAX_CANDIDATE_COUNT + 2 ];
62
64
63
65
public void reset (Context context ) {
64
66
Config config = Config .get (context );
65
67
candidateHighlight = new PaintDrawable (config .getColor ("hilited_candidate_back_color" ));
66
- ((PaintDrawable ) candidateHighlight ).setCornerRadius (config .getFloat ("layout/round_corner" ));
67
- candidateSeparator = new PaintDrawable (config .getColor ("candidate_separator_color" ));
68
- candidate_spacing = config .getPixel ("candidate_spacing" );
69
- candidate_padding = config .getPixel ("candidate_padding" );
70
-
71
- candidate_text_color = config .getColor ("candidate_text_color" );
72
- hilited_candidate_text_color = config .getColor ("hilited_candidate_text_color" );
73
-
74
- comment_height = config .getPixel ("comment_height" );
75
-
76
- int candidate_text_size = config .getPixel ("candidate_text_size" );
77
- int comment_text_size = config .getPixel ("comment_text_size" );
78
- candidate_view_height = config .getPixel ("candidate_view_height" );
79
-
80
- tfCandidate = config .getFont ("candidate_font" );
81
- tfLatin = config .getFont ("latin_font" );
82
- tfHanB = config .getFont ("hanb_font" );
83
- Typeface tfComment = config .getFont ("comment_font" );
84
- Typeface tfSymbol = config .getFont ("symbol_font" );
85
-
86
- paintCandidate .setTextSize (candidate_text_size );
87
- paintCandidate .setTypeface (tfCandidate );
88
- paintSymbol .setTextSize (candidate_text_size );
89
- paintSymbol .setTypeface (tfSymbol );
90
- paintComment .setTextSize (comment_text_size );
91
- paintComment .setTypeface (tfComment );
92
-
93
- comment_on_top = config .getBoolean ("comment_on_top" );
94
- candidate_use_cursor = config .getBoolean ("candidate_use_cursor" );
68
+ candidateHighlight .setCornerRadius (config .getFloat ("layout/round_corner" ));
69
+
70
+ separatorPaint .setColor (config .getColor ("candidate_separator_color" ));
71
+
72
+ candidateSpacing = config .getPixel ("candidate_spacing" );
73
+ candidatePadding = config .getPixel ("candidate_padding" );
74
+
75
+ candidateTextColor = config .getColor ("candidate_text_color" );
76
+ hilitedCandidateTextColor = config .getColor ("hilited_candidate_text_color" );
77
+
78
+ commentHeight = config .getPixel ("comment_height" );
79
+
80
+ int candidateTextSize = config .getPixel ("candidate_text_size" );
81
+ candidateViewHeight = config .getPixel ("candidate_view_height" );
82
+
83
+ candidateFont = config .getFont ("candidate_font" );
84
+ latinFont = config .getFont ("latin_font" );
85
+ hanBFont = config .getFont ("hanb_font" );
86
+
87
+ candidatePaint .setTextSize (candidateTextSize );
88
+ candidatePaint .setTypeface (candidateFont );
89
+
90
+ isCommentOnTop = config .getBoolean ("comment_on_top" );
91
+ shouldCandidateUseCursor = config .getBoolean ("candidate_use_cursor" );
95
92
invalidate ();
96
93
}
97
94
98
95
public TabView (Context context , AttributeSet attrs ) {
99
96
super (context , attrs );
100
- paintCandidate = new Paint ();
101
- paintCandidate .setAntiAlias (true );
102
- paintCandidate .setStrokeWidth (0 );
103
- paintSymbol = new Paint ();
104
- paintSymbol .setAntiAlias (true );
105
- paintSymbol .setStrokeWidth (0 );
106
- paintComment = new Paint ();
107
- paintComment .setAntiAlias (true );
108
- paintComment .setStrokeWidth (0 );
97
+ candidatePaint = new Paint ();
98
+ candidatePaint .setAntiAlias (true );
99
+ candidatePaint .setStrokeWidth (0 );
100
+
101
+ separatorPaint = new Paint ();
102
+ separatorPaint .setColor (Color .BLACK );
109
103
110
104
reset (context );
111
105
112
106
setWillNotDraw (false );
113
107
}
114
108
115
109
private boolean isHighlighted (int i ) {
116
- return candidate_use_cursor && i >= 0 && i == highlightIndex ;
110
+ return shouldCandidateUseCursor && i >= 0 && i == highlightIndex ;
117
111
}
118
112
119
113
private void drawHighlight (Canvas canvas ) {
120
114
if (isHighlighted (highlightIndex )) {
121
- candidateHighlight .setBounds (candidateRect [highlightIndex ]);
115
+ candidateHighlight .setBounds (tabGeometries [highlightIndex ]);
122
116
candidateHighlight .draw (canvas );
123
117
}
124
118
}
125
119
126
120
public int getHightlightLeft () {
127
- return candidateRect [highlightIndex ].left ;
121
+ return tabGeometries [highlightIndex ].left ;
128
122
}
129
123
130
124
public int getHightlightRight () {
131
- return candidateRect [highlightIndex ].right ;
125
+ return tabGeometries [highlightIndex ].right ;
132
126
}
133
127
134
128
private Typeface getFont (int codepoint , Typeface font ) {
135
- if (tfHanB != Typeface .DEFAULT && Character .isSupplementaryCodePoint (codepoint )) return tfHanB ;
136
- if (tfLatin != Typeface .DEFAULT && codepoint < 0x2e80 ) return tfLatin ;
129
+ if (hanBFont != Typeface .DEFAULT && Character .isSupplementaryCodePoint (codepoint )) return hanBFont ;
130
+ if (latinFont != Typeface .DEFAULT && codepoint < 0x2e80 ) return latinFont ;
137
131
return font ;
138
132
}
139
133
140
134
private void drawText (
141
135
String s , Canvas canvas , Paint paint , Typeface font , float center , float y ) {
142
- if (s == null ) return ;
143
- int length = s .length ();
144
- if (length == 0 ) return ;
145
- int points = s .codePointCount (0 , length );
136
+ if (TextUtils .isEmpty (s )) return ;
137
+ int codePoints = s .codePointCount (0 , s .length ());
146
138
float x = center - measureText (s , paint , font ) / 2 ;
147
- if (tfLatin != Typeface .DEFAULT || (tfHanB != Typeface .DEFAULT && length > points )) {
139
+ if (latinFont != Typeface .DEFAULT || (hanBFont != Typeface .DEFAULT && s . length () > codePoints )) {
148
140
int offset = 0 ;
149
- while (offset < length ) {
150
- int codepoint = s .codePointAt (offset );
151
- int charCount = Character .charCount (codepoint );
141
+ while (offset < s . length () ) {
142
+ int codePoint = s .codePointAt (offset );
143
+ int charCount = Character .charCount (codePoint );
152
144
int end = offset + charCount ;
153
- paint .setTypeface (getFont (codepoint , font ));
145
+ paint .setTypeface (getFont (codePoint , font ));
154
146
canvas .drawText (s , offset , end , x , y , paint );
155
147
x += paint .measureText (s , offset , end );
156
148
offset = end ;
@@ -162,28 +154,27 @@ private void drawText(
162
154
}
163
155
164
156
private void drawCandidates (Canvas canvas ) {
165
- if (candidates == null ) return ;
166
-
167
- float x , y ;
168
- int i = 0 ;
157
+ if (tabTags == null ) return ;
169
158
170
- y = candidateRect [0 ].centerY () - (paintCandidate .ascent () + paintCandidate .descent ()) / 2 ;
171
- if (show_comment && comment_on_top ) y += (float ) comment_height / 2 ;
159
+ float y = tabGeometries [0 ].centerY () - (candidatePaint .ascent () + candidatePaint .descent ()) / 2 ;
160
+ if (shouldShowComment && isCommentOnTop ) y += (float ) commentHeight / 2 ;
172
161
173
- while (i < num_candidates ) {
162
+ int i = 0 ;
163
+ while (i < tabTags .length ) {
174
164
// Calculate a position where the text could be centered in the rectangle.
175
- x = candidateRect [i ].centerX ();
165
+ float x = tabGeometries [i ].centerX ();
176
166
177
- paintCandidate .setColor (
178
- isHighlighted (i ) ? hilited_candidate_text_color : candidate_text_color );
179
- drawText (getCandidate (i ), canvas , paintCandidate , tfCandidate , x , y );
167
+ candidatePaint .setColor (
168
+ isHighlighted (i ) ? hilitedCandidateTextColor : candidateTextColor );
169
+ drawText (getTabText (i ), canvas , candidatePaint , candidateFont , x , y );
180
170
// Draw the separator at the right edge of each candidate.
181
- candidateSeparator .setBounds (
182
- candidateRect [i ].right - candidateSeparator .getIntrinsicWidth (),
183
- candidateRect [i ].top ,
184
- candidateRect [i ].right + candidate_spacing ,
185
- candidateRect [i ].bottom );
186
- candidateSeparator .draw (canvas );
171
+ canvas .drawRect (
172
+ tabGeometries [i ].right - candidateSpacing ,
173
+ tabGeometries [i ].top ,
174
+ tabGeometries [i ].right + candidateSpacing ,
175
+ tabGeometries [i ].bottom ,
176
+ separatorPaint
177
+ );
187
178
i ++;
188
179
}
189
180
}
@@ -200,25 +191,19 @@ protected void onDraw(Canvas canvas) {
200
191
}
201
192
202
193
public void updateCandidateWidth () {
203
- final int top = 0 ;
204
- final int bottom = getHeight ();
205
- int i ;
206
- int x = 0 ;
207
-
208
- candidates = TabManager .get ().getTabCandidates ();
194
+ tabTags = TabManager .get ().getTabCandidates ();
209
195
highlightIndex = TabManager .get ().getSelected ();
210
- num_candidates = candidates .length ;
211
196
212
- for (i = 0 ; i < num_candidates ; i ++) {
213
- candidateRect [i ] = new Rect (x , top , x += getCandidateWidth (i ), bottom );
214
- x += candidate_spacing ;
197
+ int x = 0 ;
198
+ for (int i = 0 ; i < tabTags .length ; i ++) {
199
+ tabGeometries [i ] = new Rect (x , 0 , x += getTabWidth (i ), getHeight ());
200
+ x += candidateSpacing ;
215
201
}
216
202
LayoutParams params = getLayoutParams ();
217
203
Timber .i ("update, from Height=" + params .height + " width=" + params .width );
218
204
params .width = x ;
219
- params .height = candidate_view_height ;
220
- if (show_comment && comment_on_top ) params .height += comment_height ;
221
- Timber .i ("update, to Height=" + candidate_view_height + " width=" + x );
205
+ params .height = (shouldShowComment && isCommentOnTop ) ? candidateViewHeight + commentHeight : candidateViewHeight ;
206
+ Timber .i ("update, to Height=" + candidateViewHeight + " width=" + x );
222
207
setLayoutParams (params );
223
208
params = getLayoutParams ();
224
209
Timber .i ("update, reload Height=" + params .height + " width=" + params .width );
@@ -241,23 +226,22 @@ public boolean performClick() {
241
226
long time0 ;
242
227
243
228
@ Override
244
- public boolean onTouchEvent (MotionEvent me ) {
245
- int action = me .getAction ();
229
+ public boolean onTouchEvent (@ NonNull MotionEvent me ) {
246
230
int x = (int ) me .getX ();
247
231
int y = (int ) me .getY ();
248
232
249
- switch (action ) {
233
+ switch (me . getActionMasked () ) {
250
234
case MotionEvent .ACTION_DOWN :
251
235
x0 = x ;
252
236
y0 = y ;
253
237
time0 = System .currentTimeMillis ();
254
238
// updateHighlight(x, y);
255
239
break ;
256
240
case MotionEvent .ACTION_MOVE :
257
- if (x - x0 > 100 || x0 - x > 100 ) time0 = 0 ;
241
+ if (Math . abs ( x - x0 ) > 100 ) time0 = 0 ;
258
242
break ;
259
243
case MotionEvent .ACTION_UP :
260
- int i = getCandidateIndex (x , y );
244
+ int i = getTabIndex (x , y );
261
245
if (i > -1 ) {
262
246
performClick ();
263
247
TabTag tag = TabManager .getTag (i );
@@ -279,7 +263,7 @@ public boolean onTouchEvent(MotionEvent me) {
279
263
invalidate ();
280
264
Trime .getService ().selectLiquidKeyboard (i );
281
265
}
282
- Timber .d ("index=" + i + " length=" + candidates .length );
266
+ Timber .d ("index=" + i + " length=" + tabTags .length );
283
267
}
284
268
break ;
285
269
}
@@ -293,36 +277,34 @@ public boolean onTouchEvent(MotionEvent me) {
293
277
* @param y 觸摸點縱座標
294
278
* @return {@code >=0}: 觸摸點 (x, y) 處候選項序號,從0開始編號; {@code -1}: 觸摸點 (x, y) 處無候選項;
295
279
*/
296
- private int getCandidateIndex (int x , int y ) {
280
+ private int getTabIndex (int x , int y ) {
297
281
Rect r = new Rect ();
298
282
299
283
int j = 0 ;
300
- for (int i = 0 ; i < num_candidates ; i ++) {
284
+ for (int i = 0 ; i < tabTags . length ; i ++) {
301
285
// Enlarge the rectangle to be more responsive to user clicks.
302
- r .set (candidateRect [j ++]);
286
+ r .set (tabGeometries [j ++]);
303
287
r .inset (0 , CANDIDATE_TOUCH_OFFSET );
304
288
if (r .contains (x , y )) {
305
289
// Returns -1 if there is no candidate in the hitting rectangle.
306
- return (i < num_candidates ) ? i : -1 ;
290
+ return (i < tabTags . length ) ? i : -1 ;
307
291
}
308
292
}
309
293
return -1 ;
310
294
}
311
295
312
- private String getCandidate (int i ) {
313
- if (candidates != null && i >= 0 ) return candidates [i ].text ;
296
+ private String getTabText (int i ) {
297
+ if (tabTags != null && i >= 0 ) return tabTags [i ].text ;
314
298
return "-1" ;
315
299
}
316
300
317
301
private float measureText (String s , Paint paint , Typeface font ) {
302
+ if (TextUtils .isEmpty (s )) return 0 ;
318
303
float x = 0 ;
319
- if (s == null ) return x ;
320
- int length = s .length ();
321
- if (length == 0 ) return x ;
322
- int points = s .codePointCount (0 , length );
323
- if (tfLatin != Typeface .DEFAULT || (tfHanB != Typeface .DEFAULT && length > points )) {
304
+ int codePoints = s .codePointCount (0 , s .length ());
305
+ if (latinFont != Typeface .DEFAULT || (hanBFont != Typeface .DEFAULT && s .length () > codePoints )) {
324
306
int offset = 0 ;
325
- while (offset < length ) {
307
+ while (offset < s . length () ) {
326
308
int codepoint = s .codePointAt (offset );
327
309
int charCount = Character .charCount (codepoint );
328
310
int end = offset + charCount ;
@@ -338,10 +320,8 @@ private float measureText(String s, Paint paint, Typeface font) {
338
320
return x ;
339
321
}
340
322
341
- private float getCandidateWidth (int i ) {
342
- String s = getCandidate (i );
343
- float x = 2 * candidate_padding ;
344
- if (s != null ) x += measureText (s , paintCandidate , tfCandidate );
345
- return x ;
323
+ private float getTabWidth (int i ) {
324
+ String s = getTabText (i );
325
+ return s != null ? 2 * candidatePadding + measureText (s , candidatePaint , candidateFont ) : 2 * candidatePadding ;
346
326
}
347
327
}
0 commit comments