summaryrefslogtreecommitdiff
path: root/core/java/android/widget
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2019-01-31 18:23:49 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-01-31 18:23:49 +0000
commit6a581da028aeb3c541fa3cbdafd6c450c657bed9 (patch)
tree6297ca311dd4afbdf7d0b1d8c5ccc5277d18c90a /core/java/android/widget
parent83cbd348c3eb6005aa262eecbdb47c05bbd8d176 (diff)
parent6d26d15168b84133bd6a96d8c24d59edf1b061af (diff)
Merge "[Magnifier-76] Show for translated/scaled textview"
Diffstat (limited to 'core/java/android/widget')
-rw-r--r--core/java/android/widget/Editor.java76
1 files changed, 62 insertions, 14 deletions
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index c38566b87d9c..e9d72a26b60f 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -4489,6 +4489,13 @@ public class Editor {
// when selecting text when the handles jump to the end / start of words which may be on
// a different line.
protected int mPreviousLineTouched = UNSET_LINE;
+ // The raw x coordinate of the motion down event which started the current dragging session.
+ // Only used and stored when magnifier is used.
+ private float mCurrentDragInitialTouchRawX = UNSET_X_VALUE;
+ // The scale transform applied by containers to the TextView. Only used and computed
+ // when magnifier is used.
+ private float mTextViewScaleX;
+ private float mTextViewScaleY;
private HandleView(Drawable drawableLtr, Drawable drawableRtl, final int id) {
super(mTextView.getContext());
@@ -4808,25 +4815,44 @@ public class Editor {
/ mMagnifierAnimator.mMagnifier.getZoom());
final Paint.FontMetrics fontMetrics = mTextView.getPaint().getFontMetrics();
final float glyphHeight = fontMetrics.descent - fontMetrics.ascent;
- return glyphHeight > magnifierContentHeight;
+ return glyphHeight * mTextViewScaleY > magnifierContentHeight;
}
- private boolean viewIsMatrixTransformed() {
+ /**
+ * Traverses the hierarchy above the text view, and computes the total scale applied
+ * to it. If a rotation is encountered, the method returns {@code false}, indicating
+ * that the magnifier should not be shown anyways. It would be nice to keep these two
+ * pieces of logic separate (the rotation check and the total scale calculation),
+ * but for efficiency we can do them in a single go.
+ * @return whether the text view is rotated
+ */
+ private boolean checkForTransforms() {
if (mMagnifierAnimator.mMagnifierIsShowing) {
// Do not check again when the magnifier is currently showing.
- return false;
- }
- if (!mTextView.hasIdentityMatrix()) {
return true;
}
+
+ if (mTextView.getRotation() != 0f || mTextView.getRotationX() != 0f
+ || mTextView.getRotationY() != 0f) {
+ return false;
+ }
+ mTextViewScaleX = mTextView.getScaleX();
+ mTextViewScaleY = mTextView.getScaleY();
+
ViewParent viewParent = mTextView.getParent();
while (viewParent != null) {
- if (viewParent instanceof View && !((View) viewParent).hasIdentityMatrix()) {
- return true;
+ if (viewParent instanceof View) {
+ final View view = (View) viewParent;
+ if (view.getRotation() != 0f || view.getRotationX() != 0f
+ || view.getRotationY() != 0f) {
+ return false;
+ }
+ mTextViewScaleX *= view.getScaleX();
+ mTextViewScaleY *= view.getScaleY();
}
viewParent = viewParent.getParent();
}
- return false;
+ return true;
}
/**
@@ -4864,6 +4890,12 @@ public class Editor {
return false;
}
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mCurrentDragInitialTouchRawX = event.getRawX();
+ } else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ mCurrentDragInitialTouchRawX = UNSET_X_VALUE;
+ }
+
final Layout layout = mTextView.getLayout();
final int lineNumber = layout.getLineForOffset(offset);
// Compute whether the selection handles are currently on the same line, and,
@@ -4891,6 +4923,8 @@ public class Editor {
} else {
rightBound += mTextView.getLayout().getLineRight(lineNumber);
}
+ leftBound *= mTextViewScaleX;
+ rightBound *= mTextViewScaleX;
final float contentWidth = Math.round(mMagnifierAnimator.mMagnifier.getWidth()
/ mMagnifierAnimator.mMagnifier.getZoom());
if (touchXInView < leftBound - contentWidth / 2
@@ -4898,13 +4932,27 @@ public class Editor {
// The touch is too far from the current line / selection, so hide the magnifier.
return false;
}
- showPosInView.x = Math.max(leftBound, Math.min(rightBound, touchXInView));
+
+ final float scaledTouchXInView;
+ if (mTextViewScaleX == 1f) {
+ // In the common case, do not use mCurrentDragInitialTouchRawX to compute this
+ // coordinate, although the formula on the else branch should be equivalent.
+ // Since the formula relies on mCurrentDragInitialTouchRawX being set on
+ // MotionEvent.ACTION_DOWN, this makes us more defensive against cases when
+ // the sequence of events might not look as expected: for example, a sequence of
+ // ACTION_MOVE not preceded by ACTION_DOWN.
+ scaledTouchXInView = touchXInView;
+ } else {
+ scaledTouchXInView = (event.getRawX() - mCurrentDragInitialTouchRawX)
+ * mTextViewScaleX + mCurrentDragInitialTouchRawX
+ - textViewLocationOnScreen[0];
+ }
+ showPosInView.x = Math.max(leftBound, Math.min(rightBound, scaledTouchXInView));
// Vertically snap to middle of current line.
- showPosInView.y = (mTextView.getLayout().getLineTop(lineNumber)
+ showPosInView.y = ((mTextView.getLayout().getLineTop(lineNumber)
+ mTextView.getLayout().getLineBottom(lineNumber)) / 2.0f
- + mTextView.getTotalPaddingTop() - mTextView.getScrollY();
-
+ + mTextView.getTotalPaddingTop() - mTextView.getScrollY()) * mTextViewScaleY;
return true;
}
@@ -4956,8 +5004,8 @@ public class Editor {
}
final PointF showPosInView = new PointF();
- final boolean shouldShow = !tooLargeTextForMagnifier()
- && !viewIsMatrixTransformed()
+ final boolean shouldShow = checkForTransforms() /*check not rotated and compute scale*/
+ && !tooLargeTextForMagnifier()
&& obtainMagnifierShowCoordinates(event, showPosInView);
if (shouldShow) {
// Make the cursor visible and stop blinking.