summaryrefslogtreecommitdiff
path: root/core/java/android/widget/SmartSelectSprite.java
diff options
context:
space:
mode:
authorPetar Šegina <psegina@google.com>2017-08-15 16:20:43 +0100
committerPetar Šegina <psegina@google.com>2017-08-23 19:20:12 +0100
commit91df3f9e7c95d43d645e158b7d8fd34acc3385d3 (patch)
tree59ffdb56f0c67dfab44d8223e32aa389d1875551 /core/java/android/widget/SmartSelectSprite.java
parentb2fb182085686ea72ee4a1364d0399ba236f4ec5 (diff)
Expand the animation from the user's last touch point
The Smart Select animation now expands from the spot the user last lifted their finger. In order to achieve this, the last up event coordinates need to be tracked in Editor. Since it's possible to trigger Smart Select by having the second of the two taps outside any of the rectangles, the touch point gets moved into the nearest rectangle and the animation starts from that point. Test: manual - try out Smart Select by touching different words at different points Test: manual - try to trigger Smart Select with a double tap where the second tap is outside of the word Test: bit FrameworksCoreTests:android.widget.SelectionActionModeHelperTest Test: bit CtsViewTestCases:android.view.textclassifier.cts.TextClassificationManagerTest Test: bit FrameworksCoreTests:android.widget.TextViewActivityTest Test: bit CtsAccessibilityServiceTestCases:android.accessibilityservice.cts.AccessibilityTextTraversalTest Change-Id: I96844e8307554b010b476673820f98dae09c0cc3
Diffstat (limited to 'core/java/android/widget/SmartSelectSprite.java')
-rw-r--r--core/java/android/widget/SmartSelectSprite.java55
1 files changed, 35 insertions, 20 deletions
diff --git a/core/java/android/widget/SmartSelectSprite.java b/core/java/android/widget/SmartSelectSprite.java
index e641a9bc5176..94109d741fd8 100644
--- a/core/java/android/widget/SmartSelectSprite.java
+++ b/core/java/android/widget/SmartSelectSprite.java
@@ -30,11 +30,11 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.Shape;
-import android.util.Pair;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewOverlay;
@@ -82,16 +82,16 @@ final class SmartSelectSprite {
private final float[] mLineCoordinates;
- private PolygonShape(final List<Pair<Float, Float>> points) {
+ private PolygonShape(final List<PointF> points) {
mLineCoordinates = new float[points.size() * POINTS_PER_LINE];
int index = 0;
- Pair<Float, Float> currentPoint = points.get(0);
- for (final Pair<Float, Float> nextPoint : points) {
- mLineCoordinates[index] = currentPoint.first;
- mLineCoordinates[index + 1] = currentPoint.second;
- mLineCoordinates[index + 2] = nextPoint.first;
- mLineCoordinates[index + 3] = nextPoint.second;
+ PointF currentPoint = points.get(0);
+ for (final PointF nextPoint : points) {
+ mLineCoordinates[index] = currentPoint.x;
+ mLineCoordinates[index + 1] = currentPoint.y;
+ mLineCoordinates[index + 2] = nextPoint.x;
+ mLineCoordinates[index + 3] = nextPoint.y;
index += POINTS_PER_LINE;
currentPoint = nextPoint;
@@ -342,9 +342,9 @@ final class SmartSelectSprite {
final List<RectF> rectangles,
final int color) {
final List<Drawable> drawables = new LinkedList<>();
- final Set<List<Pair<Float, Float>>> mergedPaths = calculateMergedPolygonPoints(rectangles);
+ final Set<List<PointF>> mergedPaths = calculateMergedPolygonPoints(rectangles);
- for (List<Pair<Float, Float>> path : mergedPaths) {
+ for (List<PointF> path : mergedPaths) {
// Add the starting point to the end of the polygon so that it ends up closed.
path.add(path.get(0));
@@ -361,7 +361,7 @@ final class SmartSelectSprite {
return drawables;
}
- private static Set<List<Pair<Float, Float>>> calculateMergedPolygonPoints(
+ private static Set<List<PointF>> calculateMergedPolygonPoints(
List<RectF> rectangles) {
final Set<List<RectF>> partitions = new HashSet<>();
final LinkedList<RectF> listOfRects = new LinkedList<>(rectangles);
@@ -389,20 +389,20 @@ final class SmartSelectSprite {
partitions.add(partition);
}
- final Set<List<Pair<Float, Float>>> result = new HashSet<>();
+ final Set<List<PointF>> result = new HashSet<>();
for (List<RectF> partition : partitions) {
- final List<Pair<Float, Float>> points = new LinkedList<>();
+ final List<PointF> points = new LinkedList<>();
final Stack<RectF> rects = new Stack<>();
for (RectF rect : partition) {
- points.add(new Pair<>(rect.right, rect.top));
- points.add(new Pair<>(rect.right, rect.bottom));
+ points.add(new PointF(rect.right, rect.top));
+ points.add(new PointF(rect.right, rect.bottom));
rects.add(rect);
}
while (!rects.isEmpty()) {
final RectF rect = rects.pop();
- points.add(new Pair<>(rect.left, rect.bottom));
- points.add(new Pair<>(rect.left, rect.top));
+ points.add(new PointF(rect.left, rect.bottom));
+ points.add(new PointF(rect.left, rect.top));
}
result.add(points);
@@ -426,7 +426,7 @@ final class SmartSelectSprite {
* @see #cancelAnimation()
*/
public void startAnimation(
- final Pair<Float, Float> start,
+ final PointF start,
final List<RectF> destinationRectangles,
final Runnable onAnimationEnd) throws IllegalArgumentException {
cancelAnimation();
@@ -439,7 +439,7 @@ final class SmartSelectSprite {
final RectF centerRectangle = destinationRectangles
.stream()
- .filter((r) -> r.contains(start.first, start.second))
+ .filter((r) -> contains(r, start))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(
"Center point is not inside any of the rectangles!"));
@@ -452,7 +452,7 @@ final class SmartSelectSprite {
startingOffset += rectangle.width();
}
- startingOffset += start.first - centerRectangle.left;
+ startingOffset += start.x - centerRectangle.left;
final float centerRectangleHalfHeight = centerRectangle.height() / 2;
final float startingOffsetLeft = startingOffset - centerRectangleHalfHeight;
@@ -632,6 +632,21 @@ final class SmartSelectSprite {
return result;
}
+ /**
+ * A variant of {@link RectF#contains(float, float)} that also allows the point to reside on
+ * the right boundary of the rectangle.
+ *
+ * @param rectangle the rectangle inside which the point should be to be considered "contained"
+ * @param point the point which will be tested
+ * @return whether the point is inside the rectangle (or on it's right boundary)
+ */
+ private static boolean contains(final RectF rectangle, final PointF point) {
+ final float x = point.x;
+ final float y = point.y;
+ return x >= rectangle.left && x <= rectangle.right && y >= rectangle.top
+ && y <= rectangle.bottom;
+ }
+
private void addToOverlay(final Drawable drawable) {
mView.getOverlay().add(drawable);
mExistingAnimationDrawables.add(drawable);