ReactNative - button not showing up - react-native

I'm having trouble displaying my custom component in ReactNative on Android simulator. Specifically, the appears as a flat line (height is close to 0 - see the blue line immediately below "Authentication"), when it should have some height. How do I make the button have height? See below. Thanks!
Here's my code:
App.js (the parts that are relevant towards displaying the button)
renderContent() {
return (
<Button onPress={() => firebase.auth().signOut()}>
Log Out
</Button>
);
}
render() {
return (
<View>
<Header headerText="Authentication"/>
{this.renderContent()} //button is rendered here.
</View>
);
}
Custom-defined button:
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
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: '#007aff',
fontSize: 16,
fontWeight: '600',
paddingTop: 10,
paddingBottom: 10
},
buttonStyle: {
flex: 1,
alignSelf: 'stretch',
backgroundColor: '#fff',
borderRadius: 5,
borderWidth: 1,
borderColor: '#007aff',
marginLeft: 5,
marginRight: 5
}
};
export { Button };

You should specify your custom button height.
<View>
<View>
<Header headerText="Authentication"/>
</View>
<View style={{height:50}}>
{this.renderContent()} //button is rendered here.
</View>
</View>
Or you can use ScrollView instead.
<View>
<View>
<Header headerText="Authentication"/>
</View>
<ScrollView>
{this.renderContent()} //button is rendered here.
</ScrollView>
</View>

Related

How to make TouchableOpacity image look like pressed in?

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

how to make background blur when modal open ups in reactnative

