Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7_0_X][TIMOB-25477] Android: Fixed bug where tapping right-aligned TextField not always receiving focus as of 6.2.2 #9662

Merged
merged 5 commits into from
Dec 14, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import android.view.inputmethod.EditorInfo;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewGroup;


Expand All @@ -39,12 +40,24 @@ public class TiUIEditText extends TextInputEditText implements NestedScrollingCh
*/
private int scrollAxisDirection = ViewCompat.SCROLL_AXIS_NONE;

/** Stores the start point of a nested touch event in screen coordinates along the x-axis. */
private int startRawTouchX;

/** Stores the start point of a nested touch event in screen coordinates along the y-axis. */
private int startRawTouchY;

/** Stores the last received nested touch event in screen coordinates along the x-axis. */
private int lastRawTouchX;

/** Stores the last received nested touch event in screen coordinates along the y-axis. */
private int lastRawTouchY;

/** Min pixel distance a touch move must cover before it's considered to be a drag/scroll event. */
private int minDragStartDistance;

/** Set true if we're in the middle of doing a nested drag/scroll. */
private boolean isDragging;


/** Creates a new EditText view. */
public TiUIEditText(Context context)
Expand Down Expand Up @@ -73,6 +86,14 @@ public TiUIEditText(Context context, AttributeSet attributeSet, int defaultStyle
*/
private void initializeView()
{
// Fetch the system's min touch move distance until it's considered to be a drag event.
// Note: This is the same setting Android's ScrollViews use.
ViewConfiguration viewConfiguration = ViewConfiguration.get(getContext());
if (viewConfiguration != null) {
this.minDragStartDistance = viewConfiguration.getScaledTouchSlop();
}

// Set up this view for nested scrolling.
this.nestedScrollingHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
}
Expand Down Expand Up @@ -117,10 +138,12 @@ public boolean onTouchEvent(MotionEvent event)
}

// Handle nested touch input and scroll handling.
boolean result = false;
boolean wasHandled = false;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
// Determine if the EditText can be scrolled vertically or horizontally.
// Note: There is a bug in EditText where canScrollHorizontally() will return
// true when it's not scrollable for "center" or "right" aligned text.
boolean isVertical = ((getInputType() & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) != 0);
boolean isScrollable;
if (isVertical) {
Expand All @@ -130,72 +153,97 @@ public boolean onTouchEvent(MotionEvent event)
}

// Start nested scrolling if the EditText is scrollable.
this.isDragging = false;
if (isScrollable) {
if (isVertical) {
this.scrollAxisDirection = ViewCompat.SCROLL_AXIS_VERTICAL;
} else {
this.scrollAxisDirection = ViewCompat.SCROLL_AXIS_HORIZONTAL;
}
this.lastRawTouchX = (int)event.getRawX();
this.lastRawTouchY = (int)event.getRawY();
startNestedScroll(this.scrollAxisDirection);
this.startRawTouchX = (int)event.getRawX();
this.startRawTouchY = (int)event.getRawY();
this.lastRawTouchX = this.startRawTouchX;
this.lastRawTouchY = this.startRawTouchY;
boolean wasStarted = startNestedScroll(this.scrollAxisDirection);
if (!wasStarted) {
this.scrollAxisDirection = ViewCompat.SCROLL_AXIS_NONE;
}
}

