I make loading component with modal base and Loading component waiting for api calls, when there is no answer from api call I want to users press to header back button and they can continue other screen problem is modal is opening and can't pressed header back button, I tried margin or padding to modal but rn modal locking to all screen, I use react native navigation and custom header below my screen picture while openin loading component
Red component is my opening loading component and I want to pressed header left side back button and back to previous screen, rn modal locking to all screen and not pressed that while loading component is open how can I press the back button
My Loading component is;
import React from 'react';
import {View} from 'react-native';
import Modal from 'react-native-modal';
import {SkypeIndicator} from 'react-native-indicators';
export const Loading = (props) => {
return (
<Modal
animationType="none"
transparent={true}
visible={visible}
supportedOrientations={['portrait']}
onRequestClose={() => {}}>
<View
style={{
flex: 1,
backgroundColor: 'yellow',
marginTop: 150,
alignItems: 'center',
justifyContent: 'center',
}}>
<View
style={{
width: 70,
height: 70,
backgroundColor: 'blue',
borderRadius: 70,
justifyContent: 'center',
alignItems: 'center',
}}>
<SkypeIndicator color={colors[indicatorColor]} />
</View>
</View>
</Modal>
);
};
Modal will block the screen, you have to cancel the modal first before user can interact on screen. For that you may need to add a cancel/close button on the modal.
Other options are
OnBackDropPressed
OnBackButtonPressed
etc.
Reference: https://github.com/react-native-modal/react-native-modal#available-props
I don't know it make sense or not to reply now. But I got the working idea from your question(Loading Comp) itself. Simply target the onRequestClose prop of Modal like below:
import React from "react";
import { View } from "react-native";
import Modal from "react-native-modal";
import { SkypeIndicator } from "react-native-indicators";
//import useNavigation hook
import { useNavigation } from "#react-navigation/native";
export const Loading = (props) => {
//create an instance of the hook
const navigation = useNavigation();
const handleOnRequest = () => {
//Now here you can do whatever you like
navigation.goBack(); //return to the previous screen
//OR you may wish to just close the modal on backPress
//For that you may pass onBackPress prop on your Loading component
//and reverse the modal visibility like below
//<Loading onBackPress={()=>setVisible(false)}
props.onBackPress && props.onBackPress();
};
return (
<Modal
animationType="none"
transparent={true}
visible={visible}
supportedOrientations={["portrait"]}
onRequestClose={handleOnRequest}
>
<View
style={{
flex: 1,
backgroundColor: "yellow",
marginTop: 150,
alignItems: "center",
justifyContent: "center",
}}
>
<View
style={{
width: 70,
height: 70,
backgroundColor: "blue",
borderRadius: 70,
justifyContent: "center",
alignItems: "center",
}}
>
<SkypeIndicator color={colors[indicatorColor]} />
</View>
</View>
</Modal>
);
};
Related
I am trying to make a simple game/task that requires a user to tap the left button, the right button, or both at about the same time. However, it seems like React Native prevents two buttons from being pressed down at the same time.
import React, { useState } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
export default function App() {
const [leftButtonTaps, setLeftButtonTaps] = useState(0)
const [rightButtonTaps, setRightButtonTaps] = useState(0)
return (
<View style={styles.container}>
{leftButtonTaps}{" "}
{rightButtonTaps}
<TouchableOpacity onPress={() => setLeftButtonTaps((prev) => prev + 1)}>
<View style={styles.button}>Left</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => {setRightButtonTaps((prev) => prev + 1)}}>
<View style={styles.button}>Right</View>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
flexDirection: "row"
},
button: {
backgroundColor: "blue",
height: 50,
width: 100,
marginTop: 300,
color: "white",
alignItems: "center",
justifyContent: "center",
marginLeft: 10,
marginRight: 10
}
});
I have tried importing TouchableOpacity from the react native gesture handler, but the results are the same. I have tried switching the onPress event to onPressIn, and that seems to work the same.
Is there any solution to this?
Edit: I have read that panresponder can solve this problem, but I can't seem to figure out how.
import React, { useState } from "react";
import { View, Text, StyleSheet, TouchableOpacity } from "react-native";
import { BottomSheet } from "react-native-btr";
export default function BottomSheetDemo() {
const [visible, setVisible] = useState(false);
function toggle() {
setVisible((visible) => !visible);
}
return (
<View style={styles.container}>
<TouchableOpacity onPress={toggle}>
<View style={styles.button}>
<Text>Toggle BottomSheet</Text>
</View>
</TouchableOpacity>
<BottomSheet
visible={visible}
onBackButtonPress={toggle}
onBackdropPress={toggle}
>
<View style={styles.card}>
<Text>Place your custom view inside BottomSheet</Text>
</View>
</BottomSheet>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
button: {
backgroundColor: "#fff",
borderWidth: 2,
borderRadius: 50,
padding: 16,
},
card: {
backgroundColor: "#fff",
height: 250,
justifyContent: "center",
alignItems: "center",
},
});
I am using the above code. So my problem is I am getting the bottom sheet as expected. And I want that it will 100px above the bottom. That is also working fine. But the thing is I am getting bottom and at top blur black background. But I want on the bottom margin-bottom 100. It will not show that black ground. I will start from marginbottom:100. But the bottom background will be transparent and I can do click on the bottom items.
TLDR: working source code. Be aware, this solution might get
messy.
If we see the source code of react-native-btr then we will see that the BottomSheet component is actually a Modal component from react-native-modal passing 4 basic props to react-native-modal as shown below
<Modal
isVisible={visible}
onBackButtonPress={onBackButtonPress}
onBackdropPress={onBackdropPress}
style={{ justifyContent: "flex-end", margin: 0 }}
>
{children}
</Modal>
So, what I did is, extract all the source code from react-native-modal which is just five files and modify this source code. I have put a new prop for react-native-modal called bottomSpacing, so that user can change the bottom spacing.
Back in app.js the code is looking like this
<Modal
testID={"modal"}
isVisible={isModalVisible}
style={{ justifyContent: "flex-end", margin: 0 }} // this line was using in react-native-btr source
bottomSpacing={BOTTOM_SPACING}>
<View style={styles.card}>
<Text>Place your custom view inside BottomSheet</Text>
</View>
</Modal>
Here, BOTTOM_SPACING is used both in bottomSpacing props and the styles.card as following
card: {
marginBottom: BOTTOM_SPACING,
...
}
Bonus: Now you can use all the features of react-native-modal such as changing the color of the shadow and the opacity of that shadow etc.
Is there any conflict with native base and react-native-modal? I can't get my modal to display the content. I was wondering if it is because the Container tag of native base.
Code: https://snack.expo.io/rJbAI_Cxr
I've had the same issue. just remove the flex:1 from Modal style and you will end up with centered modal without any style. Then you need to set all the styles for the modal by yourself.
You can use Modal from react native component also ,no need to use third party library.
import {Modal} from 'react-native';
constructor(props) {
super(props);
this.state = {
modalVisibility: false,
};
ShowModalFunction(visible) {
this.setState({ modalVisibility: visible });
}
<Modal
transparent={true}
animationType={"slide"}
visible={this.state.modalVisibility}
onRequestClose={() => { this.ShowModalFunction(!this.state.modalVisibility) }} >
<View style={{ flex:1, justifyContent: 'center', alignItems: 'center' }}>
<View style={styles.ModalInsideView}>
<Text style={{color:'white',fontSize:14,fontWeight:'700'}}>Hello </Text>
</View>
</View>
</Modal>
const styles = StyleSheet.create({
ModalInsideView:{
justifyContent: 'center',
alignItems: 'center',
backgroundColor : "#00BCD4",
height: 245 ,
width: '90%',
borderRadius:10,
borderWidth: 1,
borderColor: '#fff'
},
});
Try this if you face issue in this ,let me know.
I have a counter state and four buttons, each button is passed the same onPress function which will increase the counter value with 1.
If I press any two different buttons alternately extremely quickly (i.e. button 2 --> button 4 --> button 2 --> button 4), the onPress function is sometimes ignore (you can see the counter value is not increasing). I expect the counter will increase when clicked.
But If I press the same buttons continuously (keep pressing button 2 quickly) the problem doesn't seems happening.
Here's a minimal example that describe the problem:
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, Image, TouchableOpacity, Dimensions } from 'react-native';
export default class TestCount extends Component {
constructor(props) {
super(props);
this.state = {
clickCount: 0,
};
}
increaseCount = () => {
this.setState(function(prevState, props){
return {
clickCount: prevState.clickCount + 1
}
})
}
render() {
const { clickCount } = this.state;
return (
<View style={styles.container}>
<View style={styles.countBoard}>
<Text style={styles.question}>{clickCount}</Text>
</View>
<View style={styles.butons}>
<TouchableOpacity style={styles.choice}>
<Text style={styles.btnText} onPress={this.increaseCount}>Button 1</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.choice}>
<Text style={styles.btnText} onPress={this.increaseCount}>Button 2</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.choice}>
<Text style={styles.btnText} onPress={this.increaseCount}>Button 3</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.choice}>
<Text style={styles.btnText} onPress={this.increaseCount}>Button 4</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const BtnWidth = Math.floor((Dimensions.get('window').width - 40) / 2);
const styles = StyleSheet.create({
container: {
flex: 1,
width: '100%',
justifyContent: 'center',
alignItems: 'center',
},
countBoard: {
height: 200,
justifyContent: 'center',
alignItems: 'center',
marginLeft: 20,
marginRight: 20,
marginBottom: 15,
},
question: {
fontSize: 40,
fontWeight: '600',
},
btnText: {
fontSize: 22,
borderColor: '#595959',
},
butons: {
width: '100%',
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center',
},
choice: {
width: BtnWidth,
height: 50,
borderWidth: 1
}
});
This is maybe not a problem with React Native, but a normal function of your phone.
In some phones that don't handle double touches, if you press in two points, it will press in "the midle" of the two points.
So when you are pressing fast, sometimes you have two touches at the same time and it will become only one in "the middle".
This happened alot with me when I'm pressing on the phone, but it doesn't work, then I realize the reason why it wasn't working is because part of my hand that is holding the phone is touching the screen, creating two points on the screen and making it click in the middle of the two points.
Found the solution and it was apparently a super minor mistake -.-, I accidentally put the onPress on the <Text> component instead of TouchableOpacity. So the button looks like frozen when I press on the area without the text.
Without touching (and by default) Touchable highlight is giving me a semi-transparent button!
<LoginButton ref={btn => { this.btn = btn; }} onPress={this._executeLoginQuery} text='Sign in'></LoginButton>
rendered in LoginButton as
render () {
const { icon} = this.props;
return (
<TouchableHighlight style={styles.button} onPress={this.props.onPress}>
<View
style={{
flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<Text style={styles.buttonText}>{this.getText()}</Text>
</View>
</TouchableHighlight>
)
}
}
with the style
button: {
height: 45,
borderRadius: 100,
marginHorizontal: Metrics.section,
marginVertical: Metrics.baseMargin,
backgroundColor: Colors.blueButton,
justifyContent: 'center',
overflow:'hidden',
opacity: 1.0,
},
Giving the result as:
And as you can see background "waves" are coming through - not just through the button but the parent white background too!
How can I stop this?
From react native docs:
The underlay comes from wrapping the child in a new View, which can affect layout, and sometimes cause unwanted visual artifacts if not used correctly, for example if the backgroundColor of the wrapped view isn't explicitly set to an opaque color.
Can you tell me whats the value of Colors.blueButton. If there is opacity in any child under TouchableHighlight then please try removing it.
2nd Way
You can use TouchableOpacity and control its opacity by using activeOpacity prop.
<TouchableOpacity activeOpacity={0.8}>
//...login Button view
</TouchableOpacity>