fix: get visible char start and end are not correct
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user