// Let the base class handle the touch "down" event.
result = super.onTouchEvent(event);
wasHandled = super.onTouchEvent(event);
break;
}
case MotionEvent.ACTION_MOVE: {
// Handle the touch move/drag event.
// Handle nested scrolling, if enabled.
if (this.scrollAxisDirection != ViewCompat.SCROLL_AXIS_NONE) {
// We're doing a nested scroll.
// Determine scroll direction, distance, and if EditText has hit scroll limit.
computeScroll();
// Determine if the touch point has moved far enough to be considered a drag event.
// Note: Touch down/up events within this min distance are considered taps/clicks.
boolean isVertical = (this.scrollAxisDirection == ViewCompat.SCROLL_AXIS_VERTICAL);
int deltaX = this.lastRawTouchX - (int)event.getRawX();
int deltaY = this.lastRawTouchY - (int)event.getRawY();
int deltaValue = isVertical ? deltaY : deltaX;
boolean isScrollEnabled;
boolean canScrollFurther;
if (isVertical) {
isScrollEnabled = canScrollVertically(1) || canScrollVertically(-1);
canScrollFurther = canScrollVertically(deltaValue);
} else {
isScrollEnabled = canScrollHorizontally(1) || canScrollHorizontally(-1);
canScrollFurther = canScrollHorizontally(deltaValue);
if (!this.isDragging) {
int dragDistance;
if (isVertical) {
dragDistance = this.startRawTouchY - (int)event.getRawY();
} else {
dragDistance = this.startRawTouchX - (int)event.getRawX();
}
if (Math.abs(dragDistance) > this.minDragStartDistance) {
this.isDragging = true;
}
}

// Handle the nested scroll.
if (!isScrollEnabled || !canScrollFurther) {
// EditText cannot scroll or is unable to scroll any farther.
// Request the parent to scroll instead.
result = dispatchNestedPreScroll(deltaX, deltaY, null, null);
result |= dispatchNestedScroll(0, 0, deltaX, deltaY, null);

// Cancel the EditText's long-press timer. Prevents long-press from triggering
// text selection while scrolling the parent view. (Looks goofy when it happens.)
cancelLongPress();
} else {
// EditText can scroll. Let the EditText handle the move/scroll event.
result = super.onTouchEvent(event);
// Check if we need to scroll the parent, if currently dragging.
if (this.isDragging) {
// Determine scroll direction, distance, and if EditText has hit scroll limit.
computeScroll();
int deltaX = this.lastRawTouchX - (int)event.getRawX();
int deltaY = this.lastRawTouchY - (int)event.getRawY();
int deltaValue = isVertical ? deltaY : deltaX;
boolean isScrollEnabled;
boolean canScrollFurther;
if (isVertical) {
isScrollEnabled = canScrollVertically(1) || canScrollVertically(-1);
canScrollFurther = canScrollVertically(deltaValue);
} else {
isScrollEnabled = canScrollHorizontally(1) || canScrollHorizontally(-1);
canScrollFurther = canScrollHorizontally(deltaValue);
}

// Request the parent to scroll if one of the following is true:
// - EditText is not scrollable. (ie: All text fits within the box.)
// - EditText is scrollabe, but cannot scroll any further in given direction.
if (!isScrollEnabled || !canScrollFurther) {
wasHandled = dispatchNestedPreScroll(deltaX, deltaY, null, null);
wasHandled |= dispatchNestedScroll(0, 0, deltaX, deltaY, null);
}

// Cancel EditText's long-press timer if parent was scrolled.
// Note: EditText will move with the user's finger while scrolling the parent
// in this case and we don't want it to trigger a long-press text selection.
if (wasHandled) {
cancelLongPress();
}
}

// Store the last received touch point in screen coordinates.
// This is needed to calculate nested scroll distances.
this.lastRawTouchX = (int)event.getRawX();
this.lastRawTouchY = (int)event.getRawY();
} else {
// Nested scrolling is disabled. Let EditText do default touch handling.
result = super.onTouchEvent(event);
}

// Let the EditText handle the event if the parent wasn't scrolled via the above.
if (!wasHandled) {
wasHandled = super.onTouchEvent(event);
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
// Handle the touch release event.
result = super.onTouchEvent(event);
wasHandled = super.onTouchEvent(event);

// Stop nested-scrolling if active.
this.isDragging = false;
if (this.scrollAxisDirection != ViewCompat.SCROLL_AXIS_NONE) {
stopNestedScroll();
this.scrollAxisDirection = ViewCompat.SCROLL_AXIS_NONE;
Expand All @@ -204,11 +252,11 @@ public boolean onTouchEvent(MotionEvent event)
}
default: {
// Let the base class handle all other events, such as multi-touch.
result = super.onTouchEvent(event);
wasHandled = super.onTouchEvent(event);
break;
}
}
return result;
return wasHandled;
}

@Override
Expand Down