Android youtube player not working react-native - javascript

Hi I'm trying to get an youtube player using react-native-youtube but I'm getting a black screen with an endless loading in android. It works well in iOS. Does someone have an idea why ?
Here is the code :
<View>
<YouTube
apiKey="APIKEY"
videoId={this.state.videoUrls} // The YouTube video ID
play = {this.state.isPlaying} // control playback of video with true/false
fullscreen = {this.state.fullscreen} // control whether the video should play in fullscreen or inline
loop = {this.state.isLooping}// control whether the video should loop when ended
onReady={e => this.setState({ isReady: true })}
onChangeState={e => this.setState({ status: e.state })}
onChangeQuality={e => this.setState({ quality: e.quality })}
onError={e => this.setState({ error: e.error })}
style={{ alignSelf: 'stretch', height: 250 }}
/>
</View>
EDIT : the code of the videoId
<View style = {styles.containerPlaylist}>
<View>
{
this.state.dataVideos.map((item,i) =>
<TouchableHighlight
key = {item.contentDetails.videoId}
onPress = {()=> this.setState({videoUrls: item.contentDetails.videoId})}>
<View style = {styles.vids}>
<Image
source = {{uri: item.snippet.thumbnails.medium.url}}
style = {{flex: 2, height: '100%', backgroundColor:'#fff', resizeMode:'contain'}}
/>
<Text style = {styles.vidText}>{item.snippet.title}</Text>
</View>
</TouchableHighlight>
)}
</View>
</View>

Related

I'm trying to display the Image after the lotti progress finished and disappeared but I couldn't in react native

Here is my code:
const Success =({navigation})=>{
useEffect(() => {
setTimeout(()=>{
<View>
<Image source={images.done}
style={{
width:100,
height:100
}}
/>
</View>
navigation.navigate('Home')
},4000)
}, [])
return(
<View style={{
flex:1,
justifyContent:'center',
alignItems:'center',
}}>
<LottieView
style={{
width: 100,
height: 60,
}}
source={images.progress}
autoPlay
/>
</View>
)
}
export default Success ;
Please Help me out How I can display first Lotti progress and then immediately I wanna the image done appears after the Lotti progress finish and disappear. so I would know how to set time for Lotti progress and then set time to display the Image done then navigate to the next page
You can make use of onAnimationFinish props in lottie-react-native library. Tell the program what you are going to do when the lottie animation end.
const Success = ({navigation}) => {
const [lottieFinished, setLottieFinished] = useState(false);
const onAnimationFinish = () => {
setLottieFinished(true);
setTimeout(() => {
//Go Back to home page after 4 seconds
navigation.navigate('Home')
}, 4000);
}
return (
<View>
{
!lottieFinished ?
<LottieView
source={images.progress}
autoPlay
loop={false}
onAnimationFinish={onAnimationFinish}
/>
:
<Image
source={images.done}
style={{height:100, width:100}}
/>
}
</View>
);
}

How to play a specific video on a React native ScrollView carousel?

I have a scrollview that has as a child an array of video components. It displays on the UI a carousel of videos. I would like the user to be able to click a play button that is above the video and play that video, but the way my logic is set, all the videos play together because the condition to play the video lives in a react useState.
see the code:
const VideosView = (props) => {
const videoClips = props.route.params.data;
const [state, setState] = React.useState(0);
const [play, setPlay] = React.useState(false);
return (
<>
<SafeAreaView pointerEvents='box-none' style={styles.root}>
<Header
goBack={() => props.navigation.goBack()}
title={state === 0 ? 'RYGGRöRLIGHET' : 'STYRKA & BALANS'}
/>
<View style={styles.paragraphsContainer}>
<Text style={styles.title}>
{state === 0 ? 'Ryggrörlighet' : 'Styrka & Balans'}
</Text>
<Text style={styles.paragraph}>
'Utför övningen i ca 5 min för bästa resultat.'
</Text>
<View style={styles.circlesContainer}>
{renderImages.map((_, index) => {
return (
<TouchableOpacity key={index} onPress={() => setState(0)}>
<View
style={[
styles.circles,
{ opacity: index === state ? 1 : 0.5 }
]}
/>
</TouchableOpacity>
);
})}
</View>
</View>
</SafeAreaView>
<View style={styles.scrollViewContainer}>
<ScrollView
bounces={false}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={30}
onScroll={({ nativeEvent }) => {
const slide = Math.ceil(
nativeEvent.contentOffset.x / nativeEvent.layoutMeasurement.width
);
if (slide !== state) {
setState(slide);
}
}}
horizontal>
{videoClips.map((video, index) => (
<View style={{ position: 'relative' }}>
{!play && (
<TouchableOpacity
style={{
position: 'absolute',
backgroundColor: 'rgba(255,255,255,0.5)',
alignSelf: 'center',
top: 130,
width: 160,
height: 160,
borderRadius: 500,
zIndex: 4000
}}
onPress={() => setPlay(true)}></TouchableOpacity>
)}
<Video
shouldPlay={play}
key={index}
source={{
uri: video
}}
resizeMode='cover'
style={{ width: wp('100%'), height: hp('100%') }}
/>
</View>
))}
</ScrollView>
</View>
</>
);
};
I would like the user to click a button and play one video, use the carousel to go to next video, click play and play the next video.
Please, help.
If you change the play state from Boolean to Number you will probably solve your problem. Here is how:
const [videoBeingDisplayedIndex, setVideoBeingDisplayedIndex] = React.useState(5);
const [play, setPlay] = React.useState(5); // If it is equals to the video id the video should play, else it should not
...
<Button onClick={() => setPlay(videoBeingDisplayedIndex)}>
Play Video
</Button>
<VideoCarousel>
{
myVideoList.map((video, index) => {
return (
<Video
content={video}
index={index}
play={play === index} // Check if the current play state is equals to the video unique id
/>
);
})
}
</VideoCarousel>
...
PS.: please, have in mind that this snippet is abstracting the react-native elements and focusing on the problem.

