From cc3ec6cdb2b892eb29513e72d8b205acbe997b25 Mon Sep 17 00:00:00 2001 From: Gilles Debunne Date: Wed, 23 Jun 2010 10:30:27 -0700 Subject: [PATCH] New cursor controller in TextViews. Editable TextView now display a cursor controller under the insertion point so that it can be precisely moved. Change-Id: Ia2e6ddc57d249647ff6683e10e4226db3df27223 --- api/current.xml | 112 ++++++ core/java/android/text/TextLine.java | 4 +- .../text/method/ArrowKeyMovementMethod.java | 76 +++- core/java/android/text/method/Touch.java | 4 +- core/java/android/widget/TextView.java | 331 ++++++++++++++++-- .../res/drawable-hdpi/cursor_controller.png | Bin 0 -> 2886 bytes .../res/drawable-mdpi/cursor_controller.png | Bin 0 -> 1622 bytes core/res/res/values/dimens.xml | 2 + graphics/java/android/graphics/Canvas.java | 9 +- graphics/java/android/graphics/Rect.java | 6 +- 10 files changed, 489 insertions(+), 55 deletions(-) create mode 100644 core/res/res/drawable-hdpi/cursor_controller.png create mode 100644 core/res/res/drawable-mdpi/cursor_controller.png diff --git a/api/current.xml b/api/current.xml index 16de702b6ec3f..db2456a339570 100644 --- a/api/current.xml +++ b/api/current.xml @@ -166294,6 +166294,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + vspace / 4) @@ -5730,22 +5738,28 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - private void getInterestingRect(Rect r, int h, int top, int bottom, - int line) { + private void getInterestingRect(Rect r, int line) { + convertFromViewportToContentCoordinates(r); + + // Rectangle can can be expanded on first and last line to take + // padding into account. + // TODO Take left/right padding into account too? + if (line == 0) r.top -= getExtendedPaddingTop(); + if (line == mLayout.getLineCount() - 1) r.bottom += getExtendedPaddingBottom(); + } + + private void convertFromViewportToContentCoordinates(Rect r) { int paddingTop = getExtendedPaddingTop(); if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) { paddingTop += getVerticalOffset(false); } - top += paddingTop; - bottom += paddingTop; - h += getCompoundPaddingLeft(); + r.top += paddingTop; + r.bottom += paddingTop; - if (line == 0) - top -= getExtendedPaddingTop(); - if (line == mLayout.getLineCount() - 1) - bottom += getExtendedPaddingBottom(); + int paddingLeft = getCompoundPaddingLeft(); + r.left += paddingLeft; + r.right += paddingLeft; - r.set(h, top, h+1, bottom); r.offset(-mScrollX, -mScrollY); } @@ -5913,6 +5927,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } else if (mBlink != null) { mBlink.removeCallbacks(mBlink); } + prepareCursorController(); } private boolean canMarquee() { @@ -6327,7 +6342,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } } else { - if (DEBUG_EXTRACT) Log.v(TAG, "Span change outside of batch: " + if (DEBUG_EXTRACT) Log.v(LOG_TAG, "Span change outside of batch: " + oldStart + "-" + oldEnd + "," + newStart + "-" + newEnd + what); ims.mContentChanged = true; @@ -6343,7 +6358,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void beforeTextChanged(CharSequence buffer, int start, int before, int after) { - if (DEBUG_EXTRACT) Log.v(TAG, "beforeTextChanged start=" + start + if (DEBUG_EXTRACT) Log.v(LOG_TAG, "beforeTextChanged start=" + start + " before=" + before + " after=" + after + ": " + buffer); if (AccessibilityManager.getInstance(mContext).isEnabled() @@ -6356,7 +6371,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void onTextChanged(CharSequence buffer, int start, int before, int after) { - if (DEBUG_EXTRACT) Log.v(TAG, "onTextChanged start=" + start + if (DEBUG_EXTRACT) Log.v(LOG_TAG, "onTextChanged start=" + start + " before=" + before + " after=" + after + ": " + buffer); TextView.this.handleTextChanged(buffer, start, before, after); @@ -6366,10 +6381,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after); mBeforeText = null; } + + // TODO. The cursor controller should hide as soon as text is typed. + // But this method is also used for cosmetic changes (underline current word when + // spell corrections are displayed. There is currently no way to make the difference + // between these cosmetic changes and actual text modifications. } public void afterTextChanged(Editable buffer) { - if (DEBUG_EXTRACT) Log.v(TAG, "afterTextChanged: " + buffer); + if (DEBUG_EXTRACT) Log.v(LOG_TAG, "afterTextChanged: " + buffer); TextView.this.sendAfterTextChanged(buffer); if (MetaKeyKeyListener.getMetaState(buffer, @@ -6380,19 +6400,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void onSpanChanged(Spannable buf, Object what, int s, int e, int st, int en) { - if (DEBUG_EXTRACT) Log.v(TAG, "onSpanChanged s=" + s + " e=" + e + if (DEBUG_EXTRACT) Log.v(LOG_TAG, "onSpanChanged s=" + s + " e=" + e + " st=" + st + " en=" + en + " what=" + what + ": " + buf); TextView.this.spanChange(buf, what, s, st, e, en); } public void onSpanAdded(Spannable buf, Object what, int s, int e) { - if (DEBUG_EXTRACT) Log.v(TAG, "onSpanAdded s=" + s + " e=" + e + if (DEBUG_EXTRACT) Log.v(LOG_TAG, "onSpanAdded s=" + s + " e=" + e + " what=" + what + ": " + buf); TextView.this.spanChange(buf, what, -1, s, -1, e); } public void onSpanRemoved(Spannable buf, Object what, int s, int e) { - if (DEBUG_EXTRACT) Log.v(TAG, "onSpanRemoved s=" + s + " e=" + e + if (DEBUG_EXTRACT) Log.v(LOG_TAG, "onSpanRemoved s=" + s + " e=" + e + " what=" + what + ": " + buf); TextView.this.spanChange(buf, what, s, -1, e, -1); } @@ -6589,6 +6609,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (resultCode == InputMethodManager.RESULT_SHOWN) { start = mPrevStart; end = mPrevEnd; + } else if (mInsertionPointCursorController != null) { + mInsertionPointCursorController.show(); } final int len = mText.length(); @@ -6631,12 +6653,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int oldSelStart = Selection.getSelectionStart(mText); int oldSelEnd = Selection.getSelectionEnd(mText); - + + if (mInsertionPointCursorController != null) { + mInsertionPointCursorController.onTouchEvent(event); + } + if (mMovement != null) { handled |= mMovement.onTouchEvent(this, (Spannable) mText, event); } - if (mText instanceof Editable && onCheckIsTextEditor()) { + if (isTextEditable()) { if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) { InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); @@ -6650,7 +6676,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener newSelStart, newSelEnd); } - handled = imm.showSoftInput(this, 0, csr) && (csr != null); + handled |= imm.showSoftInput(this, 0, csr) && (csr != null); } } @@ -6662,6 +6688,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return superResult; } + private void prepareCursorController() { + // TODO Add an extra android:cursorController flag to disable the controller? + mInsertionPointCursorController = + mCursorVisible ? new InsertionPointCursorController() : null; + } + + /** + * @return True iff this TextView contains a text that can be edited. + */ + private boolean isTextEditable() { + return mText instanceof Editable && onCheckIsTextEditor(); + } + /** * Returns true, only while processing a touch gesture, if the initial * touch down event caused focus to move to the text view and as a result @@ -7341,6 +7380,229 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } + /** + * A CursorController instance can be used to control a cursor in the text. + * + * It can be passed to an {@link ArrowKeyMovementMethod} which can intercepts events + * and send them to this object instead of the cursor. + */ + public interface CursorController { + /** + * Makes the cursor controller visible on screen. Will be drawn by {@link #draw(Canvas)}. + * See also {@link #hide()}. + */ + public void show(); + + /** + * Hide the cursor controller from screen. + * See also {@link #show()}. + */ + public void hide(); + + /** + * Update the controller's position. + */ + public void updatePosition(); + + /** + * The controller and the cursor's positions can be link by a fixed offset, + * computed when the controller is touched, and then maintained as it moves + * @return Horizontal offset between the controller and the cursor. + */ + public int getOffsetX(); + + /** + * @return Vertical offset between the controller and the cursor. + */ + public int getOffsetY(); + + /** + * This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller + * a chance to become active and/or visible. + * @param event The touch event + */ + public void onTouchEvent(MotionEvent event); + + /** + * Draws a visual representation of the controller on the canvas. + * + * Called at the end of {@link #draw(Canvas)}, in the content coordinates system. + * @param canvas The Canvas used by this TextView. + */ + public void draw(Canvas canvas); + } + + class InsertionPointCursorController implements CursorController { + private static final int DELAY_BEFORE_FADE_OUT = 2100; + private static final int FADE_OUT_DURATION = 400; + + // Whether or not the cursor control is currently visible + private boolean mIsVisible = false; + // Current cursor control bounds, in content coordinates + private final Rect mBounds = new Rect(); + // Starting time of the fade timer + private long mFadeOutTimerStart; + // The cursor controller image + private final Drawable mDrawable; + // Used to detect a tap (vs drag) on the controller + private long mOnDownTimerStart; + // Offset between finger hot point on cursor controller and actual cursor + private int mOffsetX, mOffsetY; + + InsertionPointCursorController() { + Resources res = mContext.getResources(); + mDrawable = res.getDrawable(com.android.internal.R.drawable.cursor_controller); + } + + public void show() { + updatePosition(); + // Has to be done after updatePosition, so that previous position invalidate + // in only done if necessary. + mIsVisible = true; + } + + public void hide() { + if (mIsVisible) { + long time = System.currentTimeMillis(); + // Start fading out, only if not already in progress + if (time - mFadeOutTimerStart < DELAY_BEFORE_FADE_OUT) { + mFadeOutTimerStart = time - DELAY_BEFORE_FADE_OUT; + postInvalidate(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom); + } + } + } + + public void draw(Canvas canvas) { + if (mIsVisible) { + int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart); + if (time <= DELAY_BEFORE_FADE_OUT) { + postInvalidateDelayed(DELAY_BEFORE_FADE_OUT - time, + mBounds.left, mBounds.top, mBounds.right, mBounds.bottom); + } else { + time -= DELAY_BEFORE_FADE_OUT; + if (time <= FADE_OUT_DURATION) { + int alpha = 255 * (FADE_OUT_DURATION - time) / FADE_OUT_DURATION; + mDrawable.setAlpha(alpha); + postInvalidateDelayed(30, + mBounds.left, mBounds.top, mBounds.right, mBounds.bottom); + } else { + mDrawable.setAlpha(0); + mIsVisible = false; + } + } + mDrawable.draw(canvas); + } + } + + public void updatePosition() { + if (mIsVisible) { + // Clear previous cursor controller before bounds are updated + postInvalidate(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom); + } + + final int offset = Selection.getSelectionStart(mText); + + if (offset < 0) { + // Should never happen, safety check. + Log.w(LOG_TAG, "Update cursor controller position called with no cursor", null); + mIsVisible = false; + return; + } + + final int cursorControllerDrawableWidth = mDrawable.getIntrinsicWidth(); + final int cursorControllerDrawableHeight = mDrawable.getIntrinsicHeight(); + final int line = mLayout.getLineForOffset(offset); + + mBounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5 - + cursorControllerDrawableWidth / 2.0); + mBounds.top = mLayout.getLineTop(line + 1); + + // Move cursor controller a little bit up when editing the last line of text + // (or a single line) so that it is visible and easier to grab. + if (line == mLayout.getLineCount() - 1) { + mBounds.top -= Math.max(0, + cursorControllerDrawableHeight / 2 - getExtendedPaddingBottom()); + } + + mBounds.right = mBounds.left + cursorControllerDrawableWidth; + mBounds.bottom = mBounds.top + cursorControllerDrawableHeight; + + convertFromViewportToContentCoordinates(mBounds); + mDrawable.setBounds(mBounds); + + mFadeOutTimerStart = System.currentTimeMillis(); + mDrawable.setAlpha(255); + + postInvalidate(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom); + } + + public void onTouchEvent(MotionEvent event) { + if (isFocused() && isTextEditable()) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN && mIsVisible) { + final int x = (int) event.getX(); + final int y = (int) event.getY(); + + // Simulate a 'fat finger' to ease grabbing of the controller. + // Expand according to controller image size instead of using density. + // Assume controller imager has a sensible size, proportionnal to density. + final int cursorControllerDrawableWidth = mDrawable.getIntrinsicWidth(); + final int cursorControllerDrawableHeight = mDrawable.getIntrinsicHeight(); + final Rect fingerRect = new Rect( + x - cursorControllerDrawableWidth / 2, + y - cursorControllerDrawableHeight, + x + cursorControllerDrawableWidth / 2, + y); + + if (Rect.intersects(mBounds, fingerRect)) { + show(); + + if (mMovement instanceof ArrowKeyMovementMethod) { + ((ArrowKeyMovementMethod)mMovement).setCursorController(this); + } + + if (mParent != null) { + // Prevent possible scrollView parent from scrolling, so that + // we can use auto-scrolling. + mParent.requestDisallowInterceptTouchEvent(true); + + Resources res = mContext.getResources(); + final int verticalOffset = res.getDimensionPixelOffset( + com.android.internal.R.dimen.cursor_controller_vertical_offset); + + mOffsetX = (mBounds.left + mBounds.right) / 2 - x; + mOffsetY = mBounds.top - verticalOffset - y; + + mOnDownTimerStart = System.currentTimeMillis(); + } + } + } else if (event.getActionMasked() == MotionEvent.ACTION_UP) { + int time = (int) (System.currentTimeMillis() - mOnDownTimerStart); + + if (mIsVisible && (time <= ViewConfiguration.getTapTimeout())) { + // A tap on the controller is not grabbed, move the cursor instead + final int x = (int) event.getX(); + final int y = (int) event.getY(); + + Layout layout = getLayout(); + int line = layout.getLineForVertical(y); + int offset = layout.getOffsetForHorizontal(line, x); + Selection.setSelection((Spannable) mText, offset); + // Modified by cancelLongPress and prevents the cursor from changing + mScrolled = false; + } + } + } + } + + public int getOffsetX() { + return mOffsetX; + } + + public int getOffsetY() { + return mOffsetY; + } + } + @ViewDebug.ExportedProperty private CharSequence mText; private CharSequence mTransformed; @@ -7369,6 +7631,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private Blink mBlink; private boolean mCursorVisible = true; + // Cursor Controller. Null when disabled. + private CursorController mInsertionPointCursorController; + private boolean mSelectAllOnFocus = false; private int mGravity = Gravity.TOP | Gravity.LEFT; diff --git a/core/res/res/drawable-hdpi/cursor_controller.png b/core/res/res/drawable-hdpi/cursor_controller.png new file mode 100644 index 0000000000000000000000000000000000000000..720adedae21843f7e6afa39fcacaad436f931931 GIT binary patch literal 2886 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 k>qdbVG7wVRUJ4ZXi@?ZDjy7FEKVR zF)-{fL398B0338hSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q#1y$)1UwV1+Pg& zK~z|U&6i7vT}2wlf8V)}e%!XFJEl$h7{jOoF~*3xh|g_|GGL;EI3n52LIhEmQAAM? z!3WA@<+vD}l_(4&N`xp;7ZPwIGek@rS`-l-B&}(?O*(zx@L8-YKs#0=M9tQNGD&NBXjq~qFanGLSDm|M;^x0TbI&bXuh_J+QH-h8 zoc84f`|fW~{qyZ3AN=Qi;A3DJC?iygR`S^|iljAxR+DHH7zeJqWc!xu9(?u>cTaDg zm@PY}y>b^6e%{2T8ewYX;Oj>Y|NX^R4*{P7Ujt_{sN^q(!PWvwFvAkf0$1+cf8%X? z_HVnLT4(G`XOXhIqN>|ftr+#O#-z4P{@y1?X7%kC3v-X&|H7f~Pb_>0d_s`0BzP+s ze*kJ2Xf?kiiFN?n9zU@Eu1l|(+O^X8(N48b((#h2QxRSx)oV>})+W?yOl#(x-?^2o z#eW?5_n~**{O}O)U*J>(OQs)44>{0Uei;X@ot|m!dh+Fa@0pw#nLS-D*m8N2cC})1 z#kWZkk|PJNSxwF299=klxu!~m{LC`ma`4l@c&0@vPj>yAD9 z?z?(lqiLgMcd00=GgRI-ufQyf8b_FrW0Fe}ZWLG=bnx@z zU%eM4JToMr=RnE4DKcAuo%cPl_fOlepShu|mh4n{vZ&MrSMnIvAH;GCL)K+-N0MY# zc(XRHx{Ye~H<$TDZKnL!D~Aui@#?#814n`R97>WWpnN3loZ8&l^T5-8+H=TohUe6l6o8A;Pyxj=M>9Ms&f{Hfny952HBbmAZP*su~T%zc831%h- z1F07sdW{g8INF4wd?*lxcGaz9NS&ga`fX$biabI^b}o;L2rq<17}8v%zHHfYN{QBy z2q^%0mHdPU{REb#4~u;kDcHjiDuP=j5H5im1)x4y^22O!GfRUG1|D~hD$O~G9CS?is1+i zd@xRkd4X^b39vAW;Res1NdrFxB$qFkDdnbctB0wERZ7n@+0nzp;cE*I1Xd(tDYN-d zBS{(A%;J=y2pLnA%OziZ88R%H$M2Pc3dw>RCaW+DGN3FMrA*xmP5&2_i}@*dM(*+b zT6O(B0F)*<2^_~fs4FvB{NJLw`sKI9p-q-3J?1CNAfmye;d3D6Kxy3@R&_$%$|>A> zW5G-b!-mzj2oCXn3(i;UDE$|o4~epuSO#bO+(T6Y`gU$n-^?vy3BXV<7p@YUK-EtP zJsB-PrA!)gnE=iFc4?r`-fQAqHbQ^>vjf;pf18uo8X|5T_7iS5S|Ci+H5N7uk!las(wp~e`T(WM~p$IFw1XHj+%z9wC zPrLNDNWBFb44RsFF=?CcOg9R&8dUO6>bx3)85m_rTe6!H#Mwx-5y;d}#VW)8XBVdP Us2I8Cd;kCd07*qoM6N<$f)&*H>Hq)$ literal 0 HcmV?d00001 diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 61e7b882c085a..4d67bdd77a9a7 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -45,4 +45,6 @@ 56dip 4dip + + 12dp diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index a4df80cc3e9d7..77a1930b5fc3f 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -126,6 +126,7 @@ public class Canvas { * * @deprecated This constructor is not supported and should not be invoked. */ + @Deprecated public Canvas(GL gl) { mNativeCanvas = initGL(); mGL = gl; @@ -151,6 +152,7 @@ public class Canvas { * * @deprecated This method is not supported and should not be invoked. */ + @Deprecated public GL getGL() { return mGL; } @@ -162,6 +164,7 @@ public class Canvas { * * @deprecated This method is not supported and should not be invoked. */ + @Deprecated public static void freeGlCaches() { freeCaches(); } @@ -198,6 +201,7 @@ public class Canvas { * * @deprecated This method is not supported and should not be invoked. */ + @Deprecated public void setViewport(int width, int height) { if (mGL != null) { nativeSetViewport(mNativeCanvas, width, height); @@ -415,8 +419,8 @@ public class Canvas { * * @param sx The amount to scale in X * @param sy The amount to scale in Y - * @param px The x-coord for the pivot point (unchanged by the rotation) - * @param py The y-coord for the pivot point (unchanged by the rotation) + * @param px The x-coord for the pivot point (unchanged by the scale) + * @param py The y-coord for the pivot point (unchanged by the scale) */ public final void scale(float sx, float sy, float px, float py) { translate(px, py); @@ -1585,6 +1589,7 @@ public class Canvas { restore(); } + @Override protected void finalize() throws Throwable { super.finalize(); // If the constructor threw an exception before setting mNativeCanvas, the native finalizer diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index 98ffb8b4318ba..78302244e1c1b 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -75,6 +75,7 @@ public final class Rect implements Parcelable { bottom = r.bottom; } + @Override public boolean equals(Object obj) { Rect r = (Rect) obj; if (r != null) { @@ -84,6 +85,7 @@ public final class Rect implements Parcelable { return false; } + @Override public String toString() { StringBuilder sb = new StringBuilder(32); sb.append("Rect("); sb.append(left); sb.append(", "); @@ -351,7 +353,7 @@ public final class Rect implements Parcelable { * rectangle, return true and set this rectangle to that intersection, * otherwise return false and do not change this rectangle. No check is * performed to see if either rectangle is empty. Note: To just test for - * intersection, use intersects() + * intersection, use {@link #intersects(Rect, Rect)}. * * @param left The left side of the rectangle being intersected with this * rectangle @@ -445,7 +447,7 @@ public final class Rect implements Parcelable { /** * Returns true iff the two specified rectangles intersect. In no event are * either of the rectangles modified. To record the intersection, - * use intersect() or setIntersect(). + * use {@link #intersect(Rect)} or {@link #setIntersect(Rect, Rect)}. * * @param a The first rectangle being tested for intersection * @param b The second rectangle being tested for intersection