Playing of a video blo - react-native

The next program in React-Native allows a video to play but blocks the clicking on the button. I believe this is because of the position:absolute value but is there a way to avoid this problem?
import React, { Component } from 'react';
import Video from 'react-native-video';
import {
StyleSheet,
TouchableOpacity,
Text,
View,
Button,
} from 'react-native'
class App extends Component {
state = {
count: 0,
message: 'Hello Everybody'
}
onPress = () => {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<View style={styles.container}>
<Button title={'Press me'}
onPress={() => {
console.log('Boton Presionado')
this.setState({message: 'Presiono'})
}}
/>
<Text>{this.state.message}</Text>
<Video source={{uri: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'}}
ref={(ref) => {
this.player = ref
}} // Store reference
onBuffer={this.onBuffer} // Callback when remote video is buffering
onError={this.videoError} // Callback when video cannot be loaded
style={styles.backgroundVideo}
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
marginBottom: '10'
},
backgroundVideo: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
}
})
export default App;

I changed position: 'absolute' to position: 'relative' and added values for height and width.

Related

Unable to play two videos side by side in separate containers, how can I fix this? When I comment out one video, the other appears and plays

This code is to render to my Post page which is the next block of code
import React from "react";
import { View } from "react-native";
import Post from "../../components/Post";
const Home = () => {
return (
<View>
<Post />
</View>
);
};
export default Home;
This code is the Post page where I have having to comment out one video to play the other. When I uncomment both videos only the top one plays (leftContainer)
import React from "react";
import { View } from "react-native";
import Video from "react-native-video";
import styles from "./styles";
const Post = () => {
return (
<View>
{/* <View style={styles.leftContainer}>
<Video
source={{uri: 'https://static.videezy.com/system/resources/previews/000/008/292/original/Young_African_American_Woman_Headphones_2.mp4'}}
style={styles.video}
resizeMode={'cover'}/>
</View> */}
<View style={styles.rightContainer}>
<Video
source={{
uri: "https://static.videezy.com/system/resources/previews/000/008/444/original/Dark_Haired_Girl_in_deep_thought_1.mp4",
}}
style={styles.video}
resizeMode={"cover"}
/>
</View>
</View>
);
};
export default Post;
Here is the stylesheet where I have setup a leftContainer and rightContainer for each video respectively:
import { StyleSheet, Dimensions } from "react-native";
const styles = StyleSheet.create({
leftContainer: {
width: "50%",
height: Dimensions.get("window").height,
flexDirection: "row",
},
rightContainer: {
width: "50%",
height: Dimensions.get("window").height,
flexDirection: "row",
marginLeft: "50%",
},
video: {
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0,
flexDirection: "row",
},
});
export default styles;
videoContainer: {
flexDirection: 'row',
},
leftContainer: {
width:'50%',
height: Dimensions.get('window').height,
flex: 1,
},
rightContainer: {
width:'50%',
height: Dimensions.get('window').height,
flex: 1,
},

How do I make TouchableOpacity only clickable within its shape on mobile?

On web, shaping a TouchableOpacity makes it so only the shape is clickable, however on mobile the entire "box" surrounding the shape is clickable. Is there any way at all to make it so just the shape is clickable?
I have tried shaping the view and setting the style on both View and TouchableOpacity to overflow: 'hidden' but this also fails to contain the area which is touchable.
import React, { Component } from 'react';
import { StyleSheet, TouchableOpacity, Text, View } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
onPress = () => {
this.setState({
count: this.state.count + 1,
});
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity style={styles.button} onPress={this.onPress}>
<Text> Touch Here </Text>
</TouchableOpacity>
<View style={[styles.countContainer]}>
<Text style={[styles.countText]}>
{this.state.count !== 0 ? this.state.count : null}
</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 10,
overflow: 'hidden',
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
borderRadius: 640,
height: 320,
width: 320,
overflow: 'hidden',
},
countContainer: {
alignItems: 'center',
padding: 10,
},
countText: {
color: '#FF00FF',
},
});
Here's a snack example of my problem

