Fix key and accessibility scrubbing

Issue: #5767
PiperOrigin-RevId: 243811443
This commit is contained in:
olly 2019-04-16 16:26:09 +01:00 committed by Oliver Woodman
parent 0be4bee25f
commit ee08e7dcac
3 changed files with 62 additions and 45 deletions

View file

@ -433,7 +433,7 @@ public class DefaultTimeBar extends View implements TimeBar {
public void setDuration(long duration) {
this.duration = duration;
if (scrubbing && duration == C.TIME_UNSET) {
stopScrubbing(true);
stopScrubbing(/* canceled= */ true);
}
update();
}
@ -463,7 +463,7 @@ public class DefaultTimeBar extends View implements TimeBar {
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (scrubbing && !enabled) {
stopScrubbing(true);
stopScrubbing(/* canceled= */ true);
}
}
@ -487,8 +487,7 @@ public class DefaultTimeBar extends View implements TimeBar {
case MotionEvent.ACTION_DOWN:
if (isInSeekBar(x, y)) {
positionScrubber(x);
startScrubbing();
scrubPosition = getScrubberPosition();
startScrubbing(getScrubberPosition());
update();
invalidate();
return true;
@ -503,10 +502,7 @@ public class DefaultTimeBar extends View implements TimeBar {
lastCoarseScrubXPosition = x;
positionScrubber(x);
}
scrubPosition = getScrubberPosition();
for (OnScrubListener listener : listeners) {
listener.onScrubMove(this, scrubPosition);
}
updateScrubbing(getScrubberPosition());
update();
invalidate();
return true;
@ -515,7 +511,7 @@ public class DefaultTimeBar extends View implements TimeBar {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (scrubbing) {
stopScrubbing(event.getAction() == MotionEvent.ACTION_CANCEL);
stopScrubbing(/* canceled= */ event.getAction() == MotionEvent.ACTION_CANCEL);
return true;
}
break;
@ -543,8 +539,7 @@ public class DefaultTimeBar extends View implements TimeBar {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
if (scrubbing) {
removeCallbacks(stopScrubbingRunnable);
stopScrubbingRunnable.run();
stopScrubbing(/* canceled= */ false);
return true;
}
break;
@ -555,6 +550,15 @@ public class DefaultTimeBar extends View implements TimeBar {
return super.onKeyDown(keyCode, event);
}
@Override
protected void onFocusChanged(
boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
if (scrubbing && !gainFocus) {
stopScrubbing(/* canceled= */ false);
}
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
@ -637,11 +641,11 @@ public class DefaultTimeBar extends View implements TimeBar {
}
if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
if (scrubIncrementally(-getPositionIncrement())) {
stopScrubbing(false);
stopScrubbing(/* canceled= */ false);
}
} else if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) {
if (scrubIncrementally(getPositionIncrement())) {
stopScrubbing(false);
stopScrubbing(/* canceled= */ false);
}
} else {
return false;
@ -652,7 +656,8 @@ public class DefaultTimeBar extends View implements TimeBar {
// Internal methods.
private void startScrubbing() {
private void startScrubbing(long scrubPosition) {
this.scrubPosition = scrubPosition;
scrubbing = true;
setPressed(true);
ViewParent parent = getParent();
@ -660,11 +665,22 @@ public class DefaultTimeBar extends View implements TimeBar {
parent.requestDisallowInterceptTouchEvent(true);
}
for (OnScrubListener listener : listeners) {
listener.onScrubStart(this, getScrubberPosition());
listener.onScrubStart(this, scrubPosition);
}
}
private void updateScrubbing(long scrubPosition) {
if (this.scrubPosition == scrubPosition) {
return;
}
this.scrubPosition = scrubPosition;
for (OnScrubListener listener : listeners) {
listener.onScrubMove(this, scrubPosition);
}
}
private void stopScrubbing(boolean canceled) {
removeCallbacks(stopScrubbingRunnable);
scrubbing = false;
setPressed(false);
ViewParent parent = getParent();
@ -673,10 +689,34 @@ public class DefaultTimeBar extends View implements TimeBar {
}
invalidate();
for (OnScrubListener listener : listeners) {
listener.onScrubStop(this, getScrubberPosition(), canceled);
listener.onScrubStop(this, scrubPosition, canceled);
}
}
/**
* Incrementally scrubs the position by {@code positionChange}.
*
* @param positionChange The change in the scrubber position, in milliseconds. May be negative.
* @return Returns whether the scrubber position changed.
*/
private boolean scrubIncrementally(long positionChange) {
if (duration <= 0) {
return false;
}
long previousPosition = scrubbing ? scrubPosition : position;
long scrubPosition = Util.constrainValue(previousPosition + positionChange, 0, duration);
if (scrubPosition == previousPosition) {
return false;
}
if (!scrubbing) {
startScrubbing(scrubPosition);
} else {
updateScrubbing(scrubPosition);
}
update();
return true;
}
private void update() {
bufferedBar.set(progressBar);
scrubberBar.set(progressBar);
@ -793,31 +833,6 @@ public class DefaultTimeBar extends View implements TimeBar {
? (duration == C.TIME_UNSET ? 0 : (duration / keyCountIncrement)) : keyTimeIncrement;
}
/**
* Incrementally scrubs the position by {@code positionChange}.
*
* @param positionChange The change in the scrubber position, in milliseconds. May be negative.
* @return Returns whether the scrubber position changed.
*/
private boolean scrubIncrementally(long positionChange) {
if (duration <= 0) {
return false;
}
long scrubberPosition = getScrubberPosition();
scrubPosition = Util.constrainValue(scrubberPosition + positionChange, 0, duration);
if (scrubPosition == scrubberPosition) {
return false;
}
if (!scrubbing) {
startScrubbing();
}
for (OnScrubListener listener : listeners) {
listener.onScrubMove(this, scrubPosition);
}
update();
return true;
}
private boolean setDrawableLayoutDirection(Drawable drawable) {
return Util.SDK_INT >= 23 && setDrawableLayoutDirection(drawable, getLayoutDirection());
}

View file

@ -1109,6 +1109,9 @@ public class PlayerControlView extends FrameLayout {
@Override
public void onScrubStart(TimeBar timeBar, long position) {
scrubbing = true;
if (positionView != null) {
positionView.setText(Util.getStringForTime(formatBuilder, formatter, position));
}
}
@Override

View file

@ -114,7 +114,7 @@ public interface TimeBar {
* Called when the user starts moving the scrubber.
*
* @param timeBar The time bar.
* @param position The position of the scrubber, in milliseconds.
* @param position The scrub position in milliseconds.
*/
void onScrubStart(TimeBar timeBar, long position);
@ -122,7 +122,7 @@ public interface TimeBar {
* Called when the user moves the scrubber.
*
* @param timeBar The time bar.
* @param position The position of the scrubber, in milliseconds.
* @param position The scrub position in milliseconds.
*/
void onScrubMove(TimeBar timeBar, long position);
@ -130,11 +130,10 @@ public interface TimeBar {
* Called when the user stops moving the scrubber.
*
* @param timeBar The time bar.
* @param position The position of the scrubber, in milliseconds.
* @param position The scrub position in milliseconds.
* @param canceled Whether scrubbing was canceled.
*/
void onScrubStop(TimeBar timeBar, long position, boolean canceled);
}
}