import React from 'react'
import { View, StyleSheet, Text, TouchableOpacity, Modal } from 'react-native'
const ModalContent = ({ visiblity, toggleModal }) => {
return (
<Modal animationType='slide' transparent={true} visible={visiblity} onRequestClose={() => {
toggleModal()
}} >
<View style={styles.container}>
<TouchableOpacity>
<Text style={styles.textButton}>Edit</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.textButton}>Invite</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.textButton}>Delete</Text>
</TouchableOpacity>
</View>
</Modal>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
borderTopRightRadius: 25,
borderTopLeftRadius: 25,
height: 150,
alignItems: 'center',
elevation: 10,
alignItems: 'flex-start',
justifyContent: 'space-around',
paddingLeft: 20,
marginTop: 420
},
textButton: {
fontSize: 13,
color: 'black',
}
})
export default ModalContent
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import React from 'react'
import { View, StyleSheet, Text, TouchableOpacity, Modal } from 'react-native'
const ModalContent = ({ visiblity, toggleModal }) => {
return (
<Modal animationType='slide' transparent={true} visible={visiblity} onRequestClose={() => {
toggleModal()
}} >
<View style={styles.container}>
<TouchableOpacity>
<Text style={styles.textButton}>Edit</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.textButton}>Invite</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.textButton}>Delete</Text>
</TouchableOpacity>
</View>
</Modal>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
borderTopRightRadius: 25,
borderTopLeftRadius: 25,
height: 150,
alignItems: 'center',
elevation: 10,
alignItems: 'flex-start',
justifyContent: 'space-around',
paddingLeft: 20,
marginTop: 420
},
textButton: {
fontSize: 13,
color: 'black',
}
})
export default ModalContent
just simply adding backgroundcolor with opacity>>>>
backgroundColor: rgba(255, 0, 0, 0.2);
because in modal there is view contains view so if you give background color to that conatining view it will added blacky effect
In case you are using expo use
import { BlurView } from 'expo-blur';
When I added a blurView to my project, I browsed around for some third party libs and ended up with adding react-native-unimodules.
https://www.npmjs.com/package/#react-native-community/blur
you can use blurview so you can trigger blur when the bottomsheet opens or else make it normal
.
.
.
.
const [opensheet,setopensheet]=useState(false)
const [blur,setblur]=useState(0)
const ViewRef=useRef()
useEffect(
()=>
{
const changeBlur=()=>
{
if(opensheet)
setblur(25)
else
setblur(0)
}
changeBlur()
},
[opensheet]
)
.
.
.
return
(
<BlurView
ref={ViewRef}
blurAmount={blur}
>
.
.
.
)
--here opensheet is state of your modal which is defined by bool open/true and close/false
you have multiple way to solve this
one is using this library
https://github.com/Kureev/react-native-blur
one is with image with opacity blurradius
<Image
style={{opacity:0.8}
resizeMode='cover'
source={path}
blurRadius={1}
/>
another approach would to drop shadow with transparent background
i would go with first option becuase i already tried it

Conditional rendering based on state not working on state change

I have a value in my state that changes based on a Switch. Depending on the value of that state item I want to change the styling of my button. I can see the state change, but the color doesn't change.
This seems straightforward as shown in this documentation: https://reactjs.org/docs/conditional-rendering.html
I actually have one conditional rendering working in the same statement, but it is referencing redux state instead of component state.
I've included the relevant aspects of my code below and tried to strip out the unnecessary stuff.
Still kind of a bit long.
/* eslint-disable prettier/prettier */
import React, { Component } from 'react';
import {
View,
Text,
TouchableOpacity,
Dimensions,
StyleSheet,
TextInput,
Switch,
ActivityIndicator,
} from 'react-native';
import { connect } from 'react-redux';
// Actions
import { createUser } from '../../actions/user-actions';
// Getting dims
const { width: WIDTH } = Dimensions.get('window');
// Styling
const styles = StyleSheet.create({
containerStyle: {
flex: 1,
backgroundColor: 'black',
alignItems: 'center',
justifyContent: 'center',
},
footerContainerStyle: {
justifyContent: 'flex-start',
flex: 3,
width: WIDTH,
paddingHorizontal: 30,
alignItems: 'center',
marginTop: 45,
},
tcStyle: {
flexDirection: 'row',
marginBottom: 20,
},
switchStyle: {
marginRight: 15,
},
buttonStyle: {
width: WIDTH-100,
height: 50,
backgroundColor: '#007AFF',
borderRadius: 4,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 20,
},
disabledButtonStyle: {
width: WIDTH-100,
height: 50,
backgroundColor: '#007AFF',
borderRadius: 4,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 20,
opacity: 0.3,
},
buttonTextStyle: {
color: 'white',
fontSize: 14,
fontWeight: 'bold',
},
linkStyle: {
textDecorationLine: 'underline',
color: 'blue',
},
});
// Component
class Signup extends Component {
constructor(props) {
super(props);
this.state = {
switchValue: false,
email: '',
name: '',
password: '',
passwordConfirm: '',
errorMessage: '',
};
}
componentDidUpdate() {
console.log(this.props.users);
const { navigation } = this.props;
if (this.props.users.user) {
navigation.navigate('Home');
}
}
componentDidMount() {
console.log(this.props);
}
// Helper functions
toggleSwitch = (value) => {
this.setState({switchValue: value});
};
onSignUp = () => {
const { email, name, password, passwordConfirm, switchValue } = this.state;
const { createUser } = this.props;
if (password !== passwordConfirm) {
console.log('Passwords do not match')
this.setState({errorMessage: 'Passwords do not match'});
return;
}
if (!switchValue) {
console.log('You must agree to terms');
this.setState({errorMessage: 'You must agree to terms'});
return;
}
createUser(email, password, name);
}
render() {
// Conditional button rendering
const { email, password, passwordConfirm, name, switchValue } = this.state;
let button;
console.log(switchValue);
if (this.props.users.loading) {
button = (
<TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
<ActivityIndicator size="large" />
</TouchableOpacity>
);
} else if (switchValue) {
button = (
<TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
<Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
</TouchableOpacity>
)
} else if (!switchValue) {
button = (
<TouchableOpacity style={[styles.disabledButtonStyle]} onPress={this.onSignUp}>
<Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
</TouchableOpacity>
)
}
return (
<View style={styles.containerStyle}>
<View style={styles.footerContainerStyle}>
<View style={styles.tcStyle}>
<Switch
onValueChange = {this.toggleSwitch}
value = {this.state.switchValue}
style = {styles.switchStyle}
trackColor={{true: '#007AFF', false: 'grey'}}
/>
<Text style={{color: 'white', flexWrap: 'wrap', flex: 1}}>I have read & agree to the <Text style={styles.linkStyle}>Terms of Use</Text> and <Text style={styles.linkStyle}>Privacy Policy</Text></Text>
</View>
{button}
<View style={styles.textLinkStyle}>
<Text style={styles.ctaHelpTextStyle}>Have an account?</Text>
<TouchableOpacity>
<Text style={styles.ctaTextStyle}> Sign In</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
// state mapping
const mapStateToProps = ({ users }) => ({
users,
});
// Export
export default connect(mapStateToProps, {
createUser,
})(Signup);
If I toggle that switch I am expecting the button component to change to the one with the other styling. That's not happening though.
Actually your state changes correctly, but opacity does not work.
Update:
it seems react native has issues changing TouchableOpacity's opacity.
One solution is removing the opacity from the styles. And wrapping TouchableOpacity component with a View component, giving View an opacity.
You can try like this:
else if (switchValue) {
button = (
<View opacity={0.5}>
<TouchableOpacity style={styles.buttonStyle} onPress={this.onSignUp}>
<Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT true</Text>
</TouchableOpacity>
</View>
);
} else if (!switchValue) {
button = (
<View opacity={0.1}>
<TouchableOpacity
style={styles.disabledButtonStyle}
onPress={this.onSignUp}
>
<Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT false</Text>
</TouchableOpacity>
</View>
);
add return in conditions for example
if (this.props.users.loading) {
return(
<TouchableOpacity style={[styles.buttonStyle]} onPress{this.onSignUp}>
<ActivityIndicator size="large" />
</TouchableOpacity>
);
}
Based on you code, the only difference between both buttons is just the styling.
The way i would approach this is simply make the conditioning inside the styling its self not an if statement on the render method itself, follow along:
Solution
Modify this fragment:
// ... Other code parts
if (this.props.users.loading) {
button = (
<TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
<ActivityIndicator size="large" />
</TouchableOpacity>
);
} else if (switchValue) {
button = (
<TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
<Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
</TouchableOpacity>
)
} else if (!switchValue) {
button = (
<TouchableOpacity style={[styles.disabledButtonStyle]} onPress={this.onSignUp}>
<Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
</TouchableOpacity>
)
}
to this:
// ... Other code parts
if (this.props.users.loading) {
button = (
<TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
<ActivityIndicator size="large" />
</TouchableOpacity>
);
} else {
button = (
<TouchableOpacity style={switchValue ? styles.buttonStyle : styles.disabledButtonStyle} onPress={this.onSignUp}>
<Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
</TouchableOpacity>
)
}
Hope this Helps!

Implement #mention in TextInput

How can I implement #mention in react native's TextInput?
I've tried this react-native-mention but it is not being maintained anymore. There are so many styling issues and callback issues.
What I want is to display custom view inside TextInput. Something like this.
And after tapping on the list I want to display like this:
So far I am able to achieve:
When I type '#' in TextInput user list appear.
And when I tap on user I get username in TextInput
Code:
renderSuggestionsRow() {
return this.props.stackUsers.map((item, index) => {
return (
<TouchableOpacity key={`index-${index}`} onPress={() => this.onSuggestionTap(item.label)}>
<View style={styles.suggestionsRowContainer}>
<View style={styles.userIconBox}>
<Text style={styles.usernameInitials}>{!!item.label && item.label.substring(0, 2).toUpperCase()}</Text>
</View>
<View style={styles.userDetailsBox}>
<Text style={styles.displayNameText}>{item.label}</Text>
<Text style={styles.usernameText}>#{item.label}</Text>
</View>
</View>
</TouchableOpacity>
)
});
}
onSuggestionTap(username) {
this.setState({
comment: this.state.comment.slice(0, this.state.comment.indexOf('#')) + '#'+username,
active: false
});
}
handleChatText(value) {
if(value.includes('#')) {
if(value.match(/#/g).length > 0) {
this.setState({active: true});
}
} else {
this.setState({active: false});
}
this.setState({comment: value});
}
render() {
const {comments} = this.state;
return (
<View style={styles.container}>
{
this.state.active ?
<View style={{ marginLeft: 20}}>
{this.renderSuggestionsRow()}
</View> : null
}
<View style={{ height: 55}}/>
<View style={styles.inputContainer}>
<TextInput
style={styles.inputChat}
onChangeText={(value) => this.handleChatText(value)}
>
{comment}
</TextInput>
<TouchableOpacity style={styles.inputIcon} onPress={() => this.addComment()}>
<Icon type='FontAwesome' name='send-o' style={{fontSize: 16, color: '#FFF'}}/>
</TouchableOpacity>
</View>
</View>
);
}
One simple solution would be to use react-native-parsed-text.
Here is an example:
import * as React from "react";
import { Text, View, StyleSheet } from 'react-native';
import ParsedText from 'react-native-parsed-text';
const userNameRegEx = new RegExp(/#([\w\d.\-_]+)?/g);
export default class Example extends React.Component {
handleNamePress = (name) => {
alert("Pressed username " + name);
}
render() {
return (
<View style={styles.container}>
<ParsedText
style={styles.text}
parse={
[
{pattern: userNameRegEx, style: styles.username, onPress: this.handleNamePress},
]
}
childrenProps={{allowFontScaling: false}}
>
This is a text with #someone mentioned!
</ParsedText>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
text: {
color: 'black',
fontSize: 15,
},
username: {
color: 'white',
fontWeight: 'bold',
backgroundColor: "purple",
paddingHorizontal: 4,
paddingBottom: 2,
borderRadius: 4,
},
});
However, this library doesn't support rendering custom views. The example above is achieved by just pure styling. If you need a custom view you need to implement something yourself. For a long time, it wasn't possible to render arbitrary components embedded inside a text-components. However, this has changed now afaik and we can do stuff like this:
<Text>Hello I am an example <View style={{ height: 25, width: 25, backgroundColor: "blue"}}></View> with an arbitrary view!</Text>
Check both code examples here: https://snack.expo.io/#hannojg/restless-salsa
One important note: You can render the output of the ParsedText or your own custom component inside the TextInput, like this:
<TextInput
...
>
<ParsedText
...
>
{inputValue}
</ParsedText>
</TextInput>

How to show two views per rows in scollview in React native

How to show two views per rows in scollview in React native?
It is difficult to change the large framework since I made a view by pulling the json with module.
I would like to show views in the scrollview in the form shown below.
enter image description here <-- image link
I’d be glad if you could help me.
** If it have no idea in current method, you can give me a new idea.
this is code (const styles skipped)
import React, { Component } from 'react';
import { StyleSheet, View, Text, Image, StatusBar, FlatList, ScrollView, TouchableOpacity, Button, Dimensions } from 'react-native';
import logoImg from '../../images/logo.png';
import SearchInput, { createFilter } from 'react-native-search-filter';
import Icon from 'react-native-vector-icons/FontAwesome';
import Icon2 from 'react-native-vector-icons/Feather';
import promotion_list from '../../data/market_list.js';
const KEYS_TO_FILTERS = ['name', 'subject'];
const myIcon = (<Icon name="times" size={25} color='#949494' />)
export default class Market extends React.Component {
constructor(props) {
super(props);
this.state = {
searchTerm: ''
}
}
searchUpdated(term) {
this.setState({ searchTerm: term })
}
render() {
const filteredlists = promotion_list.filter(createFilter(this.state.searchTerm, KEYS_TO_FILTERS))
return (
<View style={styles.SearchList}>
<View style={{ flexDirection: 'row', margin: 10, padding: 10, height: 40, borderRadius: 100, backgroundColor: '#f5f5f5' }}>
<Icon name="search" size={20} color='#949494' style={{ flex: 0, marginRight: 10 }} />
<SearchInput
clearIcon={myIcon}
clearIconViewStyles={{ position: 'absolute', right: 6 }}
onChangeText={(term) => { this.searchUpdated(term) }}
placeholder="Search"
inputViewStyles={{ flex: 1 }}
/>
</View>
<View style={{justifyContent: 'center', alignItems: 'center'}}>
<Image style={{width:390, height:180}} source={require("../../images/market/topview.png")} />
</View>
<View>
<Text style={{marginLeft:15, marginTop:10, marginBottom:10, fontWeight:'bold', fontSize:20, color: '#494a51'}}>Your Partners</Text>
</View>
<ScrollView style={styles.ScrollView}>
{filteredlists.map(plist => {
function getImage(img_name) {
switch (img_name) {
case "1.png": return require("../../images/par_logo/1.png");
case "2.png": return require("../../images/par_logo/2.png");
case "3.png": return require("../../images/par_logo/3.png");
case "4.png": return require("../../images/par_logo/4.png");
case "5.png": return require("../../images/par_logo/5.png");
case "6.png": return require("../../images/par_logo/6.png");
case "7.png": return require("../../images/par_logo/7.png");
case "p1.png": return require("../../images/promotion_feed/1.png");
case "p2.png": return require("../../images/promotion_feed/2.png");
case "p3.png": return require("../../images/promotion_feed/3.png");
case "p4.png": return require("../../images/promotion_feed/4.png");
case "p5.png": return require("../../images/promotion_feed/5.png");
}
}
return (
<TouchableOpacity activeOpacity={1} key={plist.id} style={styles.ListItem}>
<View style={{ paddingRight: 10, paddingLeft: 10, height: 50, flexDirection: 'row', alignItems: 'center' }}>
<Image style={{ marginRight: 10, width: 30, height: 30, resizeMode: Image.resizeMode.contain }} source={getImage(plist.src1)} />
<Text style={{ fontWeight: 'bold' }}>{plist.name}</Text>
</View>
<View style={{margin:0}}>
<TouchableOpacity onPress={() => { alert("you clicked me") }}>
<Image style={{}} source={getImage(plist.src2)} />
</TouchableOpacity>
</View>
</TouchableOpacity>
)
})}
</ScrollView>
</View>
)
}
}
One possible solution is to use a FlatList which is inherited from ScrollView and use the numColumns prop. FlatList