Merge pull request #1414 from IbrahimSulai/master
Support for displaying controls in Android Exoplayer
This commit is contained in:
commit
e0fd69e9f7
@ -359,9 +359,9 @@ Determines whether to show player controls.
|
|||||||
|
|
||||||
Note on iOS, controls are always shown when in fullscreen mode.
|
Note on iOS, controls are always shown when in fullscreen mode.
|
||||||
|
|
||||||
Controls are not available Android because the system does not provide a stock set of controls. You will need to build your own or use a package like [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls) or [react-native-video-player](https://github.com/cornedor/react-native-video-player).
|
For Android MediaPlayer, you will need to build your own controls or use a package like [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls) or [react-native-video-player](https://github.com/cornedor/react-native-video-player).
|
||||||
|
|
||||||
Platforms: iOS, react-native-dom
|
Platforms: Android ExoPlayer, iOS, react-native-dom
|
||||||
|
|
||||||
#### filter
|
#### filter
|
||||||
Add video filter
|
Add video filter
|
||||||
|
@ -64,6 +64,7 @@ import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
|||||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
import com.google.android.exoplayer2.ui.PlayerControlView;
|
||||||
|
|
||||||
import java.net.CookieHandler;
|
import java.net.CookieHandler;
|
||||||
import java.net.CookieManager;
|
import java.net.CookieManager;
|
||||||
@ -96,6 +97,9 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final VideoEventEmitter eventEmitter;
|
private final VideoEventEmitter eventEmitter;
|
||||||
|
private PlayerControlView playerControlView;
|
||||||
|
private View playPauseControlContainer;
|
||||||
|
private Player.EventListener eventListener;
|
||||||
|
|
||||||
private Handler mainHandler;
|
private Handler mainHandler;
|
||||||
private ExoPlayerView exoPlayerView;
|
private ExoPlayerView exoPlayerView;
|
||||||
@ -257,6 +261,76 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Internal methods
|
// Internal methods
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggling the visibility of the player control view
|
||||||
|
*/
|
||||||
|
private void togglePlayerControlVisibility() {
|
||||||
|
reLayout(playerControlView);
|
||||||
|
if (playerControlView.isVisible()) {
|
||||||
|
playerControlView.hide();
|
||||||
|
} else {
|
||||||
|
playerControlView.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializing Player control
|
||||||
|
*/
|
||||||
|
private void initializePlayerControl() {
|
||||||
|
if (playerControlView == null) {
|
||||||
|
playerControlView = new PlayerControlView(getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setting the player for the playerControlView
|
||||||
|
playerControlView.setPlayer(player);
|
||||||
|
playerControlView.show();
|
||||||
|
playPauseControlContainer = playerControlView.findViewById(R.id.exo_play_pause_container);
|
||||||
|
|
||||||
|
// Invoking onClick event for exoplayerView
|
||||||
|
exoPlayerView.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
togglePlayerControlVisibility();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Invoking onPlayerStateChanged event for Player
|
||||||
|
eventListener = new Player.EventListener() {
|
||||||
|
@Override
|
||||||
|
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||||
|
reLayout(playPauseControlContainer);
|
||||||
|
//Remove this eventListener once its executed. since UI will work fine once after the reLayout is done
|
||||||
|
player.removeListener(eventListener);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
player.addListener(eventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding Player control to the frame layout
|
||||||
|
*/
|
||||||
|
private void addPlayerControl() {
|
||||||
|
LayoutParams layoutParams = new LayoutParams(
|
||||||
|
LayoutParams.MATCH_PARENT,
|
||||||
|
LayoutParams.MATCH_PARENT);
|
||||||
|
playerControlView.setLayoutParams(layoutParams);
|
||||||
|
addView(playerControlView, 1, layoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the layout
|
||||||
|
* @param view view needs to update layout
|
||||||
|
*
|
||||||
|
* This is a workaround for the open bug in react-native: https://github.com/facebook/react-native/issues/17968
|
||||||
|
*/
|
||||||
|
private void reLayout(View view) {
|
||||||
|
if (view == null) return;
|
||||||
|
view.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
|
||||||
|
MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
|
||||||
|
view.layout(view.getLeft(), view.getTop(), view.getMeasuredWidth(), view.getMeasuredHeight());
|
||||||
|
}
|
||||||
|
|
||||||
private void initializePlayer() {
|
private void initializePlayer() {
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
|
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
|
||||||
@ -302,6 +376,9 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
eventEmitter.loadStart();
|
eventEmitter.loadStart();
|
||||||
loadVideoStarted = true;
|
loadVideoStarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initializing the playerControlView
|
||||||
|
initializePlayerControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
private MediaSource buildMediaSource(Uri uri, String overrideExtension) {
|
private MediaSource buildMediaSource(Uri uri, String overrideExtension) {
|
||||||
@ -517,6 +594,10 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
onBuffering(false);
|
onBuffering(false);
|
||||||
startProgressHandler();
|
startProgressHandler();
|
||||||
videoLoaded();
|
videoLoaded();
|
||||||
|
//Setting the visibility for the playerControlView
|
||||||
|
if(playerControlView != null) {
|
||||||
|
playerControlView.show();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ExoPlayer.STATE_ENDED:
|
case ExoPlayer.STATE_ENDED:
|
||||||
text += "ended";
|
text += "ended";
|
||||||
@ -1056,4 +1137,17 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
releasePlayer();
|
releasePlayer();
|
||||||
initializePlayer();
|
initializePlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handling controls prop
|
||||||
|
*
|
||||||
|
* @param controls Controls prop, if true enable controls, if false disable them
|
||||||
|
*/
|
||||||
|
public void setControls(boolean controls) {
|
||||||
|
if (controls && exoPlayerView != null) {
|
||||||
|
addPlayerControl();
|
||||||
|
} else if (getChildAt(1) instanceof PlayerControlView && exoPlayerView != null) {
|
||||||
|
removeViewAt(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
private static final String PROP_SELECTED_VIDEO_TRACK_TYPE = "type";
|
private static final String PROP_SELECTED_VIDEO_TRACK_TYPE = "type";
|
||||||
private static final String PROP_SELECTED_VIDEO_TRACK_VALUE = "value";
|
private static final String PROP_SELECTED_VIDEO_TRACK_VALUE = "value";
|
||||||
private static final String PROP_HIDE_SHUTTER_VIEW = "hideShutterView";
|
private static final String PROP_HIDE_SHUTTER_VIEW = "hideShutterView";
|
||||||
|
private static final String PROP_CONTROLS = "controls";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@ -255,6 +256,11 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
videoView.setHideShutterView(hideShutterView);
|
videoView.setHideShutterView(hideShutterView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = PROP_CONTROLS, defaultBoolean = false)
|
||||||
|
public void setControls(final ReactExoplayerView videoView, final boolean controls) {
|
||||||
|
videoView.setControls(controls);
|
||||||
|
}
|
||||||
|
|
||||||
@ReactProp(name = PROP_BUFFER_CONFIG)
|
@ReactProp(name = PROP_BUFFER_CONFIG)
|
||||||
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
|
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
|
||||||
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layoutDirection="ltr"
|
||||||
|
android:background="#CC000000"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageButton android:id="@id/exo_prev"
|
||||||
|
style="@style/ExoMediaButton.Previous"/>
|
||||||
|
|
||||||
|
<ImageButton android:id="@id/exo_rew"
|
||||||
|
style="@style/ExoMediaButton.Rewind"/>
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/exo_play_pause_container"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center">
|
||||||
|
<ImageButton android:id="@id/exo_play"
|
||||||
|
style="@style/ExoMediaButton.Play"/>
|
||||||
|
|
||||||
|
<ImageButton android:id="@id/exo_pause"
|
||||||
|
style="@style/ExoMediaButton.Pause"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<ImageButton android:id="@id/exo_ffwd"
|
||||||
|
style="@style/ExoMediaButton.FastForward"/>
|
||||||
|
|
||||||
|
<ImageButton android:id="@id/exo_next"
|
||||||
|
style="@style/ExoMediaButton.Next"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView android:id="@id/exo_position"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
android:paddingRight="4dp"
|
||||||
|
android:includeFontPadding="false"
|
||||||
|
android:textColor="#FFBEBEBE"/>
|
||||||
|
|
||||||
|
<com.google.android.exoplayer2.ui.DefaultTimeBar
|
||||||
|
android:id="@id/exo_progress"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="26dp"/>
|
||||||
|
|
||||||
|
<TextView android:id="@id/exo_duration"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
android:paddingRight="4dp"
|
||||||
|
android:includeFontPadding="false"
|
||||||
|
android:textColor="#FFBEBEBE"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
Loading…
Reference in New Issue
Block a user