How to handle video views playback inside list view in react-native - react-native

I have a list of items with a Video URL in each row.I have used React-Native-Video component for Video view.
<TouchableOpacity
style={styles.fullScreen}
onPress={() => this.setState({ paused: !this.state.paused })}
>
<Video source={{ uri: rowData.podcastUrl }} // URL
ref={(ref) => {
// Store reference
this.player = ref
......
......
}}
paused={true}
</TouchableOpacity>
Above code is inside renderMyList() function which is called on the rendering of each row.
When I load my UI all the videos are either in play mode or stopped based on 'paused' state false or true(whatever I pass in above. But I want to properly handle the play/pause of individual video(list item).I have maintained a paused state variable.
Please suggest some sample code.

If you are planning to let only one video to play any given moment you can do something like below
onPress={() => { this.setState({ playing: 'someUniqueIdForThisVideo'}) }}
And check if that video is playing
paused={this.state.playing !== 'videoIdOrSomething'}
If you want multiple videos to be played you can do something like below
onPress={() => { this.setState({ ['someUniqueIdForThisVideo']: true}) }}
And check state like below
paused={this.state['someUniqueIdForThisVideo'] !== true}
This is just to give you a rough idea. You need to implement some sort of logic to set state to false if its already playing.

Related

How to get dimensions of a video in React native?

I am using react-native-video component to play a video.
Problem:
I would like to know the dimensions of the video so I can adapt some other items.
When I store the ref with
<Video
ref={ref => setVideoRef(ref)}
resizeMode={'contain'}
/>
I can access videoRef.props.scaleX and videoRef.props.scaleY, but they are always undefined, even if the video is fully loaded. How can I access the video shape/ dimensions?
You can pass a callback to the onLoad prop, which will receive the naturalSize of the video. Example:
<Video
onLoad={({ naturalSize }) => {
console.log(naturalSize.width, naturalSize.height);
})}
...
The callback has a lot more info if you need it - see more in the docs.

FlatList jumping to top of list when onEndReached called

I have a FlatList that fetches a list of jobs from the API. When the end of the list is reached on scrolling, the next set of jobs is fetched from the API and appended to the job list.
The following is the code for FlatList
<View style={localStyles.container}>
<FlatList
data={jobList.jobs}
renderItem={renderJobList}
keyExtractor={item => "" + item.jid}
onEndReachedThreshold={0.2}
onRefresh={() => { getJobsList(true) }}
refreshing={fetchingStatus}
extraData={jobList.jobs, fetchingStatus, savedIds, stateChanged}
ListFooterComponent={<ProgressIndicator inProgress={fetchingStatus} />}
onEndReached={() => {
getJobsList(false);
}} />
</View>
jobList, fetchingStatus, savedIds, stateChanged - these 4 are state variables
In the JobsListClass, the following is the code for appending the data -
request.processRequest().then((value) => {
this.jobs = this.jobs.concat(value.jarr)
...
this.notify();
}).catch((error) => {
console.log("campus err", error)
...
this.notify();
});
Have tried Array.prototype.push.apply(this.jobs, value.jarr); instead of jobs.concat in the above code but did not help.
I can‘t see what exactly cause the jumping, I would need more code to determine where this happen.
Take a look at the infinite scrolling expo snack

How to make a flat list scroll Infinitely in React Native With a Finite Amount of data in Array

