Handwriting gesture line margin
Point-based handwriting gestures are supported for points within text line bounds. With this change, they will also be supported for points which are outside the line bounds but within a margin of the line bounds. The margin is added to ViewConfiguration so that the value can be accessed by other UI toolkits so that they can implement the same behavior. The dimension resource is added as a @SystemApi so that OEMs may override the value. Bug: 243967209 Test: atest android.widget.cts.TextViewHandwritingGestureTest Change-Id: I0e64f20c670808580346a485d06a0da0f21d3ed2
This commit is contained in:
@@ -50911,6 +50911,7 @@ package android.view {
|
||||
method public int getScaledDoubleTapSlop();
|
||||
method public int getScaledEdgeSlop();
|
||||
method public int getScaledFadingEdgeLength();
|
||||
method public int getScaledHandwritingGestureLineMargin();
|
||||
method public int getScaledHandwritingSlop();
|
||||
method public float getScaledHorizontalScrollFactor();
|
||||
method public int getScaledHoverSlop();
|
||||
|
||||
@@ -401,6 +401,7 @@ package android {
|
||||
|
||||
public static final class R.dimen {
|
||||
field public static final int config_restrictedIconSize = 17104903; // 0x1050007
|
||||
field public static final int config_viewConfigurationHandwritingGestureLineMargin;
|
||||
}
|
||||
|
||||
public static final class R.drawable {
|
||||
|
||||
@@ -217,6 +217,11 @@ public class ViewConfiguration {
|
||||
*/
|
||||
private static final int WINDOW_TOUCH_SLOP = 16;
|
||||
|
||||
/**
|
||||
* Margin in dips around text line bounds where stylus handwriting gestures should be supported.
|
||||
*/
|
||||
private static final int HANDWRITING_GESTURE_LINE_MARGIN = 16;
|
||||
|
||||
/**
|
||||
* Minimum velocity to initiate a fling, as measured in dips per second
|
||||
*/
|
||||
@@ -338,6 +343,7 @@ public class ViewConfiguration {
|
||||
private final int mPagingTouchSlop;
|
||||
private final int mDoubleTapSlop;
|
||||
private final int mWindowTouchSlop;
|
||||
private final int mHandwritingGestureLineMargin;
|
||||
private final float mAmbiguousGestureMultiplier;
|
||||
private final int mMaximumDrawingCacheSize;
|
||||
private final int mOverscrollDistance;
|
||||
@@ -381,6 +387,7 @@ public class ViewConfiguration {
|
||||
mPagingTouchSlop = PAGING_TOUCH_SLOP;
|
||||
mDoubleTapSlop = DOUBLE_TAP_SLOP;
|
||||
mWindowTouchSlop = WINDOW_TOUCH_SLOP;
|
||||
mHandwritingGestureLineMargin = HANDWRITING_GESTURE_LINE_MARGIN;
|
||||
mAmbiguousGestureMultiplier = AMBIGUOUS_GESTURE_MULTIPLIER;
|
||||
//noinspection deprecation
|
||||
mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE;
|
||||
@@ -490,6 +497,9 @@ public class ViewConfiguration {
|
||||
|
||||
mDoubleTapTouchSlop = mTouchSlop;
|
||||
|
||||
mHandwritingGestureLineMargin = res.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.config_viewConfigurationHandwritingGestureLineMargin);
|
||||
|
||||
mMinimumFlingVelocity = res.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.config_viewMinFlingVelocity);
|
||||
mMaximumFlingVelocity = res.getDimensionPixelSize(
|
||||
@@ -795,6 +805,14 @@ public class ViewConfiguration {
|
||||
return mDoubleTapSlop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return margin in pixels around text line bounds where stylus handwriting gestures should be
|
||||
* supported.
|
||||
*/
|
||||
public int getScaledHandwritingGestureLineMargin() {
|
||||
return mHandwritingGestureLineMargin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interval for dispatching a recurring accessibility event in milliseconds.
|
||||
* This interval guarantees that a recurring event will be send at most once
|
||||
|
||||
@@ -9391,12 +9391,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
/** @hide */
|
||||
public int performHandwritingInsertGesture(@NonNull InsertGesture gesture) {
|
||||
PointF point = convertFromScreenToContentCoordinates(gesture.getInsertionPoint());
|
||||
int line = mLayout.getLineForVertical((int) point.y);
|
||||
if (point.y < mLayout.getLineTop(line)
|
||||
|| point.y > mLayout.getLineBottom(line, /* includeLineSpacing= */ false)) {
|
||||
return handleGestureFailure(gesture);
|
||||
}
|
||||
if (point.x < mLayout.getLineLeft(line) || point.x > mLayout.getLineRight(line)) {
|
||||
int line = getLineForHandwritingGesture(point);
|
||||
if (line == -1) {
|
||||
return handleGestureFailure(gesture);
|
||||
}
|
||||
int offset = mLayout.getOffsetForHorizontal(line, point.x);
|
||||
@@ -9412,27 +9408,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
PointF startPoint = convertFromScreenToContentCoordinates(gesture.getStartPoint());
|
||||
PointF endPoint = convertFromScreenToContentCoordinates(gesture.getEndPoint());
|
||||
|
||||
// The operation should be applied to the first line of text touched by the line joining
|
||||
// the points.
|
||||
int yMin = (int) Math.min(startPoint.y, endPoint.y);
|
||||
int yMax = (int) Math.max(startPoint.y, endPoint.y);
|
||||
int line = mLayout.getLineForVertical(yMin);
|
||||
if (yMax < mLayout.getLineTop(line)) {
|
||||
// Both points are above the top of the first line.
|
||||
return handleGestureFailure(gesture);
|
||||
}
|
||||
if (yMin > mLayout.getLineBottom(line, /* includeLineSpacing= */ false)) {
|
||||
if (line == mLayout.getLineCount() - 1 || yMax < mLayout.getLineTop(line + 1)) {
|
||||
// The points are below the last line, or they are between two lines.
|
||||
// The operation should be applied to the first line of text containing one of the points.
|
||||
int startPointLine = getLineForHandwritingGesture(startPoint);
|
||||
int endPointLine = getLineForHandwritingGesture(endPoint);
|
||||
int line;
|
||||
if (startPointLine == -1) {
|
||||
if (endPointLine == -1) {
|
||||
return handleGestureFailure(gesture);
|
||||
} else {
|
||||
// Apply the operation to the next line.
|
||||
line++;
|
||||
}
|
||||
}
|
||||
if (Math.max(startPoint.x, endPoint.x) < mLayout.getLineLeft(line)
|
||||
|| Math.min(startPoint.x, endPoint.x) > mLayout.getLineRight(line)) {
|
||||
return handleGestureFailure(gesture);
|
||||
line = endPointLine;
|
||||
} else {
|
||||
line = (endPointLine == -1) ? startPointLine : Math.min(startPointLine, endPointLine);
|
||||
}
|
||||
|
||||
// The operation should be applied to all characters touched by the line joining the points.
|
||||
@@ -9479,12 +9465,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
public int performHandwritingJoinOrSplitGesture(@NonNull JoinOrSplitGesture gesture) {
|
||||
PointF point = convertFromScreenToContentCoordinates(gesture.getJoinOrSplitPoint());
|
||||
|
||||
int line = mLayout.getLineForVertical((int) point.y);
|
||||
if (point.y < mLayout.getLineTop(line)
|
||||
|| point.y > mLayout.getLineBottom(line, /* includeLineSpacing= */ false)) {
|
||||
return handleGestureFailure(gesture);
|
||||
}
|
||||
if (point.x < mLayout.getLineLeft(line) || point.x > mLayout.getLineRight(line)) {
|
||||
int line = getLineForHandwritingGesture(point);
|
||||
if (line == -1) {
|
||||
return handleGestureFailure(gesture);
|
||||
}
|
||||
|
||||
@@ -9529,6 +9511,37 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
return InputConnection.HANDWRITING_GESTURE_RESULT_FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest line such that the point is either inside the line bounds or within
|
||||
* {@link ViewConfiguration#getScaledHandwritingGestureLineMargin} of the line bounds. Returns
|
||||
* -1 if the point is not within the margin of any line bounds.
|
||||
*/
|
||||
private int getLineForHandwritingGesture(PointF point) {
|
||||
int line = mLayout.getLineForVertical((int) point.y);
|
||||
int lineMargin = ViewConfiguration.get(mContext).getScaledHandwritingGestureLineMargin();
|
||||
if (line < mLayout.getLineCount() - 1
|
||||
&& point.y > mLayout.getLineBottom(line) - lineMargin
|
||||
&& point.y
|
||||
> (mLayout.getLineBottom(line, false) + mLayout.getLineBottom(line)) / 2f) {
|
||||
// If a point is in the space between line i and line (i + 1), Layout#getLineForVertical
|
||||
// returns i. If the point is within lineMargin of line (i + 1), and closer to line
|
||||
// (i + 1) than line i, then the gesture operation should be applied to line (i + 1).
|
||||
line++;
|
||||
} else if (point.y < mLayout.getLineTop(line) - lineMargin
|
||||
|| point.y
|
||||
> mLayout.getLineBottom(line, /* includeLineSpacing= */ false)
|
||||
+ lineMargin) {
|
||||
// The point is not within lineMargin of a line.
|
||||
return -1;
|
||||
}
|
||||
if (point.x < mLayout.getLineLeft(line) - lineMargin
|
||||
|| point.x > mLayout.getLineRight(line) + lineMargin) {
|
||||
// The point is not within lineMargin of a line.
|
||||
return -1;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Range<Integer> getRangeForRect(@NonNull RectF area, int granularity) {
|
||||
SegmentFinder segmentFinder;
|
||||
|
||||
@@ -2610,6 +2610,9 @@
|
||||
movement threshold under which hover is considered "stationary". -->
|
||||
<dimen name="config_viewConfigurationHoverSlop">4dp</dimen>
|
||||
|
||||
<!-- Margin around text line bounds where stylus handwriting gestures should be supported. -->
|
||||
<dimen name="config_viewConfigurationHandwritingGestureLineMargin">16dp</dimen>
|
||||
|
||||
<!-- Multiplier for gesture thresholds when a MotionEvent classification is ambiguous. -->
|
||||
<item name="config_ambiguousGestureMultiplier" format="float" type="dimen">2.0</item>
|
||||
|
||||
|
||||
@@ -131,6 +131,8 @@
|
||||
</staging-public-group>
|
||||
|
||||
<staging-public-group type="dimen" first-id="0x01ca0000">
|
||||
<!-- @hide @SystemApi -->
|
||||
<public name="config_viewConfigurationHandwritingGestureLineMargin" />
|
||||
</staging-public-group>
|
||||
|
||||
<staging-public-group type="color" first-id="0x01c90000">
|
||||
|
||||
Reference in New Issue
Block a user