How to call multiple screens on one page in React Native

I have made a Home page in which there are three buttons in the header (like a tab navigator) I want something like on clicking each button a screen appears beneath the header, as shown in the image below:
Here's what I have tried:
constructor(props) {
super(props);
this.state = {
initialstate: 0, //Setting initial state for screens
};
}
render(){
return(
<View style={styles.container}>
<TouchableOpacity onPress={() => this.setState({ initialstate: 0})}>
<Image source={require('../../assets/add.png')}
resizeMode="contain"/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.setState({ cardstate: 1})}>
<Image source={require('../../assets/request.png')}
resizeMode="contain"/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.setState({ cardstate: 2})}>
<Image source={require('../../assets/send.png')}
resizeMode="contain"/>
</TouchableOpacity>
{this.state.initialstate == 0 ? ( <RequestComp/> ) : ( <TopUpComp/> ) }
//Over Here when I use the Third Screen like " : <SendComp/> " it gives me JSX error says "EXPECTED }"
</View>
Ciao, what you need seems more like a popup that appears from the bottom of the screen. I use react-native-popup-ui Toast component to do that.
Something like:
import { Root, Toast } from 'popup-ui'
...
<Root>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity
onPress={() =>
Toast.show({
title: 'User created',
text: 'Your user was successfully created, use the app now.',
color: '#2ecc71'
})
}
>
<Text>Call Toast</Text>
</TouchableOpacity>
</View>
</Root>
And the result is:
Note: I have android and the Taost is overlapped by android navigation bar but on iOS you should see all the Toast component
you are using a ternary operator ( initial ? true : false ) which can work only for two components in your case.

Show Empty list message only after Loader get ended in React Native using Flat list