Make a background Image disappear from button on button click, TouchableWithoutFeedback - React Native?

I have created an extremely large button with a giraffe head and a blue sky with clouds behind. I am wondering how when you click on the giraffe head you can make the image (sky behind) disappear and then reappear when you click the giraffe again. I need lots of these buttons so I have tried to make a reusable button component.
I made a Stack of the Components.
https://snack.expo.io/#tamsynjennifer/custom-button
Otherwise this is the code:
REUSABLE BUTTON.JS
import React from 'react';
import { View, StyleSheet, Image, TouchableWithoutFeedback } from 'react-native';
const Button = ({ backgroundImage, mainImage, onPress }) => (
<View style={styles.container}>
<Image
style={styles.bgImage}
source={backgroundImage}
resizeMode={'contain'}
/>
<TouchableWithoutFeedback
onPress={onPress}
style={styles.button}
>
<Image
style={styles.image}
source={mainImage}
resizeMode={'contain'}
/>
</TouchableWithoutFeedback>
</View>
);
const styles = StyleSheet.create({
container: {
height: 250,
width: 250,
justifyContent: 'center',
alignItems: 'center',
marginTop: 0,
},
button: {
height: 200,
width: 200
},
bgImage: {
alignSelf: 'center',
justifyContent: 'center',
position: 'absolute',
height: 250,
width: 250,
},
image: {
alignSelf: 'center',
justifyContent: 'center',
position: 'absolute',
height: 200,
width: 200
},
});
export default Button;
APP.JS
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Constants } from 'expo';
const bgImage = require("./assets/BgImage.png");
const mainImage = require("./assets/MainImage.png");
import Button from './Button';
class App extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.button}>
<Button
backgroundImage={bgImage}
mainImage={mainImage}
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
height: 300,
width: 300,
justifyContent: 'center',
alignItems: 'center'
},
button: {
height: 250,
width: 250,
alignSelf: 'center',
position: 'absolute'
},
});
export default App;
This is how you can do it, I have fixed your code. Firstly you need to setState and change state onPress, so that the component re-render and change the image. Simply replace your class with this.
Expo Link
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Constants } from 'expo';
const bgImage = require("./assets/BgImage.png");
const mainImage = require("./assets/MainImage.png");
import Button from './Button';
class App extends Component {
constructor(props){
super(props)
this.state = {
imageVisibility: true,
backgroundImagePath: require("./assets/BgImage.png")
}
}
render() {
return (
<View style={styles.container}>
<View style={styles.button}>
<Button
backgroundImage={this.state.backgroundImagePath}
mainImage={mainImage}
onPress= {() => {this.changeImgaeVisibility()}}
/>
</View>
</View>
);
}
changeImgaeVisibility = () => {
if(this.state.imageVisibility){
this.setState({imageVisibility: false, backgroundImagePath: null})
}else{
this.setState({imageVisibility: true, backgroundImagePath: require("./assets/BgImage.png")})
}
}
}
const styles = StyleSheet.create({
container: {
height: 300,
width: 300,
justifyContent: 'center',
alignItems: 'center'
},
button: {
height: 250,
width: 250,
alignSelf: 'center',
position: 'absolute'
},
});
export default App;
You can add a function as a javascript object to your JSX to render the background image, this method will return the object that you need to render, as you can see in the example bellow:
const handleBackgroundImg = (imageBg, backgroundiImage) => {
if (imageBg === true) {
return <Image style={styles.bgImage} source={backgroundImage} resizeMode={'contain'}/>
}
return <Image />;
};
To add this function to your JSX code you have to change it like this:
const Button = ({ backgroundImage, mainImage, onPress, imageBg }) => (
<View style={styles.container}>
{handleBackgroundImg(imageBg, backgroundImage)}
<TouchableWithoutFeedback
onPress={onPress}
style={styles.button}
>
<Image
style={styles.image}
source={mainImage}
resizeMode={'contain'}
/>
</TouchableWithoutFeedback>
</View>
);
Now when you use this component you have to pass the imageBg boolean as well, considering true when you want to show the bg and false when you want to hide it. See the code below:
<Button
backgroundImage={bgImage}
mainImage={mainImage}
imageBg={true}
/>
If you have any doubt, ask here again and I can help you.

