Is there any way to use the built in iOS/Android video controls for video playback in React Native?
For example, here is what it would look like on iOS
I used expo-av library to do this. You can also use this library in bare project as well. (https://github.com/expo/expo/tree/master/packages/expo-av)
All you need to do to get the native video controls is pass in useNativeControls. Heres there code and example (https://snack.expo.dev/#heytony01/video)
import * as React from 'react';
import { View, StyleSheet, Button } from 'react-native';
import { Video, AVPlaybackStatus } from 'expo-av';
export default function App() {
const video = React.useRef(null);
const [status, setStatus] = React.useState({});
return (
<View style={styles.container}>
<Video
ref={video}
style={styles.video}
source={{
uri: 'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4',
}}
useNativeControls
resizeMode="contain"
isLooping
onPlaybackStatusUpdate={status => setStatus(() => status)}
/>
<View style={styles.buttons}>
<Button
title={status.isPlaying ? 'Pause' : 'Play'}
onPress={() =>
status.isPlaying ? video.current.pauseAsync() : video.current.playAsync()
}
/>
</View>
</View>
);
}
Related
i have a problem when i want to send data of a URL so when you go to the next page your show the spesific url, im using expo cli not react native cli
website.tsx
import React, { useState } from "react";
import { Dimensions } from "react-native";
import { Div, Text } from "react-native-magnus";
import WebView from "react-native-webview";
const Website = ({YOUR_URL}) => {
return (
<WebView
rautomaticallyAdjustContentInsets={false}
source={{uri: YOUR_URL}}
style={{marginTop: 20, height: "100%", width: "100%"}}
onLoad={console.log("Loaded")}
startInLoadingState={true}
javaScriptEnabled={true}
/>
);
};
export default Website;
and this is my button to send the data
<Button w={wp(40)} h={hp(5.5)} ml={hp(2)}
onPress={() => navigation.navigate('Website', {YOUR_URL:data?.external_link})}
// onPress={() => Linking.openURL(data?.external_link)}
>
<Text allowFontScaling={false} fontSize={16} color="#fff">
Selengkapnya
</Text>
if you can help me, thank you very much
For me it worked by passing it precise values for width and height for Webview component and not percentage values. For managing the different display sizes I think you should use "scale".
using https://github.com/invertase/react-native-apple-authentication
import React from 'react';
import { View } from 'react-native';
import { AppleButton } from '#invertase/react-native-apple-authentication';
async function onAppleButtonPress() {
}
function App() {
return (
<View>
<AppleButton
buttonStyle={AppleButton.Style.WHITE}
buttonType={AppleButton.Type.SIGN_IN}
style={{
width: 160, // You must specify a width
height: 45, // You must specify a height
}}
onPress={() => onAppleButtonPress()}
/>
</View>
);
}
Maybe you don't need this answer anymore, but currently this error still happens and the solution I found was:
import {appleAuth} from '#invertase/react-native-apple-authentication';
<View>
{appleAuth.isSupported && (
<Button title="Sign in with Apple" onPress={AppleSignIn} />
)}
</View>
The AppleButton seems to work fine in production:
<AppleButton
buttonStyle={AppleButton.Style.BLACK}
buttonType={AppleButton.Type.SIGN_IN}
style={styles.appleButton}
onPress={AppleSignIn}
/>
It says in the library docs that it is only available in React Native v0.60+.
I wanted to ask what would be the best way to handle loading for videos on Expo / React Native.
Expo has good documentation on the Video and AV components to handle video / audio:
https://docs.expo.io/versions/latest/sdk/video/
https://docs.expo.io/versions/latest/sdk/av/
I've tried two things so far: '
Using posterSource in a Video component. The problem here is that the poster image doesn't format properly.
This is what my Video component looks like:
const videoStyle = { width: '100%', height: '100%', display: display};
return (
<Video
ref={playbackObject}
source={{uri: source}}
posterSource={require('path/to/file')}
rate={1.0}
volume={1.0}
isMuted={isMuted}
resizeMode="cover"
usePoster={true}
shouldPlay={shouldPlay}
onPlaybackStatusUpdate={_onPlaybackStatusUpdate}
progressUpdateIntervalMillis={50}
isLooping
style={videoStyle}
posterStyle={videoStyle}
>
</Video>
)
I’ve also tried using playbackStatus to see if the video is loaded or buffering and have an activity indicator when the video is loaded or buffering, but because I use states, there is some lag.
My implementation for (2) looks like this:
const [loaded, setLoaded] = useState(false);
const _onPlaybackStatusUpdate = playbackStatus => {
if(playbackStatus.isBuffering){
if(loaded){
setLoaded(false);
}
} else {
if(!loaded){
setLoaded(true);
}
}
}
If loaded = true, we do not show an activity indicator. Else, we do show an activity indicator. The main problem here is there is a lag, which is not great UI.
So with that in mind, what would be people’s recommendation of handling loading for videos? Thanks!!
What you can do is to render an <ActivityIndicator /> as background and when it finishes loading the asset, it will get behind the video (or you could just check if the asset was loaded or not -> optionally rendering it inside <Video />.
<Video
ref={handleVideoRef}
>
<ActivityIndicator size="large" />
</Video>
const handleVideoRef = async component => {
const playbackObject = component;
if (playbackObject) {
await playbackObject.loadAsync(
{ uri: currentVideoURI },
);
}
};
here's my solution for that :
Video component has onLoadStart and onReadyForDisplay props, which indicate when the loading starts and when it's finished.
So we could create a custom component, which would support loading indicator using the Video component imported from expo. So in the end, this would looksomething like this :
import React, {useState} from "react";
import { ActivityIndicator } from "react-native";
import { Video } from "expo-av";
const AppVideo = ({style, ...rest}) => {
return (
<View style={style}>
{isPreloading &&
<ActivityIndicator
animating
color={"gray"}
size="large"
style={{ flex: 1, position:"absolute", top:"50%", left:"45%" }}
/>
}
<Video
{...rest}
onLoadStart={() => setIsPreloading(true)}
useNativeControls
onReadyForDisplay={() => setIsPreloading(false)}
resizeMode="contain"
isLooping
/>
</View>
);
}
export default AppVideo;
I am using React Native Sidebar
This is the sidebar:
<Sidebar
ref={(ref) => this._drawer = ref}
leftSidebar={ this.renderLeftSidebar() }
leftSidebarWidth = {200}
>
</Sidebar>
This is how I'm rendering the left sidebar:
renderLeftSidebar = () =>{
return (
<View style = {{ position:'absolute', backgroundColor:'#24292e4f', height:Dimensions.get('window').height}}>
<DrawerContent/>
</View>
)
}
And this is the content for that left sidebar:
export default DrawerContent = () => {
return (
<View style={styles.animatedBox}>
<Image
source={require('../assets/images/header.png')}
style={{height:200, alignSelf:'center'}}
/>
<View style = {styles.drawerContentView}>
<Icon
name='setting'
type='antdesign'
color='#4abce3'
size ={22}
iconStyle = {styles.drawerItemIconStyle}
onPress={() => console.log('hello settings')}
/>
</View>
The sidebar opens just fine and renders correctly, but when I try and press anything on the sidebar the press goes through the sidebar and interacts with elements rendered beneath it. Should I be using zIndex in my styles or is my approach completely wrong?
If you are using React-native-vector-icons, the ICON itself has no button properties.
You can use Icon.Button
import Icon from 'react-native-vector-icons/AntDesign';
...
<Icon.Button
name='setting'
color='#4abce3'
size ={22}
iconStyle = {styles.drawerItemIconStyle}
onPress={() => console.log('hello settings')}
>
This is Setting
</Icon.Button>
OR You can use TouchableOpacity
import {
TouchableOpacity
} from 'react-native'
import Icon from 'react-native-vector-icons/AntDesign';
...
<TouchableOpacity onPress={() => console.log('hello settings')}>
<Icon
name='setting'
color='#4abce3'
size ={22}
iconStyle = {styles.drawerItemIconStyle}
/>
</TouchableOpacity>
I want to play an audio file, But it's playing automaticaly and I can't pause That.
How Can I Fix That?
That Must be Paused at the begin
My Code:
import Video from 'react-native-video';
export default class Android extends Component {
constructor(props) {
super(props)
this.state = {
paused: true,
}
}
video: Video;
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
<Video
ref={(ref: Video) => { this.video = ref }}
source={{ uri: "http://s3.picofile.com/d/7376893331/8b7bc5b4-4b5e-47c4-96dd-b0c13fd18157/Sara_Diba_Delbare_Man.mp3", mainVer: 1, patchVer: 0 }}
paused={this.state.paused}
/>
</View>
);
}
}
There's currently a bug in react-native-video where the pause flag is ignored when the component is first loaded. You have to change pause AFTER the component has loaded.
First, make sure your this.state.pause = false. Then:
<Video
paused={this.state.paused}
onLoad={() => {
this.setState({
paused: true
});
}}
</Video>
Context: https://github.com/react-native-community/react-native-video/issues/494#issuecomment-281853423
Use ref attribute to create a link to the video and using that reference we can able to use video controls on the video component
Try this code,
import React from "react";
class VideoDemo extends React.Component {
getVideo = elem => {
this.video = elem
}
playVideo = () => {
// You can use the play method as normal on your video ref
this.video.play()
};
pauseVideo = () => {
// Pause as well
this.video.pause();
};
render = () => {
return (
<div>
<video
ref={this.getVideo}
src="http://techslides.com/demos/sample-videos/small.mp4"
type="video/mp4"
/>
<div>
<button onClick={this.playVideo}>
Play!
</button>
<button onClick={this.pauseVideo}>
Pause!
</button>
</div>
</div>
);
};
}
export default VideoDemo;