Skip to content

Commit

Permalink
refactor(text): Optimize how to recompute tab geometry
Browse files Browse the repository at this point in the history
- full scope: TabView, TabTag, TabManager
- fix: mistouch caused by too large response area
  • Loading branch information
WhiredPlanck authored and Bambooin committed Oct 23, 2021
1 parent 3f8824d commit da36fa0
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 61 deletions.
6 changes: 3 additions & 3 deletions app/src/main/java/com/osfans/trime/ime/symbol/TabManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
public class TabManager {
private int selected;
private final List<SimpleKeyBean> keyboard;
private final List<TabTag> tabTags;
private final ArrayList<TabTag> tabTags;
private final List<List<SimpleKeyBean>> keyboards;
private static TabManager self;
private final List<SimpleKeyBean> notKeyboard = new ArrayList<>();
Expand Down Expand Up @@ -123,7 +123,7 @@ public int getSelected() {
return selected;
}

public TabTag[] getTabCandidates() {
public ArrayList<TabTag> getTabCandidates() {
boolean addExit = true;
for (TabTag tag : tabTags) {
if (tag.command == KeyCommandType.EXIT) {
Expand All @@ -135,6 +135,6 @@ public TabTag[] getTabCandidates() {
tabTags.add(tagExit);
keyboards.add(notKeyboard);
}
return tabTags.toArray(new TabTag[0]);
return tabTags;
}
}
3 changes: 3 additions & 0 deletions app/src/main/java/com/osfans/trime/ime/symbol/TabTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
// Tab是滑动键盘顶部的标签按钮(包含返回键)。
// 为了公用候选栏的皮肤参数以及外观,保持了和普通键盘布局相似的代码。此类相当于原键盘布局的Rime.RimeCandidate

import android.graphics.Rect;

import com.osfans.trime.ime.enums.KeyCommandType;
import com.osfans.trime.ime.enums.SymbolKeyboardType;

public class TabTag {
String text; // text for tab
Rect geometry; // position and size info of tab
String comment; // not used
SymbolKeyboardType type; //
KeyCommandType command; // command for tag without key
Expand Down
102 changes: 44 additions & 58 deletions app/src/main/java/com/osfans/trime/ime/symbol/TabView.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import com.osfans.trime.setup.Config;
import com.osfans.trime.util.GraphicUtils;

import java.util.ArrayList;

import timber.log.Timber;

// 这是滑动键盘顶部的view,展示了键盘布局的多个标签。
Expand All @@ -45,7 +47,7 @@ public class TabView extends View {
private static final int CANDIDATE_TOUCH_OFFSET = -12;

private int highlightIndex;
private TabTag[] tabTags;
private ArrayList<TabTag> tabTags;
private final GraphicUtils graphicUtils;

private PaintDrawable candidateHighlight;
Expand All @@ -57,8 +59,7 @@ public class TabView extends View {
private final boolean shouldShowComment = true;
private boolean isCommentOnTop;
private boolean shouldCandidateUseCursor;

private final Rect[] tabGeometries = new Rect[MAX_CANDIDATE_COUNT + 2];
// private final Rect[] tabGeometries = new Rect[MAX_CANDIDATE_COUNT + 2];

public void reset(Context context) {
Config config = Config.get(context);
Expand Down Expand Up @@ -107,65 +108,58 @@ private boolean isHighlighted(int i) {
return shouldCandidateUseCursor && i >= 0 && i == highlightIndex;
}

private void drawHighlight(Canvas canvas) {
if (isHighlighted(highlightIndex)) {
candidateHighlight.setBounds(tabGeometries[highlightIndex]);
candidateHighlight.draw(canvas);
}
}

public int getHightlightLeft() {
return tabGeometries[highlightIndex].left;
return tabTags.get(highlightIndex).geometry.left;
}

public int getHightlightRight() {
return tabGeometries[highlightIndex].right;
return tabTags.get(highlightIndex).geometry.right;
}

private void drawCandidates(Canvas canvas) {
@Override
protected void onDraw(Canvas canvas) {
if (canvas == null) return;
if (tabTags == null) return;
super.onDraw(canvas);

float y = tabGeometries[0].centerY() - (candidatePaint.ascent() + candidatePaint.descent()) / 2;
if (shouldShowComment && isCommentOnTop) y += (float) commentHeight / 2;

int i = 0;
while (i < tabTags.length) {
// Draw highlight background
if (isHighlighted(highlightIndex)) {
candidateHighlight.setBounds(tabTags.get(highlightIndex).geometry);
candidateHighlight.draw(canvas);
}
// Draw tab text
float tabY = (shouldShowComment && isCommentOnTop)
? tabTags.get(0).geometry.centerY() - (candidatePaint.ascent() + candidatePaint.descent()) / 2.0f
+ commentHeight / 2.0f
: tabTags.get(0).geometry.centerY() - (candidatePaint.ascent() + candidatePaint.descent()) / 2.0f;

for (TabTag computedTab: tabTags) {
int i = tabTags.indexOf(computedTab);
// Calculate a position where the text could be centered in the rectangle.
float x = tabGeometries[i].centerX();
float tabX = computedTab.geometry.centerX();

candidatePaint.setColor(
isHighlighted(i) ? hilitedCandidateTextColor : candidateTextColor);
graphicUtils.drawText(canvas, getTabText(i), x, y,candidatePaint, candidateFont);
isHighlighted(i) ? hilitedCandidateTextColor : candidateTextColor);
graphicUtils.drawText(canvas, computedTab.text, tabX, tabY, candidatePaint, candidateFont);
// Draw the separator at the right edge of each candidate.
canvas.drawRect(
tabGeometries[i].right - candidateSpacing,
tabGeometries[i].top,
tabGeometries[i].right + candidateSpacing,
tabGeometries[i].bottom,
computedTab.geometry.right - candidateSpacing,
computedTab.geometry.top,
computedTab.geometry.right + candidateSpacing,
computedTab.geometry.bottom,
separatorPaint
);
i++;
}
}

@Override
protected void onDraw(Canvas canvas) {
if (canvas == null) {
return;
}
super.onDraw(canvas);

drawHighlight(canvas);
drawCandidates(canvas);
}

public void updateCandidateWidth() {
tabTags = TabManager.get().getTabCandidates();
highlightIndex = TabManager.get().getSelected();

int x = 0;
for (int i = 0; i < tabTags.length; i++) {
tabGeometries[i] = new Rect(x, 0, x += getTabWidth(i), getHeight());
for (TabTag computedTab: tabTags) {
int i = tabTags.indexOf(computedTab);
computedTab.geometry = new Rect(x, 0, x += getTabWidth(i), getHeight());
x += candidateSpacing;
}
LayoutParams params = getLayoutParams();
Expand Down Expand Up @@ -219,7 +213,6 @@ public boolean onTouchEvent(@NonNull MotionEvent me) {
case EXIT:
Trime.getService().selectLiquidKeyboard(-1);
break;

// TODO liquidKeyboard中除返回按钮外,其他按键均未实装
case DEL_LEFT:
case DEL_RIGHT:
Expand All @@ -232,7 +225,7 @@ public boolean onTouchEvent(@NonNull MotionEvent me) {
invalidate();
Trime.getService().selectLiquidKeyboard(i);
}
Timber.d("index=" + i + " length=" + tabTags.length);
Timber.d("index=" + i + " length=" + tabTags.size());
}
break;
}
Expand All @@ -247,28 +240,21 @@ public boolean onTouchEvent(@NonNull MotionEvent me) {
* @return {@code >=0}: 觸摸點 (x, y) 處候選項序號,從0開始編號; {@code -1}: 觸摸點 (x, y) 處無候選項;
*/
private int getTabIndex(int x, int y) {
Rect r = new Rect();

int j = 0;
for (int i = 0; i < tabTags.length; i++) {
// Enlarge the rectangle to be more responsive to user clicks.
r.set(tabGeometries[j++]);
r.inset(0, CANDIDATE_TOUCH_OFFSET);
if (r.contains(x, y)) {
// Returns -1 if there is no candidate in the hitting rectangle.
return (i < tabTags.length) ? i : -1;
//Rect r = new Rect();
int retIndex = -1; // Returns -1 if there is no tab in the hitting rectangle.
for (TabTag computedTab: tabTags) {
/* Enlarge the rectangle to be more responsive to user clicks.
// r.set(tabGeometries[j++]);
//r.inset(0, CANDIDATE_TOUCH_OFFSET); */
if (computedTab.geometry.contains(x, y)) {
retIndex = tabTags.indexOf(computedTab);
}
}
return -1;
}

private String getTabText(int i) {
if (tabTags != null && i >= 0) return tabTags[i].text;
return "-1";
return retIndex;
}

private float getTabWidth(int i) {
String s = getTabText(i);
String s = tabTags.get(i).text;
return s != null ? 2 * candidatePadding + graphicUtils.measureText(candidatePaint, s, candidateFont) : 2 * candidatePadding;
}
}

0 comments on commit da36fa0

Please sign in to comment.