Image becoming transparent when placed within view

My app has a background image which has a slightly transparent view placed over it to provide a blue tint to the background image. I am now trying to place the app logo on top of these views but when I do so the logo appears to take on the opacity of the view providing the tint.
I am very new to react native but what I basically need is to have: background image > view > logo.
To demonstrate what I mean, the app logo should look like this:
But it currently looks washed out, like this:
App.js
import React, { Component } from 'react';
import { View, Text, ImageBackground } from 'react-native';
import Logo from './Logo';
class App extends Component {
render() {
return (
<ImageBackground
source={require('./images/city.png')}
style={styles.backgroundStyle}
>
<View style={styles.backgroundOverlayStyle}>
<Logo />
</View>
</ImageBackground>
);
}
}
const styles = {
backgroundStyle: {
flex: 1,
backgroundColor: '#000000',
width: '100%',
height: '100%'
},
backgroundOverlayStyle: {
flex: 1,
backgroundColor: '#003284',
opacity: 0.5
}
};
export default App;
Logo.js
import React from 'react';
import { View, Image } from 'react-native';
const Logo = () => {
const { logoStyle } = styles;
return (
<View style={styles.container}>
<Image style={logoStyle} source={require('./images/request-first-logo-white.png')} />
</View>
);
};
const styles = {
container: {
alignItems: 'center',
justifyContent: 'center',
opacity: 1,
},
logoStyle: {
width: '70%',
height: '65%',
resizeMode: 'contain',
//backgroundColor: 'blue'
}
};
export default Logo;
Thank you for any help.
you need you define blurRadius for ImageBackground
import React, { Component } from 'react';
import { View, Text, ImageBackground,Image } from 'react-native';
const Logo = () => {
const { logoStyle } = styles;
return (
<View style={styles.container}>
<Image style={logoStyle} source={{uri:'https://www.what-dog.net/Images/faces2/scroll001.jpg'}} />
</View>
);
};
export default class App extends Component {
render() {
return (
<ImageBackground
source={{uri : 'https://pngstocks.com/wp-content/uploads/2018/03/cb-background-10.jpeg'}}
style={styles.backgroundStyle}
blurRadius={30}
>
<Logo />
</ImageBackground>
);
}
}
const styles = {
backgroundStyle: {
flex: 1,
backgroundColor: '#000000',
width: '100%',
height: '100%'
},
backgroundOverlayStyle: {
flex: 1,
backgroundColor: '#003284',
},
container: {
alignItems: 'center',
justifyContent: 'center',
},
logoStyle: {
width: 100,
height: 100,
resizeMode: 'contain',
//backgroundColor: 'blue'
}
};

Saving Data And Sending To Another Class In React Native

