diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java index 46cd54058c8..328b5d6a491 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java @@ -433,7 +433,7 @@ public void setBufferedPosition(long bufferedPosition) { 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 void setAdGroupTimesMs(@Nullable long[] adGroupTimesMs, @Nullable boolean public void setEnabled(boolean enabled) { super.setEnabled(enabled); if (scrubbing && !enabled) { - stopScrubbing(true); + stopScrubbing(/* canceled= */ true); } } @@ -487,8 +487,7 @@ public boolean onTouchEvent(MotionEvent event) { case MotionEvent.ACTION_DOWN: if (isInSeekBar(x, y)) { positionScrubber(x); - startScrubbing(); - scrubPosition = getScrubberPosition(); + startScrubbing(getScrubberPosition()); update(); invalidate(); return true; @@ -503,10 +502,7 @@ public boolean onTouchEvent(MotionEvent event) { 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 boolean onTouchEvent(MotionEvent event) { 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 boolean onKeyDown(int keyCode, KeyEvent event) { 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 boolean onKeyDown(int keyCode, KeyEvent event) { 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 boolean performAccessibilityAction(int action, @Nullable Bundle args) { } 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 boolean performAccessibilityAction(int action, @Nullable Bundle args) { // Internal methods. - private void startScrubbing() { + private void startScrubbing(long scrubPosition) { + this.scrubPosition = scrubPosition; scrubbing = true; setPressed(true); ViewParent parent = getParent(); @@ -660,11 +665,22 @@ private void startScrubbing() { 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 @@ private void stopScrubbing(boolean canceled) { } 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 @@ private long getPositionIncrement() { ? (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()); } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java index afd344432f6..a5deb808c1d 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java @@ -1109,6 +1109,9 @@ private final class ComponentListener @Override public void onScrubStart(TimeBar timeBar, long position) { scrubbing = true; + if (positionView != null) { + positionView.setText(Util.getStringForTime(formatBuilder, formatter, position)); + } } @Override diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/TimeBar.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/TimeBar.java index 9ac3cba4fd8..d62f2494d54 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/TimeBar.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/TimeBar.java @@ -114,7 +114,7 @@ interface OnScrubListener { * 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 @@ interface OnScrubListener { * 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 @@ interface OnScrubListener { * 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); - } }