Fix bug 3047653 - Text select handles stick around when they shouldn't
Text select handles will now fade out on their own after a few seconds since many apps expect a selection to be persistent while a text field stays focused in touch mode. The user may tap within the selection to bring the anchors back. Text select handles will also disappear upon leaving touch mode. Fix a bug that impaired cut/paste from the context menu. Change-Id: I8f431e2d261aec02581150125d11324a3ee11656
This commit is contained in:
@@ -3751,18 +3751,34 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
showError();
|
||||
mShowErrorAfterAttach = false;
|
||||
}
|
||||
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
if (observer != null) {
|
||||
if (mInsertionPointCursorController != null) {
|
||||
observer.addOnTouchModeChangeListener(mInsertionPointCursorController);
|
||||
}
|
||||
if (mSelectionModifierCursorController != null) {
|
||||
observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
if (mPreDrawState != PREDRAW_NOT_REGISTERED) {
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
if (observer != null) {
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
if (observer != null) {
|
||||
if (mPreDrawState != PREDRAW_NOT_REGISTERED) {
|
||||
observer.removeOnPreDrawListener(this);
|
||||
mPreDrawState = PREDRAW_NOT_REGISTERED;
|
||||
}
|
||||
if (mInsertionPointCursorController != null) {
|
||||
observer.removeOnTouchModeChangeListener(mInsertionPointCursorController);
|
||||
}
|
||||
if (mSelectionModifierCursorController != null) {
|
||||
observer.removeOnTouchModeChangeListener(mSelectionModifierCursorController);
|
||||
}
|
||||
}
|
||||
|
||||
if (mError != null) {
|
||||
@@ -6621,7 +6637,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
if (mInputContentType != null) {
|
||||
mInputContentType.enterDown = false;
|
||||
}
|
||||
hideControllers();
|
||||
hideInsertionPointCursorController();
|
||||
if (mSelectionModifierCursorController != null) {
|
||||
mSelectionModifierCursorController.hide();
|
||||
}
|
||||
}
|
||||
|
||||
startStopMarquee(hasWindowFocus);
|
||||
@@ -6631,7 +6650,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
protected void onVisibilityChanged(View changedView, int visibility) {
|
||||
super.onVisibilityChanged(changedView, visibility);
|
||||
if (visibility != VISIBLE) {
|
||||
hideControllers();
|
||||
hideInsertionPointCursorController();
|
||||
if (mSelectionModifierCursorController != null) {
|
||||
mSelectionModifierCursorController.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6669,8 +6691,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
if (start >= prevStart && start < prevEnd) {
|
||||
// Restore previous selection
|
||||
Selection.setSelection((Spannable)mText, prevStart, prevEnd);
|
||||
// Tapping inside the selection displays the cut/copy/paste context menu.
|
||||
showContextMenu();
|
||||
|
||||
if (mSelectionModifierCursorController != null &&
|
||||
!mSelectionModifierCursorController.isShowing()) {
|
||||
// If the anchors aren't showing, revive them.
|
||||
mSelectionModifierCursorController.show();
|
||||
} else {
|
||||
// Tapping inside the selection displays the cut/copy/paste context menu
|
||||
// as long as the anchors are already showing.
|
||||
showContextMenu();
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// Tapping outside stops selection mode, if any
|
||||
@@ -6680,6 +6710,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
mInsertionPointCursorController.show();
|
||||
}
|
||||
}
|
||||
} else if (hasSelection() && mSelectionModifierCursorController != null) {
|
||||
mSelectionModifierCursorController.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7627,7 +7659,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
* It is not used outside of {@link TextView}.
|
||||
* @hide
|
||||
*/
|
||||
private interface CursorController {
|
||||
private interface CursorController extends ViewTreeObserver.OnTouchModeChangeListener {
|
||||
/**
|
||||
* Makes the cursor controller visible on screen. Will be drawn by {@link #draw(Canvas)}.
|
||||
* See also {@link #hide()}.
|
||||
@@ -7882,6 +7914,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onTouchModeChanged(boolean isInTouchMode) {
|
||||
if (!isInTouchMode) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SelectionModifierCursorController implements CursorController {
|
||||
@@ -7892,6 +7930,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
// Whether selection anchors are active
|
||||
private boolean mIsShowing;
|
||||
|
||||
private static final int DELAY_BEFORE_FADE_OUT = 4100;
|
||||
|
||||
private final Runnable mHider = new Runnable() {
|
||||
public void run() {
|
||||
hide();
|
||||
}
|
||||
};
|
||||
|
||||
SelectionModifierCursorController() {
|
||||
Resources res = mContext.getResources();
|
||||
mStartHandle = new HandleView(this, res.getDrawable(mTextSelectHandleLeftRes));
|
||||
@@ -7904,12 +7950,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
mStartHandle.show();
|
||||
mEndHandle.show();
|
||||
hideInsertionPointCursorController();
|
||||
hideDelayed(DELAY_BEFORE_FADE_OUT);
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
mStartHandle.hide();
|
||||
mEndHandle.hide();
|
||||
mIsShowing = false;
|
||||
removeCallbacks(mHider);
|
||||
}
|
||||
|
||||
private void hideDelayed(int delay) {
|
||||
removeCallbacks(mHider);
|
||||
postDelayed(mHider, delay);
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
@@ -7975,6 +8028,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
mLayout.getLineForOffset(selectionEnd);
|
||||
mStartHandle.positionAtCursor(selectionStart, oneLineSelection);
|
||||
mEndHandle.positionAtCursor(selectionEnd, true);
|
||||
hideDelayed(DELAY_BEFORE_FADE_OUT);
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
@@ -8031,6 +8085,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
public boolean isSelectionStartDragged() {
|
||||
return mStartHandle.isDragging();
|
||||
}
|
||||
|
||||
public void onTouchModeChanged(boolean isInTouchMode) {
|
||||
if (!isInTouchMode) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideInsertionPointCursorController() {
|
||||
|
||||
Reference in New Issue
Block a user