feat(android): add settings button to control video playback speed (#4211)
This commit is contained in:
parent
d81e6ea31e
commit
d1883a7e00
@ -6,7 +6,6 @@ import com.facebook.react.bridge.ReadableMap
|
|||||||
class ControlsConfig {
|
class ControlsConfig {
|
||||||
var hideSeekBar: Boolean = false
|
var hideSeekBar: Boolean = false
|
||||||
var hideDuration: Boolean = false
|
var hideDuration: Boolean = false
|
||||||
|
|
||||||
var hidePosition: Boolean = false
|
var hidePosition: Boolean = false
|
||||||
var hidePlayPause: Boolean = false
|
var hidePlayPause: Boolean = false
|
||||||
var hideForward: Boolean = false
|
var hideForward: Boolean = false
|
||||||
@ -17,6 +16,7 @@ class ControlsConfig {
|
|||||||
var hideNavigationBarOnFullScreenMode: Boolean = true
|
var hideNavigationBarOnFullScreenMode: Boolean = true
|
||||||
var hideNotificationBarOnFullScreenMode: Boolean = true
|
var hideNotificationBarOnFullScreenMode: Boolean = true
|
||||||
var liveLabel: String? = null
|
var liveLabel: String? = null
|
||||||
|
var hideSettingButton: Boolean = true
|
||||||
|
|
||||||
var seekIncrementMS: Int = 10000
|
var seekIncrementMS: Int = 10000
|
||||||
|
|
||||||
@ -39,6 +39,7 @@ class ControlsConfig {
|
|||||||
config.hideNavigationBarOnFullScreenMode = ReactBridgeUtils.safeGetBool(controlsConfig, "hideNavigationBarOnFullScreenMode", true)
|
config.hideNavigationBarOnFullScreenMode = ReactBridgeUtils.safeGetBool(controlsConfig, "hideNavigationBarOnFullScreenMode", true)
|
||||||
config.hideNotificationBarOnFullScreenMode = ReactBridgeUtils.safeGetBool(controlsConfig, "hideNotificationBarOnFullScreenMode", true)
|
config.hideNotificationBarOnFullScreenMode = ReactBridgeUtils.safeGetBool(controlsConfig, "hideNotificationBarOnFullScreenMode", true)
|
||||||
config.liveLabel = ReactBridgeUtils.safeGetString(controlsConfig, "liveLabel", null)
|
config.liveLabel = ReactBridgeUtils.safeGetString(controlsConfig, "liveLabel", null)
|
||||||
|
config.hideSettingButton = ReactBridgeUtils.safeGetBool(controlsConfig, "hideSettingButton", true)
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import static androidx.media3.common.C.TIME_END_OF_SOURCE;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -99,7 +100,6 @@ import androidx.media3.extractor.metadata.emsg.EventMessage;
|
|||||||
import androidx.media3.extractor.metadata.id3.Id3Frame;
|
import androidx.media3.extractor.metadata.id3.Id3Frame;
|
||||||
import androidx.media3.extractor.metadata.id3.TextInformationFrame;
|
import androidx.media3.extractor.metadata.id3.TextInformationFrame;
|
||||||
import androidx.media3.session.MediaSessionService;
|
import androidx.media3.session.MediaSessionService;
|
||||||
import androidx.media3.ui.DefaultTimeBar;
|
|
||||||
import androidx.media3.ui.LegacyPlayerControlView;
|
import androidx.media3.ui.LegacyPlayerControlView;
|
||||||
|
|
||||||
import com.brentvatne.common.api.BufferConfig;
|
import com.brentvatne.common.api.BufferConfig;
|
||||||
@ -258,6 +258,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
private long lastDuration = -1;
|
private long lastDuration = -1;
|
||||||
|
|
||||||
private boolean viewHasDropped = false;
|
private boolean viewHasDropped = false;
|
||||||
|
private int selectedSpeedIndex = 1; // Default is 1.0x
|
||||||
|
|
||||||
private final String instanceId = String.valueOf(UUID.randomUUID());
|
private final String instanceId = String.valueOf(UUID.randomUUID());
|
||||||
|
|
||||||
@ -463,6 +464,10 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
setPausedModifier(true)
|
setPausedModifier(true)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//Handling the settingButton click event
|
||||||
|
final ImageButton settingButton = playerControlView.findViewById(R.id.exo_settings);
|
||||||
|
settingButton.setOnClickListener(v -> openSettings());
|
||||||
|
|
||||||
//Handling the fullScreenButton click event
|
//Handling the fullScreenButton click event
|
||||||
final ImageButton fullScreenButton = playerControlView.findViewById(R.id.exo_fullscreen);
|
final ImageButton fullScreenButton = playerControlView.findViewById(R.id.exo_fullscreen);
|
||||||
fullScreenButton.setOnClickListener(v -> setFullscreen(!isFullscreen));
|
fullScreenButton.setOnClickListener(v -> setFullscreen(!isFullscreen));
|
||||||
@ -496,6 +501,35 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
};
|
};
|
||||||
player.addListener(eventListener);
|
player.addListener(eventListener);
|
||||||
}
|
}
|
||||||
|
private void openSettings() {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(themedReactContext);
|
||||||
|
builder.setTitle(R.string.settings);
|
||||||
|
String[] settingsOptions = {themedReactContext.getString(R.string.playback_speed)};
|
||||||
|
builder.setItems(settingsOptions, (dialog, which) -> {
|
||||||
|
if (which == 0) {
|
||||||
|
showPlaybackSpeedOptions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showPlaybackSpeedOptions() {
|
||||||
|
String[] speedOptions = {"0.5x", "1.0x", "1.5x", "2.0x"};
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(themedReactContext);
|
||||||
|
builder.setTitle(R.string.select_playback_speed);
|
||||||
|
|
||||||
|
builder.setSingleChoiceItems(speedOptions, selectedSpeedIndex, (dialog, which) -> {
|
||||||
|
selectedSpeedIndex = which;
|
||||||
|
float speed = switch (which) {
|
||||||
|
case 0 -> 0.5f;
|
||||||
|
case 2 -> 1.5f;
|
||||||
|
case 3 -> 2.0f;
|
||||||
|
default -> 1.0f;
|
||||||
|
};
|
||||||
|
setRateModifier(speed);
|
||||||
|
});
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adding Player control to the frame layout
|
* Adding Player control to the frame layout
|
||||||
@ -539,6 +573,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
updateViewVisibility(playerControlView.findViewById(R.id.exo_position), controlsConfig.getHidePosition(), GONE);
|
updateViewVisibility(playerControlView.findViewById(R.id.exo_position), controlsConfig.getHidePosition(), GONE);
|
||||||
updateViewVisibility(playerControlView.findViewById(R.id.exo_progress), controlsConfig.getHideSeekBar(), INVISIBLE);
|
updateViewVisibility(playerControlView.findViewById(R.id.exo_progress), controlsConfig.getHideSeekBar(), INVISIBLE);
|
||||||
updateViewVisibility(playerControlView.findViewById(R.id.exo_duration), controlsConfig.getHideDuration(), GONE);
|
updateViewVisibility(playerControlView.findViewById(R.id.exo_duration), controlsConfig.getHideDuration(), GONE);
|
||||||
|
updateViewVisibility(playerControlView.findViewById(R.id.exo_settings), controlsConfig.getHideSettingButton(), GONE );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLiveContent() {
|
private void updateLiveContent() {
|
||||||
|
@ -101,6 +101,13 @@
|
|||||||
android:includeFontPadding="false"
|
android:includeFontPadding="false"
|
||||||
android:textColor="@color/silver_gray"/>
|
android:textColor="@color/silver_gray"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/exo_settings"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/ExoStyledControls.Button.Bottom.Settings"
|
||||||
|
/>
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/exo_fullscreen"
|
android:id="@+id/exo_fullscreen"
|
||||||
style="@style/ExoMediaButton.FullScreen"
|
style="@style/ExoMediaButton.FullScreen"
|
||||||
|
@ -16,4 +16,10 @@
|
|||||||
<string name="error_drm_unsupported_scheme">This device does not support the required DRM scheme</string>
|
<string name="error_drm_unsupported_scheme">This device does not support the required DRM scheme</string>
|
||||||
|
|
||||||
<string name="error_drm_unknown">An unknown DRM error occurred</string>
|
<string name="error_drm_unknown">An unknown DRM error occurred</string>
|
||||||
|
|
||||||
|
<string name="settings">Settings</string>
|
||||||
|
|
||||||
|
<string name="playback_speed">Playback Speed</string>
|
||||||
|
|
||||||
|
<string name="select_playback_speed">Select Playback Speed</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -157,6 +157,7 @@ Adjust the control styles. This prop is need only if `controls={true}` and is an
|
|||||||
| hideDuration | boolean | The default value is `false`, allowing you to hide the duration. |
|
| hideDuration | boolean | The default value is `false`, allowing you to hide the duration. |
|
||||||
| hideNavigationBarOnFullScreenMode | boolean | The default value is `true`, allowing you to hide the navigation bar on full-screen mode. |
|
| hideNavigationBarOnFullScreenMode | boolean | The default value is `true`, allowing you to hide the navigation bar on full-screen mode. |
|
||||||
| hideNotificationBarOnFullScreenMode | boolean | The default value is `true`, allowing you to hide the notification bar on full-screen mode. |
|
| hideNotificationBarOnFullScreenMode | boolean | The default value is `true`, allowing you to hide the notification bar on full-screen mode. |
|
||||||
|
| hideSettingButton | boolean | The default value is `true`, allowing you to hide the setting button. |
|
||||||
| seekIncrementMS | number | The default value is `10000`. You can change the value to increment forward and rewind. |
|
| seekIncrementMS | number | The default value is `10000`. You can change the value to increment forward and rewind. |
|
||||||
| liveLabel | string | Allowing you to set a label for live video. |
|
| liveLabel | string | Allowing you to set a label for live video. |
|
||||||
|
|
||||||
@ -175,6 +176,7 @@ controlsStyles={{
|
|||||||
hideDuration: false,
|
hideDuration: false,
|
||||||
hideNavigationBarOnFullScreenMode: true,
|
hideNavigationBarOnFullScreenMode: true,
|
||||||
hideNotificationBarOnFullScreenMode: true,
|
hideNotificationBarOnFullScreenMode: true,
|
||||||
|
hideSettingButton: true,
|
||||||
seekIncrementMS: 10000,
|
seekIncrementMS: 10000,
|
||||||
liveLabel: "LIVE"
|
liveLabel: "LIVE"
|
||||||
}}
|
}}
|
||||||
|
@ -308,6 +308,7 @@ type ControlsStyles = Readonly<{
|
|||||||
hideDuration?: WithDefault<boolean, false>;
|
hideDuration?: WithDefault<boolean, false>;
|
||||||
hideNavigationBarOnFullScreenMode?: WithDefault<boolean, true>;
|
hideNavigationBarOnFullScreenMode?: WithDefault<boolean, true>;
|
||||||
hideNotificationBarOnFullScreenMode?: WithDefault<boolean, true>;
|
hideNotificationBarOnFullScreenMode?: WithDefault<boolean, true>;
|
||||||
|
hideSettingButton?: WithDefault<boolean, true>;
|
||||||
seekIncrementMS?: Int32;
|
seekIncrementMS?: Int32;
|
||||||
liveLabel?: string;
|
liveLabel?: string;
|
||||||
}>;
|
}>;
|
||||||
|
@ -260,6 +260,7 @@ export type ControlsStyles = {
|
|||||||
hideFullscreen?: boolean;
|
hideFullscreen?: boolean;
|
||||||
hideNavigationBarOnFullScreenMode?: boolean;
|
hideNavigationBarOnFullScreenMode?: boolean;
|
||||||
hideNotificationBarOnFullScreenMode?: boolean;
|
hideNotificationBarOnFullScreenMode?: boolean;
|
||||||
|
hideSettingButton?: boolean;
|
||||||
seekIncrementMS?: number;
|
seekIncrementMS?: number;
|
||||||
liveLabel?: string;
|
liveLabel?: string;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user