diff --git a/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoControls.java b/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoControls.java index 8bf3b6f4..17124776 100644 --- a/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoControls.java +++ b/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoControls.java @@ -49,7 +49,7 @@ * or remove for the Default Video Controls. */ @SuppressWarnings("unused") -public abstract class VideoControls extends RelativeLayout { +public abstract class VideoControls extends RelativeLayout implements VideoControlsCore { public static final int DEFAULT_CONTROL_HIDE_DELAY = 2_000; protected static final long CONTROL_VISIBILITY_ANIMATION_LENGTH = 300; @@ -108,14 +108,6 @@ public abstract class VideoControls extends RelativeLayout { */ public abstract void setPosition(@IntRange(from = 0) long position); - /** - * Sets the video duration in Milliseconds to display - * at the end of the progress bar - * - * @param duration The duration of the video in milliseconds - */ - public abstract void setDuration(@IntRange(from = 0) long duration); - /** * Performs the progress update on the current time field, * and the seek bar @@ -147,20 +139,6 @@ public abstract class VideoControls extends RelativeLayout { */ protected abstract void updateTextContainerVisibility(); - /** - * Update the controls to indicate that the video - * is loading. - * - * @param initialLoad True if the loading is the initial state, not for seeking or buffering - */ - public abstract void showLoading(boolean initialLoad); - - /** - * Update the controls to indicate that the video is no longer loading - * which will re-display the play/pause, progress, etc. controls - */ - public abstract void finishLoading(); - public VideoControls(Context context) { super(context); setup(context); @@ -207,12 +185,27 @@ protected void onDetachedFromWindow() { progressPollRepeater.setRepeatListener(null); } + @Override + public void onAttachedToView(@NonNull VideoView videoView) { + videoView.addView(this); + setVideoView(videoView); + } + + @Override + public void onDetachedFromView(@NonNull VideoView videoView) { + videoView.removeView(this); + setVideoView(null); + } + /** * Sets the parent view to use for determining playback length, position, * state, etc. This should only be called once, during the setup process * * @param VideoView The Parent view to these controls + * + * @deprecated Use {@link #onAttachedToView(VideoView)} and {@link #onDetachedFromView(VideoView)} */ + @Deprecated public void setVideoView(@Nullable VideoView VideoView) { this.videoView = VideoView; } @@ -250,6 +243,7 @@ public void setVisibilityListener(@Nullable VideoControlsVisibilityListener call * * @param isPlaying True if the media is currently playing */ + @Override public void updatePlaybackState(boolean isPlaying) { updatePlayPauseImage(isPlaying); progressPollRepeater.start(); @@ -466,6 +460,7 @@ public List getExtraViews() { /** * Immediately starts the animation to show the controls */ + @Override public void show() { //Makes sure we don't have a hide animation scheduled visibilityHandler.removeCallbacksAndMessages(null); @@ -474,6 +469,15 @@ public void show() { animateVisibility(true); } + @Override + public void hide(boolean delayed) { + if (delayed) { + hideDelayed(); + } else { + hide(); + } + } + /** * Immediately starts the animation to hide the controls */ @@ -553,6 +557,7 @@ public void setHideEmptyTextContainer(boolean hide) { * * @return true if the controls are visible */ + @Override public boolean isVisible() { return isVisible; } diff --git a/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoControlsCore.java b/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoControlsCore.java new file mode 100644 index 00000000..84e2fa0e --- /dev/null +++ b/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoControlsCore.java @@ -0,0 +1,82 @@ +package com.devbrackets.android.exomedia.ui.widget; + +import android.support.annotation.IntRange; +import android.support.annotation.NonNull; + +/** + * An Interface that represents the core VideoControl functionality that + * the {@link VideoView} uses to inform the controls of updated states, etc. + * + * Note: To preserve backwards compatibility this is being called *Core, + * On the next major release we should rename this to VideoControls and + * call the abstract class something else. + */ +public interface VideoControlsCore { + + /** + * Called when the controls have been registered by the + * {@link VideoView}. + * + * @param videoView The {@link VideoView} that the controls are attached to + */ + void onAttachedToView(@NonNull VideoView videoView); + + /** + * Called when the controls have been cleaned up on the {@link VideoView} + * side in preparation for detachment. + * + * @param videoView The {@link VideoView} that the controls are detaching from + */ + void onDetachedFromView(@NonNull VideoView videoView); + + /** + * Shows the controls immediately + */ + void show(); + + /** + * Hides the controls immediately if delayed is false + * otherwise a delay determined by the implementation will be used + * before the controls are hidden. If the user is interacting with + * the controls then we wait until after they are done to start the + * delay. + */ + void hide(boolean delayed); + + /** + * Update the controls to indicate that the video + * is loading. + * + * @param initialLoad true if the loading is the initial state, not for seeking or buffering + */ + void showLoading(boolean initialLoad); + + /** + * Update the controls to indicate that the video is no longer loading + * which will re-display the play/pause, progress, etc. controls + */ + void finishLoading(); + + /** + * Informs the controls that the playback state has changed. This will + * update to display the correct views, and manage progress polling. + * + * @param isPlaying True if the media is currently playing + */ + void updatePlaybackState(boolean isPlaying); + + /** + * Sets the video duration in Milliseconds to display + * at the end of the progress bar + * + * @param duration The duration of the video in milliseconds + */ + void setDuration(@IntRange(from = 0) long duration); + + /** + * Returns true if the {@link VideoControlsCore} are visible + * + * @return true if the controls are visible + */ + boolean isVisible(); +} diff --git a/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoView.java b/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoView.java index ca3df574..43edefb7 100644 --- a/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoView.java +++ b/library/src/main/java/com/devbrackets/android/exomedia/ui/widget/VideoView.java @@ -77,7 +77,7 @@ public class VideoView extends RelativeLayout { private static final String TAG = VideoView.class.getSimpleName(); @Nullable - protected VideoControls videoControls; + protected VideoControlsCore videoControls; protected ImageView previewImageView; protected Uri videoUri; @@ -158,7 +158,11 @@ public void setReleaseOnDetachFromWindow(boolean releaseOnDetach) { * {@link #setReleaseOnDetachFromWindow(boolean)} has been set. */ public void release() { - videoControls = null; + if (videoControls != null) { + videoControls.onDetachedFromView(this); + videoControls = null; + } + stopPlayback(); overriddenPositionStopWatch.stop(); @@ -218,15 +222,22 @@ public ImageView getPreviewImageView() { return previewImageView; } + /** + * @deprecated Use {@link #setControls(VideoControlsCore)} + */ + @Deprecated public void setControls(@Nullable VideoControls controls) { + setControls((VideoControlsCore) controls); + } + + public void setControls(@Nullable VideoControlsCore controls) { if (videoControls != null && videoControls != controls) { - removeView(videoControls); + videoControls.onDetachedFromView(this); } - if (controls != null) { - videoControls = controls; - controls.setVideoView(this); - addView(controls); + videoControls = controls; + if (videoControls != null) { + videoControls.onAttachedToView(this); } //Sets the onTouch listener to show the controls @@ -243,7 +254,7 @@ public void showControls() { videoControls.show(); if (isPlaying()) { - videoControls.hideDelayed(); + videoControls.hide(true); } } } @@ -255,9 +266,21 @@ public void showControls() { * null * * @return The video controls being used by this view or null + * @deprecated Use {@link #getVideoControlsCore()} */ @Nullable + @Deprecated public VideoControls getVideoControls() { + if (videoControls != null && videoControls instanceof VideoControls) { + return (VideoControls) videoControls; + } + + return null; + } + + // TODO: Rename this to getVideoControls when we remove the other method of that name + @Nullable + public VideoControlsCore getVideoControlsCore() { return videoControls; } @@ -1052,7 +1075,7 @@ public boolean onTouch(View view, MotionEvent event) { public boolean onSingleTapConfirmed(MotionEvent event) { // Toggles between hiding and showing the controls if (videoControls != null && videoControls.isVisible()) { - videoControls.hide(); + videoControls.hide(false); } else { showControls(); }