fix: get visible char start and end are not correct

This commit is contained in:
hyb1996
2018-02-23 12:35:07 +08:00
parent e4cda0b64f
commit 6f9b302e9b
3 changed files with 37 additions and 17 deletions

View File

@@ -24,10 +24,10 @@ import android.graphics.Paint;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.support.v7.widget.AppCompatEditText; import android.support.v7.widget.AppCompatEditText;
import android.text.Layout; import android.text.Layout;
import android.text.method.ScrollingMovementMethod;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.util.TimingLogger;
import android.view.Gravity; import android.view.Gravity;
import android.view.View;
import com.stardust.scriptdroid.ui.edit.theme.Theme; import com.stardust.scriptdroid.ui.edit.theme.Theme;
@@ -38,13 +38,15 @@ import com.stardust.scriptdroid.ui.edit.theme.Theme;
public class CodeEditText extends AppCompatEditText { public class CodeEditText extends AppCompatEditText {
private static final String LOG_TAG = "CodeEditText"; static final String LOG_TAG = "CodeEditText";
private static final boolean DEBUG = true;
// 文字范围 // 文字范围
protected HVScrollView mScrollView; protected HVScrollView mParentScrollView;
private CodeEditor.CursorChangeCallback mCallback; private CodeEditor.CursorChangeCallback mCallback;
private volatile JavaScriptHighlighter.HighlightTokens mHighlightTokens; private volatile JavaScriptHighlighter.HighlightTokens mHighlightTokens;
private Theme mTheme; private Theme mTheme;
private TimingLogger mLogger = new TimingLogger(LOG_TAG, "draw");
public CodeEditText(Context context) { public CodeEditText(Context context) {
super(context); super(context);
@@ -64,7 +66,6 @@ public class CodeEditText extends AppCompatEditText {
setTextColor(Color.TRANSPARENT); setTextColor(Color.TRANSPARENT);
// 设置字体 // 设置字体
setTypeface(Typeface.MONOSPACE); setTypeface(Typeface.MONOSPACE);
setMovementMethod(ScrollingMovementMethod.getInstance());
setHorizontallyScrolling(true); setHorizontallyScrolling(true);
mTheme = Theme.getDefault(getContext()); mTheme = Theme.getDefault(getContext());
} }
@@ -76,8 +77,9 @@ public class CodeEditText extends AppCompatEditText {
@Override @Override
protected void onDraw(Canvas canvas) { protected void onDraw(Canvas canvas) {
if (mScrollView == null) { mLogger.reset();
mScrollView = (HVScrollView) getParent(); if (mParentScrollView == null) {
mParentScrollView = (HVScrollView) getParent();
} }
// 根据行号计算左边距padding 留出绘制行号的空间 // 根据行号计算左边距padding 留出绘制行号的空间
String max = Integer.toString(getLineCount()); String max = Integer.toString(getLineCount());
@@ -86,11 +88,14 @@ public class CodeEditText extends AppCompatEditText {
setPadding((int) gutterWidth, 0, 0, 0); setPadding((int) gutterWidth, 0, 0, 0);
} }
super.onDraw(canvas); super.onDraw(canvas);
mLogger.addSplit("super draw");
// 画文字 // 画文字
canvas.save(); canvas.save();
canvas.translate(0, getExtendedPaddingTop()); canvas.translate(0, getExtendedPaddingTop());
drawText(canvas); drawText(canvas);
mLogger.addSplit("draw text");
canvas.restore(); canvas.restore();
mLogger.dumpToLog();
} }
// 绘制文本着色 // 绘制文本着色
@@ -106,6 +111,8 @@ public class CodeEditText extends AppCompatEditText {
int lineCount = getLineCount(); int lineCount = getLineCount();
int paddingLeft = getPaddingLeft(); int paddingLeft = getPaddingLeft();
Paint paint = getPaint(); Paint paint = getPaint();
if (DEBUG)
Log.d(LOG_TAG, "draw line: " + (lastLineForDraw - firstLineForDraw + 1));
for (int line = firstLineForDraw; line <= lastLineForDraw && line < lineCount; line++) { for (int line = firstLineForDraw; line <= lastLineForDraw && line < lineCount; line++) {
int lineBottom = layout.getLineTop(line + 1); int lineBottom = layout.getLineTop(line + 1);
int lineBaseline = lineBottom - layout.getLineDescent(line); int lineBaseline = lineBottom - layout.getLineDescent(line);
@@ -115,7 +122,6 @@ public class CodeEditText extends AppCompatEditText {
continue; continue;
drawCode(canvas, paint, paddingLeft, line, layout, lineBaseline, highlightTokens); drawCode(canvas, paint, paddingLeft, line, layout, lineBaseline, highlightTokens);
} }
} }
@@ -126,10 +132,13 @@ public class CodeEditText extends AppCompatEditText {
} }
int lineEnd = layout.getLineVisibleEnd(line); int lineEnd = layout.getLineVisibleEnd(line);
int fontCount = 0; int fontCount = 0;
int previousColor = mHighlightTokens.getCharColor(lineStart); int scrollX = Math.max(getRealScrollX() - paddingLeft, 0);
int previousColorPos = lineStart; int visibleCharStart = getVisibleCharIndex(paint, scrollX, lineStart, lineEnd);
int visibleCharStart = getVisibleCharIndex(paint, getScrollX(), lineStart, lineEnd); int visibleCharEnd = getVisibleCharIndex(paint, scrollX + mParentScrollView.getWidth(), lineStart, lineEnd) + 1;
int visibleCharEnd = getVisibleCharIndex(paint, getScrollX() + getWidth(), lineStart, lineEnd) + 1; int previousColorPos = visibleCharStart;
int previousColor = mHighlightTokens.getCharColor(previousColorPos);
if (DEBUG)
Log.d(LOG_TAG, "draw line " + line + ": " + (visibleCharEnd - visibleCharStart));
for (int i = visibleCharStart; i < visibleCharEnd && i < lineEnd; i++) { for (int i = visibleCharStart; i < visibleCharEnd && i < lineEnd; i++) {
fontCount++; fontCount++;
int color = mHighlightTokens.getCharColor(i); int color = mHighlightTokens.getCharColor(i);
@@ -146,6 +155,7 @@ public class CodeEditText extends AppCompatEditText {
} }
private int getVisibleCharIndex(Paint paint, int x, int lineStart, int lineEnd) { private int getVisibleCharIndex(Paint paint, int x, int lineStart, int lineEnd) {
if (x == 0) if (x == 0)
return lineStart; return lineStart;
@@ -184,21 +194,27 @@ public class CodeEditText extends AppCompatEditText {
int scrollY = getRealScrollY(); int scrollY = getRealScrollY();
float clipTop = (scrollY == 0) ? 0 float clipTop = (scrollY == 0) ? 0
: getExtendedPaddingTop() + scrollY : getExtendedPaddingTop() + scrollY
- mScrollView.getPaddingTop(); - mParentScrollView.getPaddingTop();
canvas.clipRect(0, clipTop, getWidth(), scrollY canvas.clipRect(0, clipTop, getWidth(), scrollY
+ mScrollView.getHeight()); + mParentScrollView.getHeight());
long lineRangeForDraw = LayoutHelper.getLineRangeForDraw(layout, canvas); long lineRangeForDraw = LayoutHelper.getLineRangeForDraw(layout, canvas);
canvas.restore(); canvas.restore();
return lineRangeForDraw; return lineRangeForDraw;
} }
private int getRealScrollY() { private int getRealScrollY() {
return mScrollView.getScrollY() + getScrollY(); return mParentScrollView.getScrollY() + getScrollY();
}
private int getRealScrollX() {
return mParentScrollView.getScrollX() + getScrollX();
} }
@Override @Override
protected void onSelectionChanged(int selStart, int selEnd) { protected void onSelectionChanged(int selStart, int selEnd) {
super.onSelectionChanged(selStart, selEnd); //调用父类的onSelectionChanged时会发送一个AccessibilityEvent当文本过大时造成异常
//super.onSelectionChanged(selStart, selEnd);
if (mCallback == null || selStart != selEnd) { if (mCallback == null || selStart != selEnd) {
return; return;
} }

View File

@@ -3,6 +3,7 @@ package com.stardust.scriptdroid.ui.edit.editor;
import android.text.Editable; import android.text.Editable;
import android.util.Log; import android.util.Log;
import android.util.TimingLogger;
import com.stardust.autojs.rhino.TokenStream; import com.stardust.autojs.rhino.TokenStream;
import com.stardust.pio.UncheckedIOException; import com.stardust.pio.UncheckedIOException;
@@ -64,6 +65,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
private CodeEditText mCodeEditText; private CodeEditText mCodeEditText;
private ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
private AtomicInteger mRunningHighlighterId = new AtomicInteger(); private AtomicInteger mRunningHighlighterId = new AtomicInteger();
private TimingLogger mLogger = new TimingLogger(CodeEditText.LOG_TAG, "highlight");
public JavaScriptHighlighter(Theme theme, CodeEditText codeEditText) { public JavaScriptHighlighter(Theme theme, CodeEditText codeEditText) {
mTheme = theme; mTheme = theme;
@@ -85,7 +87,10 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
final int id = mRunningHighlighterId.incrementAndGet(); final int id = mRunningHighlighterId.incrementAndGet();
mExecutorService.execute(() -> { mExecutorService.execute(() -> {
try { try {
mLogger.reset();
updateTokens(sourceString, id); updateTokens(sourceString, id);
mLogger.addSplit("parse tokens");
mLogger.dumpToLog();
} catch (IOException neverHappen) { } catch (IOException neverHappen) {
throw new UncheckedIOException(neverHappen); throw new UncheckedIOException(neverHappen);
} }

View File

@@ -4,7 +4,6 @@
android:id="@+id/code_edit_text" android:id="@+id/code_edit_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scrollbars="horizontal"
android:textColor="@android:color/transparent" android:textColor="@android:color/transparent"
android:textCursorDrawable="@drawable/code_edit_text_cursor" android:textCursorDrawable="@drawable/code_edit_text_cursor"
android:textSize="15sp"/> android:textSize="15sp"/>