I have flat list horizontally set
with data of 11 items coming from an array, which is fixed and never changes
what I want is when user reaches at the end of flat list while scrolling, the data should remain the same but the first item should
show up in the last and then so on
here is what I have tried so far
<FlatList
{...this.props}
ref={ref => {
this.infListRef = ref;
}}
data={this.props.data}
onScrollEndDrag={this.handleScroll}
initialScrollIndex={0}
scrollEventThrottle={16}
renderItem={this.props.renderItem}
onScroll={({nativeEvent}) => this.checkScroll(nativeEvent)}
horizontal
showsHorizontalScrollIndicator={false}
keyExtractor={item => item.id}
/>
Any help will be highly appreciated.
Basically, implementing onScroll usage is when you want to be noticed when the actually scroll related to the scroll position (aminations for instance). When you would like to be notified when the user reaches, or about to reach, to the end of the FlatList.
You should implement onEndReached and onEndReachedThreshold to handle a better user experience when the user reaches the threshold.
The new data you're getting from the source (server or no matter wherefrom) should be concatenated to existing this.props.data
See good blog post - https://scotch.io/tutorials/implementing-an-infinite-scroll-list-in-react-native
And this SO answers - React Native Infinite Scroll
My solution refers to pagination because infinite scroll is a private case of pagination, it's the exact same approach.
If you want image or video list
One other approach which is kind a hack and an easy one is using react-native-snap-carousel
<Carousel
ref={ (c) => { this._carousel = c; } }
data={this.state.data}
renderItem={this._renderItem.bind(this)}
onSnapToItem={this.handleSnapToItem.bind(this)}
sliderWidth={360}
itemWidth={256}
layout={'default'}
firstItem={0}
itemHeight={20}
sliderHeight={20}
loop
vertical
loopClonesPerSide={100}
/>
Example:
https://snack.expo.io/#kurtesy/react-native-snap-carousel-example
You can achieve this using onEndReached method of Flatlist.
This is the idea behind answer.
state = {
data: [] //your initial data
}
<Flatlist
{…this.props}
extraData={this.state}
onEndReached = {() => {
this.setState((prevState) =>{
data: […prevState,this.state.data]
)}}
/>

React-Native Video autoplay code not working

My requirement is when the page loads the video should be start playing from the local storage and but it doesnt play at all.
Initially the state paused:true , and when the video loads i tried to change the state to false , but the video doesnt play automatically.
<Video
onEnd={this.handleEnd}
onLoad={this.handleLoad}
onProgress={this.handleProgress}
autoplay={true}
paused={this.state.paused}
ref={ref=> {
this.player = ref;
}}
resizeMode="cover"
source={{uri:this.state.v_url}}
volume={this.state.muted==true?0.0:1.0}
muted={this.state.muted}
/>
handleLoad = (meta) => {
console.log('Its working',this.props)
this.setState({
duration:meta.duration,
paused:false,
})
Use #coffeebeanslabs/react-native-inviewport to detect whether your component is in your device viewport:
Install using: npm i #coffeebeanslabs/react-native-inviewport
then do the following in your code:
import InViewPort from "#coffeebeanslabs/react-native-inviewport";
checkVideoVisible(isVideoVisible) {
this.setState({videoVisible: isVideoVisible});
}
<InViewPort onChange={(isVideoVisible) => this.checkVideoVisible(isVideoVisible)}>
<Video
paused={!this.state.videoVisible}
/>
</InViewPort>

In react-native-video how can you disable the seek function?

I am trying to disable the seek function on react native video. I have a full video that I want to preview for 30 seconds. In order to do this I want to disable the seek button so a user cannot skip through the video.
I have tried giving onSeek the value of function that exits the video player however this does not seem to do anything.
if(!loading) {
return <Video source={{uri: uri}} // Can be a URL or a local file.
onFullscreenPlayerDidDismiss={this.onDismiss}
preferredPeakBitrate={this.state.preferredPeakBitrate}
ref={(player) => {
if(!this.state.playing && player) {
player.presentFullscreenPlayer()
this.setState({ playing: true })
}
}} // Store reference
rate={1.0} // 0 is paused, 1 is normal.
volume={1.0} // 0 is muted, 1 is normal.
muted={false} // Mutes the audio entirely.
paused={false} // Pauses playback entirely.
resizeMode="cover" // Fill the whole screen at aspect ratio.*
repeat={false} // Repeat forever.
playInBackground={true} // Audio continues to play when app entering background.
playWhenInactive={true} // [iOS] Video continues to play when control or notification center are shown.
ignoreSilentSwitch={"ignore"} // [iOS] ignore | obey - When 'ignore', audio will still play with the iOS hard silent switch set to silent. When 'obey', audio will toggle with the switch. When not specified, will inherit audio settings as usual.
progressUpdateInterval={PROGRESS_MILLISECONDS} // [iOS] Interval to fire onProgress (default to ~250ms)
onError={this.onVideoError} // Callback when video cannot be loaded
onProgress={this.onProgress}
onLoadStart={this.onStart}
onEnd={this.stopPlaybackPing}
/>
} else {
return <View />
}
}
Short answer: No, you can't.
You called presentFullscreenPlayer() to play the video, unfortunately, you can't disable any buttons on the player. Because that's the default player made by Apple if you're running your app on iPhone, not by the people who created react-native-video, and I don't believe there's any public API that allows you to do so.
What you can do, however, is to write your own full screen player, with any button you want/don't want on there. Here's some hint:
Create a custom component called CustomVideo, which takes the url of the video as a prop:
// CustomVideo.js file
import React, { PureComponent } from 'react';
import { ... } from 'react-native';
import Video from 'react-native-video';
export class CustomVideo extends PureComponent {
constructor(props) {
super(props)
this.state = {
// Have any state you want here, for example
paused: false,
played: 0,
duration: 0,
isFullscreen: false
}
}
render() {
const { url } = this.props;
const { paused, played, duration, isFullscreen } = this.state;
return(
<View style={{ ... }}>
<Video
source={{ uri: url }}
...
/>
// =======> Here, you add your custom buttons <=======
// Suppose you want a pause/play button
<TouchableOpacity onPress={this.toggleVideo}>
<Text>{paused ? "Play" : "Pause"}</Text>
</TouchableOpacity>
// If you want a progress indicator, which users
// can use to skip videos, then use `Slider` component
<Slider
value={...}
step={...}
onValueChange={(value) => ...}
/>
// Here, you toggle whether you want to play the video
// in full screen mode, if so, render it in a modal
// Also, add a full screen toggle button to the video
// the same way you add a play/pause button
<Modal visible={isFullscreen}>
<View>
<Video ... />
</View>
</Modal>
</View>
);
}
}
So, next time, when you want render a video, instead of calling <Video source={{ uri: '...' }} />, you can call your <CustomVideo url='https://....' /> component.