I am trying to open a modal from another component.
this is in my parent component:
const [modalVisible, setModalVisible] = useState(false);
<TouchableOpacity
style={styles.gateBtn}
onPress={() => {
setModalVisible(true);
}}
>
<Text style={styles.gateBtnText}>Show Modal</Text>
<OpenModal isModalVisible={modalVisible} />
</TouchableOpacity>
and this is my OpenModal.js
import React, { useState } from "react";
import {
StyleSheet,
View,
Text,
Alert,
Modal,
TouchableHighlight,
} from "react-native";
function OpenModal(props) {
const [modalVisible, setModalVisible] = useState(false);
return (
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: "#2196F3" }}
onPress={() => {
setModalVisible(!modalVisible);
}}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
);
}
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22,
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
openButton: {
backgroundColor: "#F194FF",
borderRadius: 20,
padding: 10,
elevation: 2,
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center",
},
modalText: {
marginBottom: 15,
textAlign: "center",
},
});
export default OpenModal;
however It seems like I am doing something wrong,
I am trying to pass modalVisible to OpenModal by using isModalVisible={modalVisible} and modalVisible is already defined as false, when clicking on the button it becomes true, but in my OpenModal component It seems like its undefined, and it doesnt open the modal at all. What am I missing here?
you need to pass in the setModalVision, then use the props.modalVisible from the parent component.
in parent
<OpenModal isModalVisible={modalVisible} setModalVisible={setModalVisible} />
child component
function OpenModal(props) {
return (
<Modal
animationType="slide"
transparent={true}
visible={props.isModalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: "#2196F3" }}
onPress={() => {
props.setModalVisible(!props.isModalVisible);
}}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
);
}
Related
I have an image in each TouchableOpacity and I would like to change the picture in every onPress function so she could looked like shes pressed in (for example: remove the color from to picture and changes it to black and white or make a light gray shadow on the picture ).
and Reverse (when you click shes changing back to the original picture (Press:true/false).
I have a stateless Component and no class.
My Component :
export default function Recipie({ navigation, route }) {
const recipies = GetRecipies();
return (
<View style={{ flexGrow: 1, flex: 1 }}>
<ScrollView>
{recipies.map((u, i) => {
return (
<View key={i}>
<Text
onPress={navigation.navigate}
style={{
fontSize: 25,
fontFamily: "Cochin",
textAlign: "center",
}}
>
{u._recipieName}
</Text>
<TouchableOpacity
onPress={() => {
navigation.navigate("SingleRecipieScreen", { u });
}}
>
<Image
style={{
height: 200,
width: 350,
borderRadius: 80,
alignSelf: "center",
}}
source={{ uri: u._imgUrl }}
/>
</TouchableOpacity>
<Text
style={{
fontSize: 17,
fontFamily: "Cochin",
textAlign: "center",
}}
>
{u._recipieDescription}
</Text>
<TouchableOpacity
style={{ flex: 1, flexDirection: "column", flexGrow: 1 }}
>
{Show(u._preparationTime)}
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</View>
);
}
Try to use position absolute in View to cover button , and useState for styles, example :
import React, { useState } from "react";
import { StyleSheet, Text, TouchableOpacity, View,Image } from "react-native";
const App = () => {
const [isPressed, setIsPressed] = useState(0);
const onPress = () => setIsPressed(!isPressed);
return (
<View style={styles.container}>
<TouchableOpacity
style={styles.button}
onPress={onPress}
>
<View style={isPressed && styles.pressedButtonStyle} />
<Text> {isPressed ? "Pressed" : " Press Here"}</Text>
<Image
style={ styles.tinyLogo}
source={{
uri: 'https://reactnative.dev/img/tiny_logo.png',
}}
/>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
paddingHorizontal: 10,
},
button: {
alignItems: "center",
backgroundColor: "#DDDDDD",
},
tinyLogo: {
width: 50,
height: 50,
},
pressedButtonStyle: {
position:"absolute",
width:"100%",
height:"100%",
backgroundColor:'black',
opacity:0.6,
zIndex:100,
}
});
https://snack.expo.dev/ixeOwAg3o
I have an array of months which I am using to display months using a horizontal FlatList. I want the months to change using 2 buttons that are forward button to change the month in increasing order i.e from January to February and so on and a back button to change the month backwards i.e from January to December.
How can I make the buttons do so. Below monthName is an array that contains all the month names.
<ScrollView style={{flexGrow: 1}}>
<View style={{flex: 1, backgroundColor: '#fff', height: hp('130')}}>
<View
style={{
justifyContent: 'space-evenly',
width: wp('48'),
}}>
<FlatList
data={monthName}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
renderItem={(month, index) => (
<View>
<Months
showMonth={month.item}
id={month.id}
refer={flatRef}
/>
</View>
)}
keyExtractor={(item, index) => item.id.toString()}
horizontal
// snapToInterval={Dimensions.get('window').width}
snapToAlignment={'center'}
ref={(node) => (flatRef = node)}
/>
</View>
<View
style={{
justifyContent: 'space-evenly',
width: wp('12'),
}}>
{/* {} */}
<IonIcons.Button --> the button that makes the month increment.
name="arrow-forward"
size={25}
backgroundColor="white"
color="black"
// onPress={() => console.log('pressed')}
onPress={() => {
flatRef.scrollToIndex({index: ?});
}}
/>
</View>
</View>
</ScrollView>
try to access ref using current and it should work
this.flatRef.current.scrollToIndex({index: monthName.length > this.state.currentindex ? this.state.currentindex++ : this.state.currentindex });
import React, { useRef } from 'react';
import {
FlatList,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
import { wp } from '../../constants/scaling';
import { colors } from '../../constants/theme';
import bookingprocess from '../../data/BookingProcess';
import { textStyles } from '../../styles/textStyles';
import { RFValue } from 'react-native-responsive-fontsize';
import AntDesign from 'react-native-vector-icons/AntDesign';
const BookingProcess = ({}) => {
const flatListRef = useRef(FlatList);
const nextPress = index => {
if (index <= 2) {
flatListRef?.current?.scrollToIndex({
animated: true,
index: index + 1
});
}
};
const backPress = index => {
if (index >= 1) {
flatListRef?.current?.scrollToIndex({
animated: true,
index: index - 1
});
}
};
return (
<View
style={{
...styles.cardView,
padding: 0,
elevation: 0,
borderWidth: 1,
borderColor: '#f2f2f2',
overflow: 'hidden'
}}>
<View
style={{
padding: wp(2),
backgroundColor: colors.primaryColor
}}>
<Text
style={{
...textStyles.heading,
color: '#fff'
}}>
Booking Process
</Text>
</View>
<Text
style={{
...textStyles.mediumheading,
padding: wp(2),
paddingBottom: 0
}}>
You can reserve your parking slot in advance. Please follow
these four simple steps to book your parking slot.
</Text>
<FlatList
data={bookingprocess}
horizontal={true}
ref={flatListRef}
contentContainerStyle={{ padding: wp(2) }}
showsHorizontalScrollIndicator={false}
keyExtractor={(item, index) => item.id}
renderItem={({ item, index }) => {
return (
<View style={styles.innerCard}>
{item.image}
<View style={styles.ButtonBox}>
<TouchableOpacity
onPress={() => backPress(index)}
style={{
backgroundColor: colors.secondaryColor,
borderRadius: wp(50)
}}>
<AntDesign
name="leftcircle"
size={RFValue(25)}
color={colors.primaryColor}
/>
</TouchableOpacity>
<TouchableOpacity
onPress={() => nextPress(index)}
style={{
backgroundColor: colors.secondaryColor,
borderRadius: wp(50)
}}>
<AntDesign
name="rightcircle"
size={RFValue(25)}
color={colors.primaryColor}
/>
</TouchableOpacity>
</View>
<View style={styles.innercardHeaderView}>
<Text style={styles.headingTextNumber}>
{item.id}. {item.title}
</Text>
</View>
<Text style={styles.description}>
{item.description}
</Text>
</View>
);
}}
/>
</View>
);
};
export default BookingProcess;
const styles = StyleSheet.create({
cardView: {
backgroundColor: colors.white,
margin: wp(2),
elevation: 4,
borderRadius: wp(2),
padding: wp(2),
width: wp(94)
},
innerCard: {
margin: wp(2),
borderRadius: wp(2),
padding: wp(0),
paddingTop: 0,
paddingHorizontal: 0,
overflow: 'hidden',
width: wp(90),
elevation: 5,
marginLeft: 0,
padding: wp(2),
backgroundColor: '#fff'
},
ButtonBox: {
position: 'absolute',
flexDirection: 'row',
right: 0,
justifyContent: 'space-between',
width: wp(20),
padding: wp(2)
},
innercardHeaderView: {
backgroundColor: '#0000',
flexDirection: 'row',
padding: wp(2),
paddingBottom: 0,
alignItems: 'center'
},
headingTextNumber: {
...textStyles.heading,
color: colors.primaryColor,
textAlign: 'center',
alignSelf: 'center',
textAlignVertical: 'center'
},
description: {
...textStyles.mediumheading,
paddingHorizontal: wp(2),
textAlign: 'justify'
}
});
Instead of using a FlatList I would suggest you to make a state variable and execute it like this
Working example - Here
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { AntDesign } from '#expo/vector-icons';
...
const [SelectMonth, SetSelectMonth] = React.useState(monthName[0]);
const NextPress = () => {
if (SelectMonth.id !== 12) {
let temp = monthName.find((c) => c.id === SelectMonth.id + 1);
if (temp) {
SetSelectMonth(temp);
}
}
};
const PrevPress = () => {
if (SelectMonth.id !== 1) {
let temp = monthName.find((c) => c.id === SelectMonth.id - 1);
if (temp) {
SetSelectMonth(temp);
}
}
};
return (
<View style={styles.container}>
<View style={styles.CalenderBox}>
<AntDesign
name="caretleft"
size={30}
color="black"
onPress={() => PrevPress()}
/>
<View style={styles.MonthNameBox}>
<Text style={{ fontWeight: 'bold', fontSize: 24 }}>
{SelectMonth.name}
</Text>
</View>
<AntDesign
name="caretright"
size={30}
color="black"
onPress={() => NextPress()}
/>
</View>
</View>
);
I am using expo with Android Virtual Device .I am trying to mimic this animation behavior from this example, https://codepen.io/borntofrappe/pen/qwqPwq,
Here is what it looks like right now:
I use flag array to represent which button is clicked, if the certain button is clicked, I will call handleSpeedBtn function to change its corresponding flag, when the flag is true, it will provide buttonTextLayer style to this button. Right now,I am having trouble displaying the buttonTextLayer style in animation style.It applies buttonTextLayer style to the button without any animation, besides, I do not have any errors when I run the code. Just change the opacity from 0 to 1 probably would not make my app looks like the example I found on codepen, but I just want to see the animation at least. Thanks for help!
import React, { useState } from "react";
import {
Text,
StyleSheet,
View,
TouchableOpacity,
Animated,
} from "react-native";
import { MaterialCommunityIcons } from "#expo/vector-icons";
const SortTitle = ({ callBack, title }) => {
const [flag, setFlag] = useState([false, true, false]);
const opacity = useState(new Animated.Value(0))[0];
const handleSpeedBtn = (index) => {
let ary = [false, false, false];
ary[index] = ary[index] == true ? false : true;
setFlag(ary);
Animated.timing(opacity, {
toValue: 1,
duration: 2000,
useNativeDriver: true,
}).start();
};
return (
<View>
<View style={styles.titleContainer}>
<Text style={styles.titleText}>{title}</Text>
</View>
<View style={styles.btnGroupContainer}>
<View style={styles.btnContainer}>
<TouchableOpacity onPress={() => handleSpeedBtn(0)}>
<Animated.View
style={[flag[0] ? styles.buttonTextLayer : {}, opacity]}>
<MaterialCommunityIcons
name="speedometer-slow"
size={46}
color="white"
style={[flag[0] ? styles.icon : {}]}
/>
<Text style={[styles.buttonText, flag[0] ? {} : styles.hidden]}>
Slow
</Text>
</Animated.View>
</TouchableOpacity>
</View>
<View style={styles.btnContainer}>
<TouchableOpacity onPress={() => handleSpeedBtn(1)}>
<Animated.View
style={[flag[1] ? styles.buttonTextLayer : {}, opacity]}>
<MaterialCommunityIcons
name="speedometer-medium"
size={46}
color="white"
style={[flag[1] ? styles.icon : {}]}
/>
<Text style={[styles.buttonText, flag[1] ? {} : styles.hidden]}>
Medium
</Text>
</Animated.View>
</TouchableOpacity>
</View>
<View style={styles.btnContainer}>
<TouchableOpacity onPress={() => handleSpeedBtn(2)}>
<Animated.View
style={[flag[2] ? styles.buttonTextLayer : {}, opacity]}>
<MaterialCommunityIcons
name="speedometer"
size={46}
color="white"
style={[flag[2] ? styles.icon : {}]}
/>
<Text style={[styles.buttonText, flag[2] ? {} : styles.hidden]}>
Fast
</Text>
</Animated.View>
</TouchableOpacity>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
titleText: {
fontSize: 25,
color: "#000000",
fontWeight: "bold",
marginLeft: 10,
marginVertical: 5,
},
titleContainer: {
borderBottomColor: "#e3e3e3",
borderBottomWidth: 2,
},
icon: {
marginLeft: 10,
},
textDiv: {},
btnGroupContainer: {
height: 80,
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-around",
backgroundColor: "#889bf2",
},
btnContainer: {
paddingVertical: 10,
justifyContent: "space-around",
},
buttonText: {
textAlign: "center",
color: "#ffffff",
fontSize: 15,
alignSelf: "center",
flex: 1,
},
buttonTextLayer: {
width: 130,
backgroundColor: "#5c69a4",
borderRadius: 50,
flexDirection: "row",
},
hidden: {
width: 0,
height: 0,
},
});
export default SortTitle;
Working example
Link: ----> https://snack.expo.io/#msbot01/aa6537
import React, { Component } from 'react';
import { Text, View, StyleSheet, Image } from 'react-native';
import Constants from 'expo-constants';
import Icon from 'react-native-vector-icons/FontAwesome';
// You can import from local files
import AssetExample from './components/AssetExample';
import AwesomeIcon from 'react-native-vector-icons/FontAwesome';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
import Ripple from 'react-native-material-ripple';
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
tabSelected:1
};
}
onClick(e){
this.setState({
tabSelected:e
})
}
render() {
return (
<View style={{ flex: 1 }}>
<View style={{position:"absolute", bottom:0, height:50,backgroundColor:'white', width:'100%', alignItems:'center', flexDirection:'row', justifyContent:'space-around'}}>
<Ripple style={{height:'100%', width:100, justifyContent:'center', alignItems:'center'}} onPress={()=>{this.onClick(0)}}>
{this.state.tabSelected==0?
<View style={{flexDirection:'row', padding:10, borderRadius:20, alignItems:'center', backgroundColor:'#bffab6', width:'80%', justifyContent:"center", height:'70%'}}>
<Icon name="user" size={15} color="#1fdb02"/>
<Text style={{fontSize:15, paddingLeft:5, color:'#1fdb02'}}>user</Text>
</View>
:
<Icon name="user" size={15} color="#1fdb02"/>
}
</Ripple>
<Ripple style={{height:'100%', width:100, justifyContent:'center', alignItems:'center'}} onPress={()=>{this.onClick(1)}}>
{this.state.tabSelected==1?
<View style={{flexDirection:'row', padding:10, borderRadius:20, alignItems:'center', backgroundColor:'#fce29a', width:'80%', justifyContent:"center", height:'70%'}}>
<Icon name="search" size={15} color="#e6ac02"/>
<Text style={{fontSize:15, paddingLeft:5, color:'#e6ac02'}}>search</Text>
</View>
:
<Icon name="search" size={15} color="#e6ac02"/>
}
</Ripple>
<Ripple style={{height:'100%', width:100, justifyContent:'center', alignItems:'center'}} onPress={()=>{this.onClick(2)}}>
{this.state.tabSelected==2?
<View style={{flexDirection:'row', padding:10, borderRadius:20, alignItems:'center', backgroundColor:'#b6e9fa', width:'80%', justifyContent:"center", height:'70%'}}>
<Icon name="heart" size={15} color="#048dba"/>
<Text style={{fontSize:15, paddingLeft:5, color:'#048dba'}}>like</Text>
</View>
:
<Icon name="heart" size={15} color="#048dba"/>
}
</Ripple>
<Ripple style={{height:'100%', width:100, justifyContent:'center', alignItems:'center'}} onPress={()=>{this.onClick(3)}}>
{this.state.tabSelected==3?
<View style={{flexDirection:'row',padding:10, borderRadius:20, alignItems:'center', backgroundColor:'#f3b8ff', width:'80%', justifyContent:"center", height:'70%'}}>
<Icon name="share" size={15} color="#9c04ba"/>
<Text style={{fontSize:15, paddingLeft:5, color:'#9c04ba'}}>share</Text>
</View>
:
<Icon name="share" size={15} color="#9c04ba"/>
}
</Ripple>
</View>
</View>
);
}
}
I am creating a barcode scanner using React Native and Expo.
I am trying to pass a new URL to a WebView after scanning a barcode.
But I am not sure how.
Please help.
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
setModalVisible(true);
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View
style={{
flex: 1,
flexDirection: 'column'
}}>
<Modal
animationType="slide"
transparent={false}
visible={modalVisible}
onRequestClose={() => {
setScanned(false);
}}>
<View style={{ flex: 1 }}>
<WebView
style={{ flex: 1 }}
source={{ uri: 'http://domain.biz/' }}
/>
<TouchableHighlight
style={{
backgroundColor:'black',
padding: 15,
alignItems: 'center'
}}
onPress={() => {
setModalVisible(!modalVisible);
setScanned(false);
}}
underlayColor='slategray'
>
<Text style={{ color:'white', fontSize: 15 }}>Re Scan</Text>
</TouchableHighlight>
</View>
</Modal>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<View style={{ marginBottom: 100 }}>
<View style={{ alignItems: 'center', marginBottom: 5 }}>
<Image
style={{
width: 100,
height: 100,
resizeMode: 'contain',
marginBottom: 20,
}}
source={{ uri: 'http://domain.biz/img/logo_dark.png' }}
/>
<Text style={{ color: 'white', fontSize: 20, fontWeight: 'bold', paddingBottom: 10}}>
QR Code Reader v0.5
</Text>
</View>
<View
style={{
borderColor: 'white',
borderTopWidth: 5,
borderBottomWidth: 5,
borderLeftWidth: 1,
borderRightWidth: 1,
paddingVertical: 80,
paddingHorizontal: 100,
}}
/>
<View style={{ alignItems: 'center', marginTop: 5 }}>
<Text style={{ color: 'white', fontSize: 15}}>
QR Scan...
</Text>
</View>
</View>
</BarCodeScanner>
</View>
);
}
I am creating a barcode scanner using React Native and Expo.
I am trying to pass a new URL to a WebView after scanning a barcode.
But I am not sure how.
Please help.
This should do the work. I save the url from the scanner in state.uri and use that instead of a static string.
For testing purposes I used this barcode which leads to this answer:
Best, Paul
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Button, Modal, TouchableHighlight, Image } from 'react-native';
import { WebView } from 'react-native-webview';
import { BarCodeScanner } from 'expo-barcode-scanner';
export default function App(){
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(true);
const [modalVisible, setModalVisible] = useState(true);
const [uri, setUri] = useState('https://stackoverflow.com/questions/61977154/webview-uri-redirect-by-scanning-barcodes-with-react-native-expo');
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
setModalVisible(true);
// console.warn("Scan returned " + data);
setUri({ uri: data })
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View
style={{
flex: 1,
flexDirection: 'column'
}}>
<Modal
animationType="slide"
transparent={false}
visible={modalVisible}
onRequestClose={() => {
setScanned(false);
}}>
<View style={{ flex: 1 }}>
<WebView
style={{ flex: 1 }}
source={{uri: uri['uri']}}
/>
<TouchableHighlight
style={{
backgroundColor:'black',
padding: 15,
alignItems: 'center'
}}
onPress={() => {
setModalVisible(!modalVisible);
setScanned(false);
}}
underlayColor='slategray'
>
<Text style={{ color:'white', fontSize: 15 }}>Re Scan</Text>
</TouchableHighlight>
</View>
</Modal>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<View style={{ marginBottom: 100 }}>
<View style={{ alignItems: 'center', marginBottom: 5 }}>
<Image
style={{
width: 100,
height: 100,
resizeMode: 'contain',
marginBottom: 20,
}}
source={{ uri: 'http://domain.biz/img/logo_dark.png' }}
/>
<Text style={{ color: 'white', fontSize: 20, fontWeight: 'bold', paddingBottom: 10}}>
QR Code Reader v0.5
</Text>
</View>
<View
style={{
borderColor: 'white',
borderTopWidth: 5,
borderBottomWidth: 5,
borderLeftWidth: 1,
borderRightWidth: 1,
paddingVertical: 80,
paddingHorizontal: 100,
}}
/>
<View style={{ alignItems: 'center', marginTop: 5 }}>
<Text style={{ color: 'white', fontSize: 15}}>
QR Scan...
</Text>
</View>
</View>
</BarCodeScanner>
</View>
);
}
Here it is, but I have passed the data from the other page name:index.js.
You can use the linking component to open every URL passed through {data}
import React from "react";
import { View, Text, Linking, TouchableOpacity } from "react-native";
const detail = ({ route, navigation }) => {
const data = route.params;
const [uri, setUri] = React.useState({});
return (
<View>
<TouchableOpacity onPress={() => Linking.openURL(data)}>
<Text>{data}</Text>
</TouchableOpacity>
</View>
);
};
export default detail;
I have created a generic button which I'd like to have round edges instead of being a square. My button component is as such:
const Button = ({ onPress, children }) => {
const { buttonStyle, textStyle } = styles;
return (
<TouchableOpacity onPress={onPress} style={buttonStyle}>
<Text style={textStyle}>
{children}
</Text>
</TouchableOpacity>
);
};
const styles = {
textStyle: {
alignSelf: 'center',
color: colors.primaryTeal,
fontSize: 16,
fontWeight: '600',
paddingTop: 10,
paddingBottom: 10,
},
buttonStyle: {
flex: 1,
backgroundColor: colors.whiteText,
marginLeft: 5,
marginRight: 5,
borderRadius: 50
}
};
However, it remains to be square and doesn't respond to borderRadius at all.
It's invoked as such:
<Button onPress={this.onButtonPress.bind(this)}>
Log in
</Button>
How do I make it respect borderRadius and get round edges?
The login form in which it appears(Render)
render() {
return (
<Card>
<CardSection>
<Input
placeholder="user#gmail.com"
label="Email"
value={this.state.email}
onChangeText={email => this.setState({ email })}
/>
</CardSection>
<CardSection>
<Input
secureTextEntry
placeholder="password"
label="Password"
value={this.state.password}
onChangeText={password => this.setState({ password })}
/>
</CardSection>
<View style={styles.btnWrapper}>
<CardSection>
{this.state.loading ?
<Spinner size="small" /> :
<Button onPress={this.onButtonPress.bind(this)}>
Log in
</Button>}
</CardSection>
</View>
<Text style={styles.errorTextStyle} disabled={this.state.error !== null}>
{this.state.error}
</Text>
</Card>
CardSection component:
const CardSection = (props) => {
return (
<View style={styles.containerStyle}>
{props.children}
</View>
);
};
const styles = {
containerStyle: {
borderBottomWidth: 1,
padding: 5,
backgroundColor: '#fff',
justifyContent: 'flex-start',
flexDirection: 'row',
borderColor: '#ddd',
position: 'relative'
}
};
Works perfectly fine. Just make sure to use react native's StyleSheet.create to get cached styles.
Maybe your button container view background is white and you're not seeing the rounded corners.
Heres my working snack
Code snippet i used, but refer to the snack as you'll see it live in action.
import React, { Component } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
const Button = ({ onPress, children }) => {
return (
<TouchableOpacity onPress={onPress} style={styles.buttonStyle}>
<Text style={styles.textStyle}>
{children}
</Text>
</TouchableOpacity>
);
};
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Button>
Log in
</Button>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1,
backgroundColor: 'black',
},
textStyle: {
alignSelf: 'center',
color: 'teal',
fontSize: 16,
fontWeight: '600',
paddingTop: 10,
paddingBottom: 10,
},
buttonStyle: {
flex: 1,
backgroundColor: 'white',
marginLeft: 5,
marginRight: 5,
borderRadius: 50
},
});
You have to add style overflow: hidden to TouchableOpacity
Try add attribute borderWidth and borderColor on buttonStyle, like below:
buttonStyle: {
backgroundColor: colors.whiteText,
marginLeft: 5,
marginRight: 5,
borderRadius: 50,
borderWidth: 2,
borderColor: "#3b5998"
}
A complete example:
<TouchableOpacity
onPress={() => handleSubmit()}
disabled={!isValid}
style={{
alignSelf: "center",
marginBottom: 30,
overflow: 'hidden',
borderColor: "#3b5998",
borderWidth: 2,
borderRadius: 100,
}}
>
<View
style={{
flexDirection: "row",
alignSelf: "center",
paddingLeft: 15,
paddingRight: 15,
minHeight: 40,
alignItems: 'center',
}}
>
<Text style={{ fontSize: 20, fontWeight: "bold", color: "#3b5998" }}>
SEND
</Text>
</View>
</TouchableOpacity>
I think you might be looking for the containerStyle prop
<TouchableOpacity containerStyle={ViewStyleProps}>