I have a little problem with an app that I am working on. I have to make something like a note app. There for I have a button that navigates me to another screen where I can write the note and I have a save button that should send me back to the previews screen and the scrollview shold be updated
Here is what I've tried so far:
App.js:
import React, { Component } from 'react';
import Main from './app/components/Main.js';
import NoteBody from './app/components/NoteBody.js';
import {StackNavigator} from 'react-navigation'
const App = StackNavigator({Home: {screen: Main}, WriteNote: {screen: NoteBody}});
export default App;
Main.js:
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
TextInput,
ScrollView,
TouchableOpacity,
AsyncStorage,
} from 'react-native';
import Note from './Note';
import NoteBody from './NoteBody.js';
export default class Main extends Component {
static navigationOptions = {
title: 'Notes',
};
constructor(props){
super(props);
this.state = {
noteArray: [],
noteText: '',
};
}
componentDidMount(){
this.getSavedNotes(this.state.noteArray);
}
render() {
let notes = this.state.noteArray.map((val, key)=>{
return <Note key={key} keyval={key} val={val}
deleteMethod={()=>this.deleteNote(key)}/>
});
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<ScrollView style={styles.scrollViewContainer}>
<ScrollView style={styles.scrollContainer}>
{notes}
</ScrollView>
<TouchableOpacity onPress={() =>
navigate('WriteNote' ,{onNavigateBack:
this.handleOnNavigateBack.bind(this)})}
style={styles.addButton}>
<Text style={styles.addButtonText}>+</Text>
<Text style={styles.addButtonAditionalText}>Add note</Text>
</TouchableOpacity>
</ScrollView>
</View>
);
}
deleteNote(key){
this.state.noteArray.splice(key, 1);
this.setState({noteArray: this.state.noteArray});
AsyncStorage.setItem('arr', JSON.stringify(this.state.noteArray));
// alert(this.state.noteArray);
}
getSavedNotes = async (noteArray) =>{
try{
let data = await AsyncStorage.getItem('arr');
if(JSON.parse(data))
{
this.setState({noteArray: JSON.parse(data)});
}
}catch(error){
alert(error);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollContainer: {
flex: 1,
},
addButton: {
position: 'relative',
zIndex: 11,
left: 0,
top: 0,
alignItems: 'flex-start',
justifyContent: 'flex-end',
width: 100,
height: 60,
elevation: 8
},
addButtonText: {
color: '#000',
fontSize: 60,
},
addButtonAditionalText: {
color: '#000',
fontSize: 12,
marginLeft: 40,
position: 'absolute',
bottom: 20,
},
scrollViewContainer: {
flex: 1,
marginBottom: 70,
}
});
Note.js: Here we have the scrollview and the button that navigates you to the NoteBody screen.
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
} from 'react-native';
export default class Note extends Component {
render() {
return (
<View key={this.props.keyval} style={styles.note}>
<Text style={styles.noteText}>{this.props.val.date}</Text>
<Text style={styles.noteText}>{this.props.val.note}</Text>
<TouchableOpacity onPress={this.props.deleteMethod} style={styles.noteDelete}>
<Text style={styles.noteDeleteText}>Del</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
note: {
position: 'relative',
padding: 20,
paddingRight: 100,
borderBottomWidth:2,
borderBottomColor: '#ededed'
},
noteText: {
paddingLeft: 20,
borderLeftWidth: 10,
borderLeftColor: '#0000FF'
},
noteDelete: {
position: 'absolute',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#2980b9',
padding: 10,
top: 10,
bottom: 10,
right: 10
},
noteDeleteText: {
color: 'white'
}
});
and finally NoteBody: Here is where you can write the body of the note and you have that save button that should also save the data in an AsyncStorage so I can display it even after the app is closed.
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
TextInput,
TouchableOpacity,
AsyncStorage,
} from 'react-native';
import Note from './Note.js';
export default class NoteBody extends Component {
static navigationOptions = {
title: 'Note',
};
constructor(props){
super(props);
this.state = {
noteArray: [],
noteText: '',
};
}
componentDidMount(){
this.getSavedNotes(this.state.noteArray);
}
render() {
let notes = this.state.noteArray.map((val, key)=>{
return <Note key={key} keyval={key} val={val}
deleteMethod={()=>this.deleteNote(key)}/>
});
return (
<View style={styles.container}>
<View style={styles.noteBody}>
<TextInput
multiline = {true}
numberOfLines = {1000000}
style={styles.textInput}
placeholder='Write your note here'
onChangeText={(noteText)=> this.setState({noteText})}
value={this.state.noteText}
placeholderTextColor='grey'
underlineColorAndroid='transparent'>
</TextInput>
</View>
<TouchableOpacity onPress={ this.addNote.bind(this) } style={styles.addButton}>
<Text style={styles.addButtonText}>SAVE</Text>
</TouchableOpacity>
</View>
);
}
addNote(){
const { navigate } = this.props.navigation;
if(this.state.noteText){
var d = new Date();
this.state.noteArray.push({
'date':d.getFullYear()+
"/"+(d.getMonth()+1) +
"/"+ d.getDate(),
'note': this.state.noteText
});
this.setState({ noteArray: this.state.noteArray });
this.setState({noteText:''});
AsyncStorage.setItem('arr', JSON.stringify(this.state.noteArray));
this.props.navigation.state.params.onNavigateBack();
navigate('Home');
// alert(this.state.noteArray);
}
}
getSavedNotes = async (noteArray) =>{
try{
let data = await AsyncStorage.getItem('arr');
if(JSON.parse(data))
{
this.setState({noteArray: JSON.parse(data)});
}
}catch(error){
alert(error);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
noteBody:{
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
zIndex: 10,
alignItems: 'center',
borderBottomWidth:1,
borderTopColor: '#000',
marginBottom: 100,
},
textInput: {
alignSelf: 'stretch',
textAlignVertical: 'top',
backgroundColor: '#fff',
color: '#000',
padding: 20,
borderTopWidth:2,
borderTopColor: '#ededed',
},
addButton: {
position: 'absolute',
zIndex: 11,
left: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center',
width: 300,
backgroundColor: '#00FF00',
height: 60,
elevation: 8
},
addButtonText: {
color: '#fff',
fontSize: 24,
},
});
The save button only saves the last note I wrote and it doesn't even show it on the scrollview immediately. I have to reopen the app to display it.
There are a couple of things which are wrong here:
First you only fetch the saved notes in the constructor of your Main component, which only gets called on instantiation. The recommended place to put this code is in componentDidMount(). Also I don't understand why you are are passing the noteArray state to your getSavedNotes() method.
Next, and this is an important one: your methods to add and delete notes from the array are mutating (splice and push). Since React uses shallow comparison to determine when to re-render, you need to create a new object when using setState(). So for additions you could use concat() and for deletions the omit() function of Lodash is very useful. Alternatively you could use the spread operator.
Disclaimer: I haven't yet read all of your code in detail, so there might still be some additional problems.
Edit: with FlatList
// render() method of Main.js
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<ScrollView style={styles.scrollViewContainer}>
<ScrollView style={styles.scrollContainer}>
<FlatList
data={this.state.noteArray}
renderItem={({item, index}) => this.renderItem(item, index)}
keyExtractor={(item, index) => `${index}`}
/>
</ScrollView>
<TouchableOpacity onPress={() =>
navigate('WriteNote')}
style={styles.addButton}>
<Text style={styles.addButtonText}>+</Text>
<Text style={styles.addButtonAditionalText}>Add note</Text>
</TouchableOpacity>
</ScrollView>
</View>
);
}
renderItem = (item, index) => {
return (
<Note
keyval={index}
val={item}
deleteMethod={()=>this.deleteNote(index)}
/>
);
}
It looks like you could add a listener in Main.js for 'onFocus' events. I would use the callback to query AsyncStorage and set state with the result.
Screen A
Method to do the thing in Screen A that you want to happen when navigating back from Screen B:
handleOnNavigateBack = (foo) => {
this.setState({
foo
})
}
This is the React Navigation method in Screen A to navigate to Screen B:
this.props.navigation.navigate('ScreenB', {
onNavigateBack: this.handleOnNavigateBack})
…or if your handleOnNavigateBack function is not a arrow function (which binds this) you'll need to bind this: (ht #stanica)
this.props.navigation.navigate('ScreenB', {
onNavigateBack: this.handleOnNavigateBack.bind(this)
})
Screen B
After navigating to Screen B and ready to Navigate back to Screen A…
Call the function (passed to Screen B from Screen A) to do the thing in Screen A:
this.props.navigation.state.params.onNavigateBack(this.state.foo)
Then call the React Navigation method to go Back (to Screen A):
this.props.navigation.goBack()
I also updated my question's code so it is the version that dose what is suppose to do.