feat(android): add possibility to hide seekBar (#3789)
* feat: hide seekBar on Android when a video is a live broadcast * refactor: prop name & code * chore: update the document for a new prop (controlsStyles) * refactor: code * remove: additional variables * fix: indent issues * remove: duplicate function * Update android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java revert change1 * Update android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java revert change2 * Update android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java * Update android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java chore: revert indent change * Update android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java chore: revert indent change * Update android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java chore: revert indent change * Update android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java chore: revert indent change * Update android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java chore: revert indent change * fix: eslint errors * Update android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java chore: revert indent change --------- Co-authored-by: Olivier Bouillet <62574056+freeboub@users.noreply.github.com>
This commit is contained in:
parent
3cd7ab60b2
commit
95e6140eea
@ -0,0 +1,21 @@
|
||||
package com.brentvatne.common.api
|
||||
|
||||
import com.brentvatne.common.toolbox.ReactBridgeUtils
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
|
||||
class ControlsConfig {
|
||||
var hideSeekBar: Boolean = false
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun parse(src: ReadableMap?): ControlsConfig {
|
||||
val config = ControlsConfig()
|
||||
|
||||
if (src != null) {
|
||||
config.hideSeekBar = ReactBridgeUtils.safeGetBool(src, "hideSeekBar", false)
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
}
|
||||
}
|
@ -29,6 +29,8 @@ import android.view.Window;
|
||||
import android.view.accessibility.CaptioningManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
@ -102,10 +104,12 @@ import androidx.media3.extractor.metadata.emsg.EventMessage;
|
||||
import androidx.media3.extractor.metadata.id3.Id3Frame;
|
||||
import androidx.media3.extractor.metadata.id3.TextInformationFrame;
|
||||
import androidx.media3.session.MediaSessionService;
|
||||
import androidx.media3.ui.DefaultTimeBar;
|
||||
import androidx.media3.ui.LegacyPlayerControlView;
|
||||
|
||||
import com.brentvatne.common.api.BufferConfig;
|
||||
import com.brentvatne.common.api.BufferingStrategy;
|
||||
import com.brentvatne.common.api.ControlsConfig;
|
||||
import com.brentvatne.common.api.ResizeMode;
|
||||
import com.brentvatne.common.api.SideLoadedTextTrack;
|
||||
import com.brentvatne.common.api.SideLoadedTextTrackList;
|
||||
@ -120,6 +124,7 @@ import com.brentvatne.react.R;
|
||||
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
|
||||
import com.brentvatne.receiver.BecomingNoisyListener;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.google.ads.interactivemedia.v3.api.AdError;
|
||||
@ -212,6 +217,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
private Handler mainHandler;
|
||||
private Runnable mainRunnable;
|
||||
private DataSource.Factory cacheDataSourceFactory;
|
||||
private ControlsConfig controlsConfig = new ControlsConfig();
|
||||
|
||||
// Props from React
|
||||
private Uri srcUri;
|
||||
@ -451,6 +457,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
final ImageButton fullScreenButton = playerControlView.findViewById(R.id.exo_fullscreen);
|
||||
fullScreenButton.setOnClickListener(v -> setFullscreen(!isFullscreen));
|
||||
updateFullScreenButtonVisbility();
|
||||
refreshProgressBarVisibility();
|
||||
|
||||
// Invoking onPlaybackStateChanged and onPlayWhenReadyChanged events for Player
|
||||
eventListener = new Player.Listener() {
|
||||
@ -509,6 +516,35 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
view.layout(view.getLeft(), view.getTop(), view.getMeasuredWidth(), view.getMeasuredHeight());
|
||||
}
|
||||
|
||||
private void refreshProgressBarVisibility (){
|
||||
if(playerControlView == null) return;
|
||||
DefaultTimeBar exoProgress;
|
||||
TextView exoDuration;
|
||||
TextView exoPosition;
|
||||
exoProgress = playerControlView.findViewById(R.id.exo_progress);
|
||||
exoDuration = playerControlView.findViewById(R.id.exo_duration);
|
||||
exoPosition = playerControlView.findViewById(R.id.exo_position);
|
||||
if(controlsConfig.getHideSeekBar()){
|
||||
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
1.0f
|
||||
);
|
||||
exoProgress.setVisibility(GONE);
|
||||
exoDuration.setVisibility(GONE);
|
||||
exoPosition.setLayoutParams(param);
|
||||
}else{
|
||||
exoProgress.setVisibility(VISIBLE);
|
||||
exoDuration.setVisibility(VISIBLE);
|
||||
// Reset the layout parameters of exoPosition to their default state
|
||||
LinearLayout.LayoutParams defaultParam = new LinearLayout.LayoutParams(
|
||||
LayoutParams.WRAP_CONTENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
exoPosition.setLayoutParams(defaultParam);
|
||||
}
|
||||
}
|
||||
|
||||
private void reLayoutControls() {
|
||||
reLayout(exoPlayerView);
|
||||
reLayout(playerControlView);
|
||||
@ -2296,4 +2332,9 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
AdError error = adErrorEvent.getError();
|
||||
eventEmitter.receiveAdErrorEvent(error.getMessage(), String.valueOf(error.getErrorCode()), String.valueOf(error.getErrorType()));
|
||||
}
|
||||
|
||||
public void setControlsStyles(ControlsConfig controlsStyles) {
|
||||
controlsConfig = controlsStyles;
|
||||
refreshProgressBarVisibility();
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import androidx.media3.datasource.RawResourceDataSource;
|
||||
|
||||
import com.brentvatne.common.api.BufferConfig;
|
||||
import com.brentvatne.common.api.BufferingStrategy;
|
||||
import com.brentvatne.common.api.ControlsConfig;
|
||||
import com.brentvatne.common.api.ResizeMode;
|
||||
import com.brentvatne.common.api.SideLoadedTextTrackList;
|
||||
import com.brentvatne.common.api.SubtitleStyle;
|
||||
@ -88,6 +89,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
private static final String PROP_SHUTTER_COLOR = "shutterColor";
|
||||
private static final String PROP_SHOW_NOTIFICATION_CONTROLS = "showNotificationControls";
|
||||
private static final String PROP_DEBUG = "debug";
|
||||
private static final String PROP_CONTROLS_STYLES = "controlsStyles";
|
||||
|
||||
private final ReactExoplayerConfig config;
|
||||
|
||||
@ -451,6 +453,12 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
videoView.setDebug(enableDebug);
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_CONTROLS_STYLES)
|
||||
public void setControlsStyles(final ReactExoplayerView videoView, @Nullable ReadableMap controlsStyles) {
|
||||
ControlsConfig controlsConfig = ControlsConfig.parse(controlsStyles);
|
||||
videoView.setControlsStyles(controlsConfig);
|
||||
}
|
||||
|
||||
private boolean startsWithValidScheme(String uriString) {
|
||||
String lowerCaseUri = uriString.toLowerCase();
|
||||
return lowerCaseUri.startsWith("http://")
|
||||
|
@ -47,6 +47,25 @@ A Boolean value that indicates whether the player should automatically delay pla
|
||||
- **false** - Immediately starts playback
|
||||
- **true (default)** - Delays playback in order to minimize stalling
|
||||
|
||||
### `controlsStyles`
|
||||
|
||||
<PlatformsList types={['Android']} />
|
||||
|
||||
Adjust the control styles. This prop is need only if `controls={true}` and is an object. See the list of prop supported below.
|
||||
|
||||
| Property | Type | Description |
|
||||
|-------------|---------|--------------------------------------------------------------------------------------|
|
||||
| hideSeekBar | boolean | The default value is `false`, allowing you to hide the seek bar for live broadcasts. |
|
||||
|
||||
Example with default values:
|
||||
|
||||
```javascript
|
||||
controlsStyles={{
|
||||
hideSeekBar: false,
|
||||
}}
|
||||
```
|
||||
|
||||
|
||||
### `bufferConfig`
|
||||
|
||||
<PlatformsList types={['Android']} />
|
||||
|
@ -273,6 +273,10 @@ export type OnAudioFocusChangedData = Readonly<{
|
||||
hasAudioFocus: boolean;
|
||||
}>;
|
||||
|
||||
type ControlsStyles = Readonly<{
|
||||
hideSeekBar?: boolean;
|
||||
}>;
|
||||
|
||||
export interface VideoNativeProps extends ViewProps {
|
||||
src?: VideoSrc;
|
||||
drm?: Drm;
|
||||
@ -320,6 +324,7 @@ export interface VideoNativeProps extends ViewProps {
|
||||
useTextureView?: boolean; // Android
|
||||
useSecureView?: boolean; // Android
|
||||
bufferingStrategy?: BufferingStrategyType; // Android
|
||||
controlsStyles?: ControlsStyles; // Android
|
||||
onVideoLoad?: DirectEventHandler<OnLoadData>;
|
||||
onVideoLoadStart?: DirectEventHandler<OnLoadStartData>;
|
||||
onVideoAspectRatio?: DirectEventHandler<OnVideoAspectRatioData>;
|
||||
|
@ -193,6 +193,10 @@ export enum PosterResizeModeType {
|
||||
|
||||
export type AudioOutput = 'speaker' | 'earpiece';
|
||||
|
||||
export type ControlsStyles = {
|
||||
hideSeekBar?: boolean;
|
||||
};
|
||||
|
||||
export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
|
||||
source?: ReactVideoSource;
|
||||
drm?: Drm;
|
||||
@ -247,4 +251,5 @@ export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
|
||||
localSourceEncryptionKeyScheme?: string;
|
||||
debug?: DebugConfig;
|
||||
allowsExternalPlayback?: boolean; // iOS
|
||||
controlsStyles?: ControlsStyles; // Android
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user