Merge "Text selection handles correctly scroll"
This commit is contained in:
committed by
Android (Google) Code Review
commit
2bbe178fea
@@ -378,8 +378,7 @@ public class PopupWindow {
|
||||
* <p>Change the popup's content. The content is represented by an instance
|
||||
* of {@link android.view.View}.</p>
|
||||
*
|
||||
* <p>This method has no effect if called when the popup is showing. To
|
||||
* apply it while a popup is showing, call </p>
|
||||
* <p>This method has no effect if called when the popup is showing.</p>
|
||||
*
|
||||
* @param contentView the new content for the popup
|
||||
*
|
||||
@@ -1040,7 +1039,7 @@ public class PopupWindow {
|
||||
*
|
||||
* @return true if the popup is translated upwards to fit on screen
|
||||
*/
|
||||
private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
|
||||
boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
|
||||
int xoff, int yoff) {
|
||||
|
||||
anchor.getLocationInWindow(mDrawingLocation);
|
||||
@@ -1374,6 +1373,7 @@ public class PopupWindow {
|
||||
* height can be set to -1 to update location only. Calling this function
|
||||
* also updates the window with the current popup state as
|
||||
* described for {@link #update()}.</p>
|
||||
*
|
||||
* <p>If the view later scrolls to move <code>anchor</code> to a different
|
||||
* location, the popup will be moved correspondingly.</p>
|
||||
*
|
||||
@@ -1395,9 +1395,13 @@ public class PopupWindow {
|
||||
}
|
||||
|
||||
WeakReference<View> oldAnchor = mAnchor;
|
||||
if (oldAnchor == null || oldAnchor.get() != anchor ||
|
||||
(updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff))) {
|
||||
final boolean needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);
|
||||
if (oldAnchor == null || oldAnchor.get() != anchor || (needsUpdate && !mIsDropdown)) {
|
||||
registerForScrollChanged(anchor, xoff, yoff);
|
||||
} else if (needsUpdate) {
|
||||
// No need to register again if this is a DropDown, showAsDropDown already did.
|
||||
mAnchorXoff = xoff;
|
||||
mAnchorYoff = yoff;
|
||||
}
|
||||
|
||||
WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams();
|
||||
|
||||
@@ -3873,9 +3873,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
|
||||
private void registerForPreDraw() {
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
if (observer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPreDrawState == PREDRAW_NOT_REGISTERED) {
|
||||
observer.addOnPreDrawListener(this);
|
||||
@@ -3961,15 +3958,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
if (observer != null) {
|
||||
// No need to create the controller.
|
||||
// The get method will add the listener on controller creation.
|
||||
if (mInsertionPointCursorController != null) {
|
||||
observer.addOnTouchModeChangeListener(mInsertionPointCursorController);
|
||||
}
|
||||
if (mSelectionModifierCursorController != null) {
|
||||
observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
|
||||
}
|
||||
// No need to create the controller.
|
||||
// The get method will add the listener on controller creation.
|
||||
if (mInsertionPointCursorController != null) {
|
||||
observer.addOnTouchModeChangeListener(mInsertionPointCursorController);
|
||||
}
|
||||
if (mSelectionModifierCursorController != null) {
|
||||
observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3978,18 +3973,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
if (observer != null) {
|
||||
if (mPreDrawState != PREDRAW_NOT_REGISTERED) {
|
||||
observer.removeOnPreDrawListener(this);
|
||||
mPreDrawState = PREDRAW_NOT_REGISTERED;
|
||||
}
|
||||
// No need to create the controller, as getXXController would.
|
||||
if (mInsertionPointCursorController != null) {
|
||||
observer.removeOnTouchModeChangeListener(mInsertionPointCursorController);
|
||||
}
|
||||
if (mSelectionModifierCursorController != null) {
|
||||
observer.removeOnTouchModeChangeListener(mSelectionModifierCursorController);
|
||||
}
|
||||
if (mPreDrawState != PREDRAW_NOT_REGISTERED) {
|
||||
observer.removeOnPreDrawListener(this);
|
||||
mPreDrawState = PREDRAW_NOT_REGISTERED;
|
||||
}
|
||||
// No need to create the controller, as getXXController would.
|
||||
if (mInsertionPointCursorController != null) {
|
||||
observer.removeOnTouchModeChangeListener(mInsertionPointCursorController);
|
||||
}
|
||||
if (mSelectionModifierCursorController != null) {
|
||||
observer.removeOnTouchModeChangeListener(mSelectionModifierCursorController);
|
||||
}
|
||||
|
||||
if (mError != null) {
|
||||
@@ -4290,10 +4283,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
|
||||
if (mPreDrawState == PREDRAW_DONE) {
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
if (observer != null) {
|
||||
observer.removeOnPreDrawListener(this);
|
||||
mPreDrawState = PREDRAW_NOT_REGISTERED;
|
||||
}
|
||||
observer.removeOnPreDrawListener(this);
|
||||
mPreDrawState = PREDRAW_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
int color = mCurTextColor;
|
||||
@@ -5541,8 +5532,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
ellipsisWidth);
|
||||
} else {
|
||||
if (boring == UNKNOWN_BORING) {
|
||||
boring = BoringLayout.isBoring(mTransformed, mTextPaint,
|
||||
mBoring);
|
||||
boring = BoringLayout.isBoring(mTransformed, mTextPaint, mBoring);
|
||||
if (boring != null) {
|
||||
mBoring = boring;
|
||||
}
|
||||
@@ -8655,9 +8645,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
}
|
||||
|
||||
private class HandleView extends View {
|
||||
private class HandleView extends View implements ViewTreeObserver.OnScrollChangedListener {
|
||||
private Drawable mDrawable;
|
||||
private final PopupWindow mContainer;
|
||||
private final ScrollingPopupWindow mContainer;
|
||||
private int mPositionX;
|
||||
private int mPositionY;
|
||||
private final CursorController mController;
|
||||
@@ -8726,7 +8716,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
public HandleView(CursorController controller, int pos) {
|
||||
super(TextView.this.mContext);
|
||||
mController = controller;
|
||||
mContainer = new PopupWindow(TextView.this.mContext, null,
|
||||
mContainer = new ScrollingPopupWindow(TextView.this.mContext, null,
|
||||
com.android.internal.R.attr.textSelectHandleWindowStyle);
|
||||
mContainer.setSplitTouchEnabled(true);
|
||||
mContainer.setClippingEnabled(false);
|
||||
@@ -8794,24 +8784,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
return;
|
||||
}
|
||||
mContainer.setContentView(this);
|
||||
final int[] coords = mTempCoords;
|
||||
TextView.this.getLocationInWindow(coords);
|
||||
mContainerPositionX = coords[0] + mPositionX;
|
||||
mContainerPositionY = coords[1] + mPositionY;
|
||||
mContainer.showAtLocation(TextView.this, 0, mContainerPositionX, mContainerPositionY);
|
||||
mContainerPositionX = mPositionX;
|
||||
mContainerPositionY = mPositionY - TextView.this.getHeight();
|
||||
mContainer.showAsDropDown(TextView.this, mContainerPositionX, mContainerPositionY);
|
||||
|
||||
// Hide paste view when handle is moved on screen.
|
||||
if (mPastePopupWindow != null) {
|
||||
mPastePopupWindow.hide();
|
||||
}
|
||||
hidePastePopupWindow();
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
mIsDragging = false;
|
||||
mContainer.dismiss();
|
||||
if (mPastePopupWindow != null) {
|
||||
mPastePopupWindow.hide();
|
||||
}
|
||||
hidePastePopupWindow();
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
@@ -8834,19 +8818,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
final int compoundPaddingRight = getCompoundPaddingRight();
|
||||
|
||||
final TextView hostView = TextView.this;
|
||||
final int left = 0;
|
||||
final int right = hostView.getWidth();
|
||||
final int top = 0;
|
||||
final int bottom = hostView.getHeight();
|
||||
|
||||
if (mTempRect == null) {
|
||||
mTempRect = new Rect();
|
||||
}
|
||||
final Rect clip = mTempRect;
|
||||
clip.left = left + compoundPaddingLeft;
|
||||
clip.top = top + extendedPaddingTop;
|
||||
clip.right = right - compoundPaddingRight;
|
||||
clip.bottom = bottom - extendedPaddingBottom;
|
||||
clip.left = compoundPaddingLeft;
|
||||
clip.top = extendedPaddingTop;
|
||||
clip.right = hostView.getWidth() - compoundPaddingRight;
|
||||
clip.bottom = hostView.getHeight() - extendedPaddingBottom;
|
||||
|
||||
final ViewParent parent = hostView.getParent();
|
||||
if (parent == null || !parent.getChildVisibleRect(hostView, clip, null)) {
|
||||
@@ -8858,7 +8838,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
final int posX = coords[0] + mPositionX + (int) mHotspotX;
|
||||
final int posY = coords[1] + mPositionY + (int) mHotspotY;
|
||||
|
||||
return posX >= clip.left && posX <= clip.right &&
|
||||
// Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal.
|
||||
return posX >= clip.left - 1 && posX <= clip.right + 1 &&
|
||||
posY >= clip.top && posY <= clip.bottom;
|
||||
}
|
||||
|
||||
@@ -8868,23 +8849,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
if (isPositionVisible()) {
|
||||
int[] coords = null;
|
||||
if (mContainer.isShowing()) {
|
||||
coords = mTempCoords;
|
||||
TextView.this.getLocationInWindow(coords);
|
||||
final int containerPositionX = coords[0] + mPositionX;
|
||||
final int containerPositionY = coords[1] + mPositionY;
|
||||
final int containerPositionX = mPositionX;
|
||||
final int containerPositionY = mPositionY - TextView.this.getHeight();
|
||||
|
||||
if (containerPositionX != mContainerPositionX ||
|
||||
containerPositionY != mContainerPositionY) {
|
||||
mContainerPositionX = containerPositionX;
|
||||
mContainerPositionY = containerPositionY;
|
||||
|
||||
mContainer.update(mContainerPositionX, mContainerPositionY,
|
||||
mContainer.update(TextView.this, mContainerPositionX, mContainerPositionY,
|
||||
mRight - mLeft, mBottom - mTop);
|
||||
|
||||
// Hide paste popup window as soon as a scroll occurs.
|
||||
if (mPastePopupWindow != null) {
|
||||
mPastePopupWindow.hide();
|
||||
}
|
||||
hidePastePopupWindow();
|
||||
}
|
||||
} else {
|
||||
show();
|
||||
@@ -8902,9 +8879,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
mLastParentY = coords[1];
|
||||
}
|
||||
// Hide paste popup window as soon as the handle is dragged.
|
||||
if (mPastePopupWindow != null) {
|
||||
mPastePopupWindow.hide();
|
||||
}
|
||||
hidePastePopupWindow();
|
||||
}
|
||||
} else {
|
||||
hide();
|
||||
@@ -9008,10 +8983,60 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
mPastePopupWindow.show();
|
||||
}
|
||||
}
|
||||
|
||||
void hidePastePopupWindow() {
|
||||
if (mPastePopupWindow != null) {
|
||||
mPastePopupWindow.hide();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A popup window, attached to a view, and that listens to scroll events in its anchors'
|
||||
* view hierarchy, so that it is automatically moved on such events.
|
||||
*/
|
||||
private class ScrollingPopupWindow extends PopupWindow {
|
||||
|
||||
private int[] mDrawingLocations = new int[2];
|
||||
|
||||
public ScrollingPopupWindow(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
|
||||
int xoff, int yoff) {
|
||||
anchor.getLocationInWindow(mDrawingLocations);
|
||||
p.x = mDrawingLocations[0] + xoff;
|
||||
p.y = mDrawingLocations[1] + anchor.getHeight() + yoff;
|
||||
|
||||
// Hide paste popup as soon as the view is scrolled.
|
||||
hidePastePopupWindow();
|
||||
|
||||
if (!isPositionVisible()) {
|
||||
dismiss();
|
||||
onHandleBecomeInvisible();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void onScrollChanged() {
|
||||
if (isPositionVisible()) {
|
||||
show();
|
||||
ViewTreeObserver vto = TextView.this.getViewTreeObserver();
|
||||
vto.removeOnScrollChangedListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onHandleBecomeInvisible() {
|
||||
ViewTreeObserver vto = TextView.this.getViewTreeObserver();
|
||||
vto.addOnScrollChangedListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
private class InsertionPointCursorController implements CursorController {
|
||||
private static final int DELAY_BEFORE_FADE_OUT = 4100;
|
||||
private static final int DELAY_BEFORE_FADE_OUT = 4000;
|
||||
private static final int DELAY_BEFORE_PASTE = 2000;
|
||||
private static final int RECENT_CUT_COPY_DURATION = 15 * 1000;
|
||||
|
||||
@@ -9027,7 +9052,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
public void show(int delayBeforePaste) {
|
||||
updatePosition();
|
||||
hideDelayed();
|
||||
getHandle().show();
|
||||
removePastePopupCallback();
|
||||
final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime;
|
||||
if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION) {
|
||||
@@ -9547,9 +9571,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
mInsertionPointCursorController = new InsertionPointCursorController();
|
||||
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
if (observer != null) {
|
||||
observer.addOnTouchModeChangeListener(mInsertionPointCursorController);
|
||||
}
|
||||
observer.addOnTouchModeChangeListener(mInsertionPointCursorController);
|
||||
}
|
||||
|
||||
return mInsertionPointCursorController;
|
||||
@@ -9564,9 +9586,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
mSelectionModifierCursorController = new SelectionModifierCursorController();
|
||||
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
if (observer != null) {
|
||||
observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
|
||||
}
|
||||
observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
|
||||
}
|
||||
|
||||
return mSelectionModifierCursorController;
|
||||
|
||||
Reference in New Issue
Block a user