Update text selection handles to have a minimum touch target size.

The text selection handles were traditionally sized based on the size
of the provided drawables. When these drawables are visually small, do
not restrict the size of the touch target beyond a certain minimum.

Bug 16851360

Change-Id: If6a468c7b3a9a1a21913006633f00699637751c0
This commit is contained in:
Adam Powell
2014-08-19 18:28:04 -07:00
parent 75d6bc1aee
commit 3fceabd64c
3 changed files with 76 additions and 4 deletions

View File

@@ -3158,6 +3158,7 @@ public class Editor {
// Offset from touch position to mPosition
private float mTouchToWindowOffsetX, mTouchToWindowOffsetY;
protected int mHotspotX;
protected int mHorizontalGravity;
// Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up
private float mTouchOffsetY;
// Where the touch position should be on the handle to ensure a maximum cursor visibility
@@ -3172,6 +3173,8 @@ public class Editor {
private boolean mPositionHasChanged = true;
// Used to delay the appearance of the action popup window
private Runnable mActionPopupShower;
// Minimum touch target size for handles
private int mMinSize;
public HandleView(Drawable drawableLtr, Drawable drawableRtl) {
super(mTextView.getContext());
@@ -3184,10 +3187,12 @@ public class Editor {
mDrawableLtr = drawableLtr;
mDrawableRtl = drawableRtl;
mMinSize = mTextView.getContext().getResources().getDimensionPixelSize(
com.android.internal.R.dimen.text_handle_min_size);
updateDrawable();
final int handleHeight = mDrawable.getIntrinsicHeight();
final int handleHeight = getPreferredHeight();
mTouchOffsetY = -0.3f * handleHeight;
mIdealVerticalOffset = 0.7f * handleHeight;
}
@@ -3197,9 +3202,11 @@ public class Editor {
final boolean isRtlCharAtOffset = mTextView.getLayout().isRtlCharAt(offset);
mDrawable = isRtlCharAtOffset ? mDrawableRtl : mDrawableLtr;
mHotspotX = getHotspotX(mDrawable, isRtlCharAtOffset);
mHorizontalGravity = getHorizontalGravity(isRtlCharAtOffset);
}
protected abstract int getHotspotX(Drawable drawable, boolean isRtlRun);
protected abstract int getHorizontalGravity(boolean isRtlRun);
// Touch-up filter: number of previous positions remembered
private static final int HISTORY_SIZE = 5;
@@ -3244,7 +3251,15 @@ public class Editor {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
setMeasuredDimension(getPreferredWidth(), getPreferredHeight());
}
private int getPreferredWidth() {
return Math.max(mDrawable.getIntrinsicWidth(), mMinSize);
}
private int getPreferredHeight() {
return Math.max(mDrawable.getIntrinsicHeight(), mMinSize);
}
public void show() {
@@ -3336,7 +3351,8 @@ public class Editor {
}
final int line = layout.getLineForOffset(offset);
mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX);
mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX -
getHorizontalOffset() + getCursorOffset());
mPositionY = layout.getLineBottom(line);
// Take TextView's padding and scroll into account.
@@ -3385,10 +3401,36 @@ public class Editor {
@Override
protected void onDraw(Canvas c) {
mDrawable.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
final int drawWidth = mDrawable.getIntrinsicWidth();
final int left = getHorizontalOffset();
mDrawable.setBounds(left, 0, left + drawWidth, mDrawable.getIntrinsicHeight());
mDrawable.draw(c);
}
private int getHorizontalOffset() {
final int width = getPreferredWidth();
final int drawWidth = mDrawable.getIntrinsicWidth();
final int left;
switch (mHorizontalGravity) {
case Gravity.LEFT:
left = 0;
break;
default:
case Gravity.CENTER:
left = (width - drawWidth) / 2;
break;
case Gravity.RIGHT:
left = width - drawWidth;
break;
}
return left;
}
protected int getCursorOffset() {
return 0;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getActionMasked()) {
@@ -3507,6 +3549,22 @@ public class Editor {
return drawable.getIntrinsicWidth() / 2;
}
@Override
protected int getHorizontalGravity(boolean isRtlRun) {
return Gravity.CENTER_HORIZONTAL;
}
@Override
protected int getCursorOffset() {
int offset = super.getCursorOffset();
final Drawable cursor = mCursorCount > 0 ? mCursorDrawable[0] : null;
if (cursor != null) {
cursor.getPadding(mTempRect);
offset += (cursor.getIntrinsicWidth() - mTempRect.left - mTempRect.right) / 2;
}
return offset;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final boolean result = super.onTouchEvent(ev);
@@ -3593,6 +3651,11 @@ public class Editor {
}
}
@Override
protected int getHorizontalGravity(boolean isRtlRun) {
return isRtlRun ? Gravity.RIGHT : Gravity.LEFT;
}
@Override
public int getCurrentCursorOffset() {
return mTextView.getSelectionStart();
@@ -3636,6 +3699,11 @@ public class Editor {
}
}
@Override
protected int getHorizontalGravity(boolean isRtlRun) {
return isRtlRun ? Gravity.LEFT : Gravity.RIGHT;
}
@Override
public int getCurrentCursorOffset() {
return mTextView.getSelectionEnd();

View File

@@ -394,4 +394,7 @@
<dimen name="lock_pattern_dot_line_width">3dp</dimen>
<dimen name="lock_pattern_dot_size">12dp</dimen>
<dimen name="lock_pattern_dot_size_activated">28dp</dimen>
<dimen name="text_handle_min_size">40dp</dimen>
</resources>

View File

@@ -1983,4 +1983,5 @@
<java-symbol type="layout" name="select_dialog_singlechoice_material" />
<java-symbol type="layout" name="select_dialog_multichoice_material" />
<java-symbol type="array" name="no_ems_support_sim_operators" />
<java-symbol type="dimen" name="text_handle_min_size" />
</resources>