I have a flat list, which gets its data source as a state. Actually, this data is from firebase, and i have been using redux. So, the data is fetched in the actions, and using callback i get the data to state.
What i want to achieve is, when there is no data found from the api, An empty list message should be show in the view. Actually , i achieved this using "ListEmptyComponent". But whats happening is the screen starts with empty message, and the spinner loads below it, and then if data found the message goes away as well as spinner.
But, what i wanted is, when the view gets rendered the first thing everyone should see is the spinner, and then if data empty spinner hides then empty list message displays.
How to achieve this ?
My Action :
export const fetchOrderHistory = (phone, callback) => {
return (dispatch) => {
dispatch({ type: START_SPINNER_ACTION_FOR_ORDER_HISTORY })
firebase.database().ref('orders/'+phone)
.on('value', snapshot => {
const snapShotValue = snapshot.val();
callback(snapShotValue);
dispatch ({ type: ORDER_HISTORY_FETCHED , payload: snapshot.val()});
dispatch({ type: STOP_SPINNER_ACTION_FRO_ORDER_HISTORY })
});
};
};
My Flat List & spinner:
<FlatList
data={this.state.historyOfOrders}
keyExtractor={item => item.uid}
ListEmptyComponent={this.onListEmpty()}
renderItem={({ item }) => (
<Card
containerStyle={{ borderRadius: 5 }}
>
<View style={styles.topContainerStyle}>
<View>
<TouchableOpacity
onPress={() => this.props.navigation.navigate('ViewOrderScreen', {itemsOfOrder: item}) }
>
<View style={styles.viewOrderContainer}>
<View style={styles.viewOrderTextContainer}>
<Text style={styles.viewOrderTextStyle}>View Order</Text>
</View>
<Icon
name='ios-arrow-forward'
type='ionicon'
color='#ff7675'
/>
</View>
</TouchableOpacity>
</View>
</View>
</View>
</Card>
)}
/>
{this.props.isSpinnerLoading &&
<View style={styles.loading}>
<ActivityIndicator size="large" color="#03A9F4"/>
</View> }
My Call back at componentWillMount which set state:
componentWillMount() {
this.props.fetchOrderHistory((this.props.phone), (snapShotValue)=> {
const userOrderHistory = _.map(snapShotValue, (val,uid) => ({uid, ...val}))
this.setState({ historyOfOrders: userOrderHistory })
});
}
My EmptyList Message:
onListEmpty = () => {
return <View style={{ alignSelf: 'center' }}>
<Text style={{ fontWeight: 'bold', fontSize: 25 }}>No Data</Text>
</View>
}
My State:
state = { historyOfOrders: "" }
I am getting the spinner values from the reducers, using mapStateToProps.
Kindly Guide me, through
you have to do two things for that.
First, show Flatlist only if the loader is stopped. Second, set default value of this.state.historyOfOrders is null and check if this.state.historyOfOrders not null then only show Flatlist.
Here is a code:
{(!this.props.isSpinnerLoading && this.state.historyOfOrders != null) ?
(
<FlatList
data={this.state.historyOfOrders}
keyExtractor={item => item.uid}
ListEmptyComponent={this.onListEmpty()}
renderItem={({ item }) => (
<Card containerStyle={{ borderRadius: 5 }}>
<View style={styles.topContainerStyle}>
<View>
<TouchableOpacity onPress={() => this.props.navigation.navigate('ViewOrderScreen', {itemsOfOrder: item}) }>
<View style={styles.viewOrderContainer}>
<View style={styles.viewOrderTextContainer}>
<Text style={styles.viewOrderTextStyle}>View Order</Text>
</View>
<Icon
name='ios-arrow-forward'
type='ionicon'
color='#ff7675'
/>
</View>
</TouchableOpacity>
</View>
</View>
</Card>
)}
/>
) : null
}
With this condition, even if you want loader above Flatlist you can do that.
The path you should take is rendering only the spinner when the loading flag is set and rendering the list when loading flag is false.
Your render method should be like below
render()
{
if(this.props.isSpinnerLoading)
{
return (<View style={styles.loading}>
<ActivityIndicator size="large" color="#03A9F4"/>
</View> );
}
return (/** Actual List code here **/);
}

React Native - iOS - Local image invisible (works on android)

I'm mapping TouchableOpacity with an Image nested inside of it. It works great on Android but on iOS the image is invisible. There is still a 75x75 touchable opacity that I can tap but the image is invisible in the modal that pops up and just in general.
How does this work?
I'm using Expo SDK FileSystem to get the path of each image.
For example: file://path/to/container/progress/myfilehash.jpg
I push this to my state and map it in the component. the require() function WILL NOT WORK for the way I am doing this. I think it is purely a problem with the rendering.
Map code:
{this.state.images.map((val, key) => (
<TouchableOpacity
key={key}
onPress={() => this.setState({active: val, modal: true})}
>
<Image
style={{width: 75, height: 75}}
source={{isStatic: true, uri: val}}
/>
</TouchableOpacity>
))}
Modal:
<Container style={Colors.Backdrop}>
<Header style={Colors.Navbar}>
<Left>
<TouchableHighlight
onPress={() => {
this.setState({modal: false})
}}>
<Icon
name="arrow-back"
style={{color: 'white'}}
/>
</TouchableHighlight>
</Left>
<Body></Body>
<Right>
<TouchableOpacity
onPress={() => {
this._deleteImage(this.state.active);
}}>
<Text
style={[
Colors.ErrorText, {
fontSize: 24,
marginRight: 10
}
]}>×</Text>
</TouchableOpacity>
</Right>
</Header>
<Content>
<View
style={{flex: 1}}
>
<FitImage
source={{uri: this.state.active}}
/>
</View>
</Content>
</Container>
Code for fetching image paths. (NOTE: I tried not truncating "file://" from ios with same exact result)
_getAllImagesInDirectory = async() => {
let dir = await FileSystem.readDirectoryAsync(FileSystem.documentDirectory + 'progress');
dir.forEach((val) => {
this.state.images.push(Platform.OS === 'ios' ? FileSystem.documentDirectory.substring(7, FileSystem.documentDirectory.length) : FileSystem.documentDirectory + 'progress/' + val);
});
await this.setState({images: this.state.images, loading: false});
}
I also faced this problem once, I solved it by pasting the image in the root folder and then used that path in the source of Image tag.

Categories