Loading api/current.xml +125 −0 Original line number Diff line number Diff line Loading @@ -166353,6 +166353,29 @@ <parameter name="event" type="android.view.MotionEvent"> </parameter> </method> <method name="setCursorController" return="void" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="cursorController" type="android.widget.TextView.CursorController"> </parameter> </method> <field name="mCursorController" type="android.widget.TextView.CursorController" transient="false" volatile="false" static="false" final="false" deprecated="not deprecated" visibility="protected" > </field> </class> <class name="BaseKeyListener" extends="android.text.method.MetaKeyKeyListener" Loading Loading @@ -222863,6 +222886,108 @@ > </method> </class> <interface name="TextView.CursorController" abstract="true" static="true" final="false" deprecated="not deprecated" visibility="public" > <method name="draw" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="canvas" type="android.graphics.Canvas"> </parameter> </method> <method name="getOffsetX" return="float" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="getOffsetY" return="float" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="hide" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="onTouchEvent" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="event" type="android.view.MotionEvent"> </parameter> </method> <method name="show" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="updatePosition" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="offset" type="int"> </parameter> </method> <field name="FADE_OUT_DURATION" type="int" transient="false" volatile="false" value="400" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> </interface> <interface name="TextView.OnEditorActionListener" abstract="true" static="true" core/java/android/text/Selection.java +2 −2 Original line number Diff line number Diff line Loading @@ -417,8 +417,8 @@ public class Selection { } } private static final class START implements NoCopySpan { }; private static final class END implements NoCopySpan { }; private static final class START implements NoCopySpan { } private static final class END implements NoCopySpan { } /* * Public constants Loading core/java/android/text/method/ArrowKeyMovementMethod.java +86 −264 Original line number Diff line number Diff line Loading @@ -16,30 +16,38 @@ package android.text.method; import android.util.Log; import android.text.Layout; import android.text.Selection; import android.text.Spannable; import android.view.KeyEvent; import android.graphics.Rect; import android.text.*; import android.widget.TextView; import android.view.View; import android.view.ViewConfiguration; import android.view.MotionEvent; import android.view.View; import android.widget.TextView; import android.widget.TextView.CursorController; // XXX this doesn't extend MetaKeyKeyListener because the signatures // don't match. Need to figure that out. Meanwhile the meta keys // won't work in fields that don't take input. public class ArrowKeyMovementMethod implements MovementMethod { public class ArrowKeyMovementMethod implements MovementMethod { /** * An optional controller for the cursor. * Use {@link #setCursorController(CursorController)} to set this field. */ protected CursorController mCursorController; private boolean isCap(Spannable buffer) { return ((MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0)); } private boolean isAlt(Spannable buffer) { return MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; } private boolean up(TextView widget, Spannable buffer) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean alt = MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; boolean cap = isCap(buffer); boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { Loading @@ -60,12 +68,8 @@ implements MovementMethod } private boolean down(TextView widget, Spannable buffer) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean alt = MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; boolean cap = isCap(buffer); boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { Loading @@ -86,12 +90,8 @@ implements MovementMethod } private boolean left(TextView widget, Spannable buffer) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean alt = MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; boolean cap = isCap(buffer); boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { Loading @@ -110,12 +110,8 @@ implements MovementMethod } private boolean right(TextView widget, Spannable buffer) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean alt = MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; boolean cap = isCap(buffer); boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { Loading @@ -133,35 +129,6 @@ implements MovementMethod } } private int getOffset(int x, int y, TextView widget){ // Converts the absolute X,Y coordinates to the character offset for the // character whose position is closest to the specified // horizontal position. x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); // Clamp the position to inside of the view. if (x < 0) { x = 0; } else if (x >= (widget.getWidth()-widget.getTotalPaddingRight())) { x = widget.getWidth()-widget.getTotalPaddingRight() - 1; } if (y < 0) { y = 0; } else if (y >= (widget.getHeight()-widget.getTotalPaddingBottom())) { y = widget.getHeight()-widget.getTotalPaddingBottom() - 1; } x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int offset = layout.getOffsetForHorizontal(line, x); return offset; } public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) { if (executeDown(widget, buffer, keyCode)) { MetaKeyKeyListener.adjustMetaAfterKeypress(buffer); Loading Loading @@ -193,12 +160,11 @@ implements MovementMethod break; case KeyEvent.KEYCODE_DPAD_CENTER: if (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) { if (widget.showContextMenu()) { if ((MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) && (widget.showContextMenu())) { handled = true; } } } if (handled) { MetaKeyKeyListener.adjustMetaAfterKeypress(buffer); Loading @@ -214,8 +180,7 @@ implements MovementMethod public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) { int code = event.getKeyCode(); if (code != KeyEvent.KEYCODE_UNKNOWN && event.getAction() == KeyEvent.ACTION_MULTIPLE) { if (code != KeyEvent.KEYCODE_UNKNOWN && event.getAction() == KeyEvent.ACTION_MULTIPLE) { int repeat = event.getRepeatCount(); boolean handled = false; while ((--repeat) > 0) { Loading @@ -226,13 +191,22 @@ implements MovementMethod return false; } public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event) { public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event) { if (mCursorController != null) { mCursorController.hide(); } return false; } public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { if (mCursorController != null) { return onTouchEventCursor(widget, buffer, event); } else { return onTouchEventStandard(widget, buffer, event); } } private boolean onTouchEventStandard(TextView widget, Spannable buffer, MotionEvent event) { int initialScrollX = -1, initialScrollY = -1; if (event.getAction() == MotionEvent.ACTION_UP) { initialScrollX = Touch.getInitialScrollX(widget, buffer); Loading @@ -243,53 +217,20 @@ implements MovementMethod if (widget.isFocused() && !widget.didTouchFocusSelect()) { if (event.getAction() == MotionEvent.ACTION_DOWN) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); int x = (int) event.getX(); int y = (int) event.getY(); int offset = getOffset(x, y, widget); boolean cap = isCap(buffer); if (cap) { buffer.setSpan(LAST_TAP_DOWN, offset, offset, Spannable.SPAN_POINT_POINT); int offset = widget.getOffset((int) event.getX(), (int) event.getY()); buffer.setSpan(LAST_TAP_DOWN, offset, offset, Spannable.SPAN_POINT_POINT); // Disallow intercepting of the touch events, so that // users can scroll and select at the same time. // without this, users would get booted out of select // mode once the view detected it needed to scroll. widget.getParent().requestDisallowInterceptTouchEvent(true); } else { OnePointFiveTapState[] tap = buffer.getSpans(0, buffer.length(), OnePointFiveTapState.class); if (tap.length > 0) { if (event.getEventTime() - tap[0].mWhen <= ViewConfiguration.getDoubleTapTimeout() && sameWord(buffer, offset, Selection.getSelectionEnd(buffer))) { tap[0].active = true; MetaKeyKeyListener.startSelecting(widget, buffer); widget.getParent().requestDisallowInterceptTouchEvent(true); buffer.setSpan(LAST_TAP_DOWN, offset, offset, Spannable.SPAN_POINT_POINT); } tap[0].mWhen = event.getEventTime(); } else { OnePointFiveTapState newtap = new OnePointFiveTapState(); newtap.mWhen = event.getEventTime(); newtap.active = false; buffer.setSpan(newtap, 0, buffer.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean cap = isCap(buffer); if (cap && handled) { // Before selecting, make sure we've moved out of the "slop". Loading @@ -303,39 +244,9 @@ implements MovementMethod // Update selection as we're moving the selection area. // Get the current touch position int x = (int) event.getX(); int y = (int) event.getY(); int offset = getOffset(x, y, widget); final OnePointFiveTapState[] tap = buffer.getSpans(0, buffer.length(), OnePointFiveTapState.class); if (tap.length > 0 && tap[0].active) { // Get the last down touch position (the position at which the // user started the selection) int lastDownOffset = buffer.getSpanStart(LAST_TAP_DOWN); // Compute the selection boundaries int spanstart; int spanend; if (offset >= lastDownOffset) { // Expand from word start of the original tap to new word // end, since we are selecting "forwards" spanstart = findWordStart(buffer, lastDownOffset); spanend = findWordEnd(buffer, offset); } else { // Expand to from new word start to word end of the original // tap since we are selecting "backwards". // The spanend will always need to be associated with the touch // up position, so that refining the selection with the // trackball will work as expected. spanstart = findWordEnd(buffer, lastDownOffset); spanend = findWordStart(buffer, offset); } Selection.setSelection(buffer, spanstart, spanend); } else { int offset = widget.getOffset((int) event.getX(), (int) event.getY()); Selection.extendSelection(buffer, offset); } return true; } } else if (event.getAction() == MotionEvent.ACTION_UP) { Loading @@ -349,65 +260,12 @@ implements MovementMethod return true; } int x = (int) event.getX(); int y = (int) event.getY(); int off = getOffset(x, y, widget); // XXX should do the same adjust for x as we do for the line. OnePointFiveTapState[] onepointfivetap = buffer.getSpans(0, buffer.length(), OnePointFiveTapState.class); if (onepointfivetap.length > 0 && onepointfivetap[0].active && Selection.getSelectionStart(buffer) == Selection.getSelectionEnd(buffer)) { // If we've set select mode, because there was a onepointfivetap, // but there was no ensuing swipe gesture, undo the select mode // and remove reference to the last onepointfivetap. MetaKeyKeyListener.stopSelecting(widget, buffer); for (int i=0; i < onepointfivetap.length; i++) { buffer.removeSpan(onepointfivetap[i]); } buffer.removeSpan(LAST_TAP_DOWN); } boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); DoubleTapState[] tap = buffer.getSpans(0, buffer.length(), DoubleTapState.class); boolean doubletap = false; if (tap.length > 0) { if (event.getEventTime() - tap[0].mWhen <= ViewConfiguration.getDoubleTapTimeout() && sameWord(buffer, off, Selection.getSelectionEnd(buffer))) { doubletap = true; } tap[0].mWhen = event.getEventTime(); } else { DoubleTapState newtap = new DoubleTapState(); newtap.mWhen = event.getEventTime(); buffer.setSpan(newtap, 0, buffer.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } if (cap) { int offset = widget.getOffset((int) event.getX(), (int) event.getY()); if (isCap(buffer)) { buffer.removeSpan(LAST_TAP_DOWN); if (onepointfivetap.length > 0 && onepointfivetap[0].active) { // If we selecting something with the onepointfivetap-and // swipe gesture, stop it on finger up. MetaKeyKeyListener.stopSelecting(widget, buffer); } else { Selection.extendSelection(buffer, off); } } else if (doubletap) { Selection.setSelection(buffer, findWordStart(buffer, off), findWordEnd(buffer, off)); Selection.extendSelection(buffer, offset); } else { Selection.setSelection(buffer, off); Selection.setSelection(buffer, offset); } MetaKeyKeyListener.adjustMetaAfterKeypress(buffer); Loading @@ -420,73 +278,36 @@ implements MovementMethod return handled; } private static class DoubleTapState implements NoCopySpan { long mWhen; } /* We check for a onepointfive tap. This is similar to * doubletap gesture (where a finger goes down, up, down, up, in a short * time period), except in the onepointfive tap, a users finger only needs * to go down, up, down in a short time period. We detect this type of tap * to implement the onepointfivetap-and-swipe selection gesture. * This gesture allows users to select a segment of text without going * through the "select text" option in the context menu. */ private static class OnePointFiveTapState implements NoCopySpan { long mWhen; boolean active; } private static boolean sameWord(CharSequence text, int one, int two) { int start = findWordStart(text, one); int end = findWordEnd(text, one); if (end == start) { return false; } return start == findWordStart(text, two) && end == findWordEnd(text, two); } // TODO: Unify with TextView.getWordForDictionary() private static int findWordStart(CharSequence text, int start) { for (; start > 0; start--) { char c = text.charAt(start - 1); int type = Character.getType(c); private boolean onTouchEventCursor(TextView widget, Spannable buffer, MotionEvent event) { if (widget.isFocused() && !widget.didTouchFocusSelect()) { switch (event.getActionMasked()) { case MotionEvent.ACTION_MOVE: widget.cancelLongPress(); if (c != '\'' && type != Character.UPPERCASE_LETTER && type != Character.LOWERCASE_LETTER && type != Character.TITLECASE_LETTER && type != Character.MODIFIER_LETTER && type != Character.DECIMAL_DIGIT_NUMBER) { break; } } // Offset the current touch position (from controller to cursor) final float x = event.getX() + mCursorController.getOffsetX(); final float y = event.getY() + mCursorController.getOffsetY(); int offset = widget.getOffset((int) x, (int) y); mCursorController.updatePosition(offset); return true; return start; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mCursorController = null; return true; } // TODO: Unify with TextView.getWordForDictionary() private static int findWordEnd(CharSequence text, int end) { int len = text.length(); for (; end < len; end++) { char c = text.charAt(end); int type = Character.getType(c); if (c != '\'' && type != Character.UPPERCASE_LETTER && type != Character.LOWERCASE_LETTER && type != Character.TITLECASE_LETTER && type != Character.MODIFIER_LETTER && type != Character.DECIMAL_DIGIT_NUMBER) { break; } return false; } return end; /** * Defines the cursor controller. * * When set, this object can be used to handle events, that can be translated in cursor updates. * @param cursorController A cursor controller implementation */ public void setCursorController(CursorController cursorController) { mCursorController = cursorController; } public boolean canSelectArbitrarily() { Loading Loading @@ -525,8 +346,9 @@ implements MovementMethod } public static MovementMethod getInstance() { if (sInstance == null) if (sInstance == null) { sInstance = new ArrowKeyMovementMethod(); } return sInstance; } Loading core/java/android/text/method/Touch.java +3 −4 Original line number Diff line number Diff line Loading @@ -17,14 +17,13 @@ package android.text.method; import android.text.Layout; import android.text.NoCopySpan; import android.text.Layout.Alignment; import android.text.NoCopySpan; import android.text.Spannable; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.widget.TextView; import android.view.KeyEvent; public class Touch { private Touch() { } Loading Loading @@ -99,7 +98,7 @@ public class Touch { MotionEvent event) { DragState[] ds; switch (event.getAction()) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: ds = buffer.getSpans(0, buffer.length(), DragState.class); Loading core/java/android/view/AbsSavedState.java +2 −2 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ public abstract class AbsSavedState implements Parcelable { */ protected AbsSavedState(Parcel source) { // FIXME need class loader Parcelable superState = (Parcelable) source.readParcelable(null); Parcelable superState = source.readParcelable(null); mSuperState = superState != null ? superState : EMPTY_STATE; } Loading @@ -75,7 +75,7 @@ public abstract class AbsSavedState implements Parcelable { = new Parcelable.Creator<AbsSavedState>() { public AbsSavedState createFromParcel(Parcel in) { Parcelable superState = (Parcelable) in.readParcelable(null); Parcelable superState = in.readParcelable(null); if (superState != null) { throw new IllegalStateException("superState must be null"); } Loading Loading
api/current.xml +125 −0 Original line number Diff line number Diff line Loading @@ -166353,6 +166353,29 @@ <parameter name="event" type="android.view.MotionEvent"> </parameter> </method> <method name="setCursorController" return="void" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="cursorController" type="android.widget.TextView.CursorController"> </parameter> </method> <field name="mCursorController" type="android.widget.TextView.CursorController" transient="false" volatile="false" static="false" final="false" deprecated="not deprecated" visibility="protected" > </field> </class> <class name="BaseKeyListener" extends="android.text.method.MetaKeyKeyListener" Loading Loading @@ -222863,6 +222886,108 @@ > </method> </class> <interface name="TextView.CursorController" abstract="true" static="true" final="false" deprecated="not deprecated" visibility="public" > <method name="draw" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="canvas" type="android.graphics.Canvas"> </parameter> </method> <method name="getOffsetX" return="float" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="getOffsetY" return="float" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="hide" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="onTouchEvent" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="event" type="android.view.MotionEvent"> </parameter> </method> <method name="show" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="updatePosition" return="void" abstract="true" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="offset" type="int"> </parameter> </method> <field name="FADE_OUT_DURATION" type="int" transient="false" volatile="false" value="400" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> </interface> <interface name="TextView.OnEditorActionListener" abstract="true" static="true"
core/java/android/text/Selection.java +2 −2 Original line number Diff line number Diff line Loading @@ -417,8 +417,8 @@ public class Selection { } } private static final class START implements NoCopySpan { }; private static final class END implements NoCopySpan { }; private static final class START implements NoCopySpan { } private static final class END implements NoCopySpan { } /* * Public constants Loading
core/java/android/text/method/ArrowKeyMovementMethod.java +86 −264 Original line number Diff line number Diff line Loading @@ -16,30 +16,38 @@ package android.text.method; import android.util.Log; import android.text.Layout; import android.text.Selection; import android.text.Spannable; import android.view.KeyEvent; import android.graphics.Rect; import android.text.*; import android.widget.TextView; import android.view.View; import android.view.ViewConfiguration; import android.view.MotionEvent; import android.view.View; import android.widget.TextView; import android.widget.TextView.CursorController; // XXX this doesn't extend MetaKeyKeyListener because the signatures // don't match. Need to figure that out. Meanwhile the meta keys // won't work in fields that don't take input. public class ArrowKeyMovementMethod implements MovementMethod { public class ArrowKeyMovementMethod implements MovementMethod { /** * An optional controller for the cursor. * Use {@link #setCursorController(CursorController)} to set this field. */ protected CursorController mCursorController; private boolean isCap(Spannable buffer) { return ((MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0)); } private boolean isAlt(Spannable buffer) { return MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; } private boolean up(TextView widget, Spannable buffer) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean alt = MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; boolean cap = isCap(buffer); boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { Loading @@ -60,12 +68,8 @@ implements MovementMethod } private boolean down(TextView widget, Spannable buffer) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean alt = MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; boolean cap = isCap(buffer); boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { Loading @@ -86,12 +90,8 @@ implements MovementMethod } private boolean left(TextView widget, Spannable buffer) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean alt = MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; boolean cap = isCap(buffer); boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { Loading @@ -110,12 +110,8 @@ implements MovementMethod } private boolean right(TextView widget, Spannable buffer) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean alt = MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; boolean cap = isCap(buffer); boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { Loading @@ -133,35 +129,6 @@ implements MovementMethod } } private int getOffset(int x, int y, TextView widget){ // Converts the absolute X,Y coordinates to the character offset for the // character whose position is closest to the specified // horizontal position. x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); // Clamp the position to inside of the view. if (x < 0) { x = 0; } else if (x >= (widget.getWidth()-widget.getTotalPaddingRight())) { x = widget.getWidth()-widget.getTotalPaddingRight() - 1; } if (y < 0) { y = 0; } else if (y >= (widget.getHeight()-widget.getTotalPaddingBottom())) { y = widget.getHeight()-widget.getTotalPaddingBottom() - 1; } x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int offset = layout.getOffsetForHorizontal(line, x); return offset; } public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) { if (executeDown(widget, buffer, keyCode)) { MetaKeyKeyListener.adjustMetaAfterKeypress(buffer); Loading Loading @@ -193,12 +160,11 @@ implements MovementMethod break; case KeyEvent.KEYCODE_DPAD_CENTER: if (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) { if (widget.showContextMenu()) { if ((MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) && (widget.showContextMenu())) { handled = true; } } } if (handled) { MetaKeyKeyListener.adjustMetaAfterKeypress(buffer); Loading @@ -214,8 +180,7 @@ implements MovementMethod public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) { int code = event.getKeyCode(); if (code != KeyEvent.KEYCODE_UNKNOWN && event.getAction() == KeyEvent.ACTION_MULTIPLE) { if (code != KeyEvent.KEYCODE_UNKNOWN && event.getAction() == KeyEvent.ACTION_MULTIPLE) { int repeat = event.getRepeatCount(); boolean handled = false; while ((--repeat) > 0) { Loading @@ -226,13 +191,22 @@ implements MovementMethod return false; } public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event) { public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event) { if (mCursorController != null) { mCursorController.hide(); } return false; } public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { if (mCursorController != null) { return onTouchEventCursor(widget, buffer, event); } else { return onTouchEventStandard(widget, buffer, event); } } private boolean onTouchEventStandard(TextView widget, Spannable buffer, MotionEvent event) { int initialScrollX = -1, initialScrollY = -1; if (event.getAction() == MotionEvent.ACTION_UP) { initialScrollX = Touch.getInitialScrollX(widget, buffer); Loading @@ -243,53 +217,20 @@ implements MovementMethod if (widget.isFocused() && !widget.didTouchFocusSelect()) { if (event.getAction() == MotionEvent.ACTION_DOWN) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); int x = (int) event.getX(); int y = (int) event.getY(); int offset = getOffset(x, y, widget); boolean cap = isCap(buffer); if (cap) { buffer.setSpan(LAST_TAP_DOWN, offset, offset, Spannable.SPAN_POINT_POINT); int offset = widget.getOffset((int) event.getX(), (int) event.getY()); buffer.setSpan(LAST_TAP_DOWN, offset, offset, Spannable.SPAN_POINT_POINT); // Disallow intercepting of the touch events, so that // users can scroll and select at the same time. // without this, users would get booted out of select // mode once the view detected it needed to scroll. widget.getParent().requestDisallowInterceptTouchEvent(true); } else { OnePointFiveTapState[] tap = buffer.getSpans(0, buffer.length(), OnePointFiveTapState.class); if (tap.length > 0) { if (event.getEventTime() - tap[0].mWhen <= ViewConfiguration.getDoubleTapTimeout() && sameWord(buffer, offset, Selection.getSelectionEnd(buffer))) { tap[0].active = true; MetaKeyKeyListener.startSelecting(widget, buffer); widget.getParent().requestDisallowInterceptTouchEvent(true); buffer.setSpan(LAST_TAP_DOWN, offset, offset, Spannable.SPAN_POINT_POINT); } tap[0].mWhen = event.getEventTime(); } else { OnePointFiveTapState newtap = new OnePointFiveTapState(); newtap.mWhen = event.getEventTime(); newtap.active = false; buffer.setSpan(newtap, 0, buffer.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); boolean cap = isCap(buffer); if (cap && handled) { // Before selecting, make sure we've moved out of the "slop". Loading @@ -303,39 +244,9 @@ implements MovementMethod // Update selection as we're moving the selection area. // Get the current touch position int x = (int) event.getX(); int y = (int) event.getY(); int offset = getOffset(x, y, widget); final OnePointFiveTapState[] tap = buffer.getSpans(0, buffer.length(), OnePointFiveTapState.class); if (tap.length > 0 && tap[0].active) { // Get the last down touch position (the position at which the // user started the selection) int lastDownOffset = buffer.getSpanStart(LAST_TAP_DOWN); // Compute the selection boundaries int spanstart; int spanend; if (offset >= lastDownOffset) { // Expand from word start of the original tap to new word // end, since we are selecting "forwards" spanstart = findWordStart(buffer, lastDownOffset); spanend = findWordEnd(buffer, offset); } else { // Expand to from new word start to word end of the original // tap since we are selecting "backwards". // The spanend will always need to be associated with the touch // up position, so that refining the selection with the // trackball will work as expected. spanstart = findWordEnd(buffer, lastDownOffset); spanend = findWordStart(buffer, offset); } Selection.setSelection(buffer, spanstart, spanend); } else { int offset = widget.getOffset((int) event.getX(), (int) event.getY()); Selection.extendSelection(buffer, offset); } return true; } } else if (event.getAction() == MotionEvent.ACTION_UP) { Loading @@ -349,65 +260,12 @@ implements MovementMethod return true; } int x = (int) event.getX(); int y = (int) event.getY(); int off = getOffset(x, y, widget); // XXX should do the same adjust for x as we do for the line. OnePointFiveTapState[] onepointfivetap = buffer.getSpans(0, buffer.length(), OnePointFiveTapState.class); if (onepointfivetap.length > 0 && onepointfivetap[0].active && Selection.getSelectionStart(buffer) == Selection.getSelectionEnd(buffer)) { // If we've set select mode, because there was a onepointfivetap, // but there was no ensuing swipe gesture, undo the select mode // and remove reference to the last onepointfivetap. MetaKeyKeyListener.stopSelecting(widget, buffer); for (int i=0; i < onepointfivetap.length; i++) { buffer.removeSpan(onepointfivetap[i]); } buffer.removeSpan(LAST_TAP_DOWN); } boolean cap = (MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0); DoubleTapState[] tap = buffer.getSpans(0, buffer.length(), DoubleTapState.class); boolean doubletap = false; if (tap.length > 0) { if (event.getEventTime() - tap[0].mWhen <= ViewConfiguration.getDoubleTapTimeout() && sameWord(buffer, off, Selection.getSelectionEnd(buffer))) { doubletap = true; } tap[0].mWhen = event.getEventTime(); } else { DoubleTapState newtap = new DoubleTapState(); newtap.mWhen = event.getEventTime(); buffer.setSpan(newtap, 0, buffer.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } if (cap) { int offset = widget.getOffset((int) event.getX(), (int) event.getY()); if (isCap(buffer)) { buffer.removeSpan(LAST_TAP_DOWN); if (onepointfivetap.length > 0 && onepointfivetap[0].active) { // If we selecting something with the onepointfivetap-and // swipe gesture, stop it on finger up. MetaKeyKeyListener.stopSelecting(widget, buffer); } else { Selection.extendSelection(buffer, off); } } else if (doubletap) { Selection.setSelection(buffer, findWordStart(buffer, off), findWordEnd(buffer, off)); Selection.extendSelection(buffer, offset); } else { Selection.setSelection(buffer, off); Selection.setSelection(buffer, offset); } MetaKeyKeyListener.adjustMetaAfterKeypress(buffer); Loading @@ -420,73 +278,36 @@ implements MovementMethod return handled; } private static class DoubleTapState implements NoCopySpan { long mWhen; } /* We check for a onepointfive tap. This is similar to * doubletap gesture (where a finger goes down, up, down, up, in a short * time period), except in the onepointfive tap, a users finger only needs * to go down, up, down in a short time period. We detect this type of tap * to implement the onepointfivetap-and-swipe selection gesture. * This gesture allows users to select a segment of text without going * through the "select text" option in the context menu. */ private static class OnePointFiveTapState implements NoCopySpan { long mWhen; boolean active; } private static boolean sameWord(CharSequence text, int one, int two) { int start = findWordStart(text, one); int end = findWordEnd(text, one); if (end == start) { return false; } return start == findWordStart(text, two) && end == findWordEnd(text, two); } // TODO: Unify with TextView.getWordForDictionary() private static int findWordStart(CharSequence text, int start) { for (; start > 0; start--) { char c = text.charAt(start - 1); int type = Character.getType(c); private boolean onTouchEventCursor(TextView widget, Spannable buffer, MotionEvent event) { if (widget.isFocused() && !widget.didTouchFocusSelect()) { switch (event.getActionMasked()) { case MotionEvent.ACTION_MOVE: widget.cancelLongPress(); if (c != '\'' && type != Character.UPPERCASE_LETTER && type != Character.LOWERCASE_LETTER && type != Character.TITLECASE_LETTER && type != Character.MODIFIER_LETTER && type != Character.DECIMAL_DIGIT_NUMBER) { break; } } // Offset the current touch position (from controller to cursor) final float x = event.getX() + mCursorController.getOffsetX(); final float y = event.getY() + mCursorController.getOffsetY(); int offset = widget.getOffset((int) x, (int) y); mCursorController.updatePosition(offset); return true; return start; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mCursorController = null; return true; } // TODO: Unify with TextView.getWordForDictionary() private static int findWordEnd(CharSequence text, int end) { int len = text.length(); for (; end < len; end++) { char c = text.charAt(end); int type = Character.getType(c); if (c != '\'' && type != Character.UPPERCASE_LETTER && type != Character.LOWERCASE_LETTER && type != Character.TITLECASE_LETTER && type != Character.MODIFIER_LETTER && type != Character.DECIMAL_DIGIT_NUMBER) { break; } return false; } return end; /** * Defines the cursor controller. * * When set, this object can be used to handle events, that can be translated in cursor updates. * @param cursorController A cursor controller implementation */ public void setCursorController(CursorController cursorController) { mCursorController = cursorController; } public boolean canSelectArbitrarily() { Loading Loading @@ -525,8 +346,9 @@ implements MovementMethod } public static MovementMethod getInstance() { if (sInstance == null) if (sInstance == null) { sInstance = new ArrowKeyMovementMethod(); } return sInstance; } Loading
core/java/android/text/method/Touch.java +3 −4 Original line number Diff line number Diff line Loading @@ -17,14 +17,13 @@ package android.text.method; import android.text.Layout; import android.text.NoCopySpan; import android.text.Layout.Alignment; import android.text.NoCopySpan; import android.text.Spannable; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.widget.TextView; import android.view.KeyEvent; public class Touch { private Touch() { } Loading Loading @@ -99,7 +98,7 @@ public class Touch { MotionEvent event) { DragState[] ds; switch (event.getAction()) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: ds = buffer.getSpans(0, buffer.length(), DragState.class); Loading
core/java/android/view/AbsSavedState.java +2 −2 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ public abstract class AbsSavedState implements Parcelable { */ protected AbsSavedState(Parcel source) { // FIXME need class loader Parcelable superState = (Parcelable) source.readParcelable(null); Parcelable superState = source.readParcelable(null); mSuperState = superState != null ? superState : EMPTY_STATE; } Loading @@ -75,7 +75,7 @@ public abstract class AbsSavedState implements Parcelable { = new Parcelable.Creator<AbsSavedState>() { public AbsSavedState createFromParcel(Parcel in) { Parcelable superState = (Parcelable) in.readParcelable(null); Parcelable superState = in.readParcelable(null); if (superState != null) { throw new IllegalStateException("superState must be null"); } Loading