From 6f9b302e9bd4e506648e1b123b21826af9378ef3 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Fri, 23 Feb 2018 12:35:07 +0800 Subject: [PATCH] fix: get visible char start and end are not correct --- .../ui/edit/editor/CodeEditText.java | 48 ++++++++++++------- .../ui/edit/editor/JavaScriptHighlighter.java | 5 ++ app/src/main/res/layout/code_editor.xml | 1 - 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/edit/editor/CodeEditText.java b/app/src/main/java/com/stardust/scriptdroid/ui/edit/editor/CodeEditText.java index 7268f426..569cfdbf 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/edit/editor/CodeEditText.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/edit/editor/CodeEditText.java @@ -24,10 +24,10 @@ import android.graphics.Paint; import android.graphics.Typeface; import android.support.v7.widget.AppCompatEditText; import android.text.Layout; -import android.text.method.ScrollingMovementMethod; import android.util.AttributeSet; +import android.util.Log; +import android.util.TimingLogger; import android.view.Gravity; -import android.view.View; 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 { - 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 volatile JavaScriptHighlighter.HighlightTokens mHighlightTokens; private Theme mTheme; + private TimingLogger mLogger = new TimingLogger(LOG_TAG, "draw"); public CodeEditText(Context context) { super(context); @@ -64,7 +66,6 @@ public class CodeEditText extends AppCompatEditText { setTextColor(Color.TRANSPARENT); // 设置字体 setTypeface(Typeface.MONOSPACE); - setMovementMethod(ScrollingMovementMethod.getInstance()); setHorizontallyScrolling(true); mTheme = Theme.getDefault(getContext()); } @@ -76,8 +77,9 @@ public class CodeEditText extends AppCompatEditText { @Override protected void onDraw(Canvas canvas) { - if (mScrollView == null) { - mScrollView = (HVScrollView) getParent(); + mLogger.reset(); + if (mParentScrollView == null) { + mParentScrollView = (HVScrollView) getParent(); } // 根据行号计算左边距padding 留出绘制行号的空间 String max = Integer.toString(getLineCount()); @@ -86,11 +88,14 @@ public class CodeEditText extends AppCompatEditText { setPadding((int) gutterWidth, 0, 0, 0); } super.onDraw(canvas); + mLogger.addSplit("super draw"); // 画文字 canvas.save(); canvas.translate(0, getExtendedPaddingTop()); drawText(canvas); + mLogger.addSplit("draw text"); canvas.restore(); + mLogger.dumpToLog(); } // 绘制文本着色 @@ -106,6 +111,8 @@ public class CodeEditText extends AppCompatEditText { int lineCount = getLineCount(); int paddingLeft = getPaddingLeft(); Paint paint = getPaint(); + if (DEBUG) + Log.d(LOG_TAG, "draw line: " + (lastLineForDraw - firstLineForDraw + 1)); for (int line = firstLineForDraw; line <= lastLineForDraw && line < lineCount; line++) { int lineBottom = layout.getLineTop(line + 1); int lineBaseline = lineBottom - layout.getLineDescent(line); @@ -115,7 +122,6 @@ public class CodeEditText extends AppCompatEditText { continue; drawCode(canvas, paint, paddingLeft, line, layout, lineBaseline, highlightTokens); - } } @@ -126,10 +132,13 @@ public class CodeEditText extends AppCompatEditText { } int lineEnd = layout.getLineVisibleEnd(line); int fontCount = 0; - int previousColor = mHighlightTokens.getCharColor(lineStart); - int previousColorPos = lineStart; - int visibleCharStart = getVisibleCharIndex(paint, getScrollX(), lineStart, lineEnd); - int visibleCharEnd = getVisibleCharIndex(paint, getScrollX() + getWidth(), lineStart, lineEnd) + 1; + int scrollX = Math.max(getRealScrollX() - paddingLeft, 0); + int visibleCharStart = getVisibleCharIndex(paint, scrollX, lineStart, lineEnd); + int visibleCharEnd = getVisibleCharIndex(paint, scrollX + mParentScrollView.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++) { fontCount++; 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) { if (x == 0) return lineStart; @@ -184,21 +194,27 @@ public class CodeEditText extends AppCompatEditText { int scrollY = getRealScrollY(); float clipTop = (scrollY == 0) ? 0 : getExtendedPaddingTop() + scrollY - - mScrollView.getPaddingTop(); + - mParentScrollView.getPaddingTop(); canvas.clipRect(0, clipTop, getWidth(), scrollY - + mScrollView.getHeight()); + + mParentScrollView.getHeight()); long lineRangeForDraw = LayoutHelper.getLineRangeForDraw(layout, canvas); canvas.restore(); return lineRangeForDraw; } private int getRealScrollY() { - return mScrollView.getScrollY() + getScrollY(); + return mParentScrollView.getScrollY() + getScrollY(); + } + + + private int getRealScrollX() { + return mParentScrollView.getScrollX() + getScrollX(); } @Override protected void onSelectionChanged(int selStart, int selEnd) { - super.onSelectionChanged(selStart, selEnd); + //调用父类的onSelectionChanged时会发送一个AccessibilityEvent,当文本过大时造成异常 + //super.onSelectionChanged(selStart, selEnd); if (mCallback == null || selStart != selEnd) { return; } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/edit/editor/JavaScriptHighlighter.java b/app/src/main/java/com/stardust/scriptdroid/ui/edit/editor/JavaScriptHighlighter.java index 677b9eb5..77cca0fc 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/edit/editor/JavaScriptHighlighter.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/edit/editor/JavaScriptHighlighter.java @@ -3,6 +3,7 @@ package com.stardust.scriptdroid.ui.edit.editor; import android.text.Editable; import android.util.Log; +import android.util.TimingLogger; import com.stardust.autojs.rhino.TokenStream; import com.stardust.pio.UncheckedIOException; @@ -64,6 +65,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged private CodeEditText mCodeEditText; private ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); private AtomicInteger mRunningHighlighterId = new AtomicInteger(); + private TimingLogger mLogger = new TimingLogger(CodeEditText.LOG_TAG, "highlight"); public JavaScriptHighlighter(Theme theme, CodeEditText codeEditText) { mTheme = theme; @@ -85,7 +87,10 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged final int id = mRunningHighlighterId.incrementAndGet(); mExecutorService.execute(() -> { try { + mLogger.reset(); updateTokens(sourceString, id); + mLogger.addSplit("parse tokens"); + mLogger.dumpToLog(); } catch (IOException neverHappen) { throw new UncheckedIOException(neverHappen); } diff --git a/app/src/main/res/layout/code_editor.xml b/app/src/main/res/layout/code_editor.xml index 4d81a249..68a0d4e3 100644 --- a/app/src/main/res/layout/code_editor.xml +++ b/app/src/main/res/layout/code_editor.xml @@ -4,7 +4,6 @@ android:id="@+id/code_edit_text" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:scrollbars="horizontal" android:textColor="@android:color/transparent" android:textCursorDrawable="@drawable/code_edit_text_cursor" android:textSize="15sp"/>