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.
Related
I am new to React Native and I have given a swipe task.
Swipe should change only the content of a view not the entire page
The swipe action should be tracked in dots bar.
I found two packages which are React Native Tab View and react-page-transitions. I am thinking about manipulating one of them to achieve such action or is there a better way? What is the best practice in swipe?
First Content
Second Content (frist content swiped)
I responded to a similar question and recommended react-native-swiper as it has the swiping functionality built in out of the box (this isnt enabled for web):
import React, { useState } from 'react';
import { Text, View, StyleSheet, FlatList } from 'react-native';
import Constants from 'expo-constants';
import Swiper from 'react-native-swiper';
import {
colorGenerator,
colorManipulators,
} from '#phantom-factotum/colorutils';
const totalItems = 4;
export default function App() {
const DATA = colorGenerator(totalItems).map((color, index) => ({
color,
textColor: colorManipulators.darkenColor(color, 0.45),
title: 'Item' + (index + 1),
}));
return (
<View style={styles.container}>
<Swiper style={styles.wrapper} showsButtons={true} horizontal={true}>
{DATA.map((item, i) => {
return (
<View
style={[styles.item, { backgroundColor: item.color }]}
key={item.title}>
<Text style={[styles.text, { color: item.textColor }]}>
{item.title}
</Text>
</View>
);
})}
</Swiper>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
wrapper: {
// flex: 1,
},
item: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 30,
fontWeight: 'bold',
},
});
Here's the demo
I want to change button borderRadius,color, and padding but it doesn't work
this is my view
import * as React from 'react';
import { StatusBar } from 'expo-status-bar';
import { Button, StyleSheet, Text, View, Image} from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
function HomeScreen({navigation}) {
return(
<View
style={styles.container}>
<Text>Home Screen</Text>
<Button
style={styles.button}
title= "Go To Details"
onPress={()=> navigation.navigate('Details')}
/>
</View>
)
}
and this is my styles
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
button: {
width: 200,
marginTop: 20,
backgroundColor: "green",
padding: 15,
borderRadius: 50,
},
});
this is my screen
are there something that i miss?
I don't think so you can customize like your own with react native Button. But you can change something like title, color, etc. Check their doc https://reactnative.dev/docs/button
A better way is to make your own Button with your custom Style like this :
<TouchableOpacity onPress={()=> navigation.navigate('Details')}>
<View style={styles.button}>
<Text>Go To Details</Text>
</View>
</TouchableOpacity>
I'll suggest you to use View, because button from 'react-native' have some default styling and there can be some difficulty to override them, you can customise View like anything you want. just have a View and give them desired styles.
function HomeScreen({navigation}) {
return(
<View
style={styles.container}>
<Text>Home Screen</Text>
<View
style={styles.button}
title= "Go To Details"
onPress={()=> navigation.navigate('Details')}
/>
</View>
)
}
just give styles you want
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
button: {
width: 200,
marginTop: 20,
backgroundColor: "green",
padding: 15,
borderRadius: 50,
},
});
Hello there I'm new to react native. I'm trying to create reusable component, not only card component, maybe in future will create other reusable components. Below is the code example of reusable card component that I've created:
Card.js
import React from 'react';
import { View, StyleSheet } from 'react-native';
const Card = props => {
return (
<View style={{...styles.card, ...props.style}}>{props.children}</View>);};
const styles = StyleSheet.create({
card: {
shadowColor: 'black',
shadowOffset: { width: 0, height: 2 },
shadowRadius: 6,
shadowOpacity: 0.26,
elevation: 8,
backgroundColor: 'white',
padding: 20,
borderRadius: 10,
}
});
export default Card;
StartGameScreen.js
import React from 'react';
import { View, Text, StyleSheet, TextInput, Button } from 'react-native';
import Card from '../components/Card';
const StartGameScreen = props => {
return (
<View style={styles.screen}>
<Text style={styles.title}>Start a New Game!</Text>
<Card style={styles.inputContainer}>
<Text>Select a Number</Text>
<TextInput />
<View style={styles.buttonContainer}>
<View style={styles.button}><Button title="Reset" onPress={() => {}} /></View>
<View style={styles.button}><Button title="Confirm" onPress={() => {}} /></View>
</View>
</Card>
</View>
);
};
const styles = StyleSheet.create({
screen: {
flex: 1,
padding: 10,
alignItems: 'center'
},
title: {
fontSize: 20,
marginVertical: 10
},
inputContainer: {
width: 300,
maxWidth: '80%',
alignItems: 'center'
},
buttonContainer: {
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
paddingHorizontal: 15
},
button: {
width:100
}
});
export default StartGameScreen;
The Result as below:
I'm expecting it to be as below:
Is it possible to use my above code and have the expected result? or is my code wrong and there is better solution??
Your card component is reusable only mistake is the way you are merging the styles. When you merge styles you should not expand it but use an array of styles. Like below.
const Card = props => {
return (<View style={[styles.card, props.style]}>{props.children}</View>);
};
You can check the below snack for full code.
https://snack.expo.io/#guruparan/e368b9
I'm pretty new to ReactNative world. Im struggling to find an api or a library that shows the Progress Dialog as below in React Native. I believe ActivityIndicator can be used, but it does not show as overlay. Can anyone help me how can I show as an overlay using styles or if there is good library to make this.
Thanks
Here is the code to Open Prgressbar:
import React from 'react';
import { Modal, View, Text, ActivityIndicator, Button } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { isProgress: false }
}
openProgressbar = () => {
this.setState({ isProgress: true })
}
render() {
return (
this.state.isProgress ?
<CustomProgressBar />
:
<View style={{ flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' }}>
<Button title="Please click here to Open ProgressBar" onPress={this.openProgressbar} />
</View>
);
}
}
const CustomProgressBar = ({ visible }) => (
<Modal onRequestClose={() => null} visible={visible}>
<View style={{ flex: 1, backgroundColor: '#dcdcdc', alignItems: 'center', justifyContent: 'center' }}>
<View style={{ borderRadius: 10, backgroundColor: 'white', padding: 25 }}>
<Text style={{ fontSize: 20, fontWeight: '200' }}>Loading</Text>
<ActivityIndicator size="large" />
</View>
</View>
</Modal>
);
Expo url for live demo
https://snack.expo.io/#jitendra.mca13/progress-bar-demo
I would approach this by using the React Native Modal component with two Views.
This solution is a React solution and not native, so you will need to style your Modal accordingly for each platform.
import React from 'react';
import {
Modal,
View,
StyleSheet,
Text,
ActivityIndicator
} from 'react-native';
const ProgressDialog = ({ visible }) => (
<Modal
visible={visible}
>
<View style={styles.container}>
<View style={styles.content}>
<Text style={styles.title}>Please Wait</Text>
<View style={styles.loading}>
<View style={styles.loader}>
<ActivityIndicator size="large" />
</View>
<View style={styles.loadingContent}>
<Text>Loading</Text>
</View>
</View>
</View>
</View>
</Modal>
);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, .5)',
alignItems: 'center',
justifyContent: 'center',
},
content: {
padding: 35,
backgroundColor: 'white'
},
title: {
fontSize: 18,
fontWeight: 'bold',
},
loading: {
flexDirection: 'row',
alignItems: 'center',
},
loader: {
flex: 1,
},
loadingContent: {
flex: 3,
fontSize: 16,
paddingHorizontal: 10,
}
})
export default ProgressDialog;
Here's a demo on Expo, of course you will probably want to tweak the CSS.
Android & iOS solution
Create a directory called ProgressDialog
Create index.ios.js and index.android.js
Paste the above code into both index.ios.js and index.android.js
Make CSS changes for iOS
You can use the below npm package which is a very easy and attractive loader with many options.
https://github.com/maxs15/react-native-spinkit
import React from 'react';
import { StyleSheet, View } from "react-native";
import Spinner from "react-native-spinkit";
export default LoadingCmpBig = props => {
return (
<View style={styles.container}>
<StatusBar barStyle="default" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
//backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
}
});
You can use this component and use it where you want to show the Progress. You just have to maintain the state for visible the loading or not in your render function of the component.
I am trying to have a list view show up that looks similar to this. The problem I am trying to solve is regarding word wrapping of the label. I do have it working with the code below, but it feels like a hack and doesn't work with device rotation. There has to be a way to do it without using Dimensions and styling.
Here is what I have.
import React, { Component } from 'react';
import {
StyleSheet,
Dimensions,
TouchableOpacity,
Text,
View
} from 'react-native';
import Moment from 'moment'
import Icon from 'react-native-vector-icons/FontAwesome';
class ProjectListItemRenderer extends Component {
componentDidMount() {
//alert(Dimensions.get('window').height)
}
render() {
return (
<View style={styles.projectRow}>
<View style={{width: Dimensions.get('window').width - 50}}>
<Text style={styles.itemName}>{this.props.name}</Text>
<Text style={styles.itemDetails}>{`${Moment(this.props.lastUpdated).fromNow()}`}</Text>
</View>
<View style={styles.moreContainer}>
<Icon name="chevron-right" size={15} style={styles.moreIcon} />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
projectRow: {
flexDirection: 'row',
justifyContent: 'flex-start',
padding: 15,
},
itemName: {
fontSize: 18,
color: '#4A90E2',
},
itemDetails: {
fontSize: 12,
color: '#BBBBBB',
},
moreContainer: {
justifyContent: 'center',
alignItems: 'center'
},
moreIcon: {
color: "#d6d7da"
}
});
module.exports = ProjectListItemRenderer;
The other option I tried was absolute positioning, with the label being 20px from the right, and then absolute positioning the chevron on the right. The problem I ran into there was trying to figure out the height of the individual listItem renderer after it is rendered (and word wrapped).
The problem comes from having flexDirection: 'row' in the View containing your text. This makes the text overflow to the right instead of wrapping. If you want your text to wrap, the containing View must have flexDirection: 'column' in the style.
I've modified your code accordingly:
import React, { Component } from 'react';
import {
StyleSheet,
Dimensions,
TouchableOpacity,
Text,
View
} from 'react-native';
import Moment from 'moment'
import Icon from 'react-native-vector-icons/FontAwesome';
class ProjectListItemRenderer extends Component {
componentDidMount() {
//alert(Dimensions.get('window').height)
}
render() {
return (
<View style={styles.projectRow}>
<View style={styles.projectText}>
<Text style={styles.itemName}>{this.props.name}</Text>
<Text style={styles.itemDetails>
{`${Moment(this.props.lastUpdated).fromNow()}`}
</Text>
</View>
<View style={styles.moreContainer}>
<Icon name="chevron-right" size={15} style={styles.moreIcon} />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
projectText: {
flex: 1,
flexDirection: 'column'
},
projectRow: {
flexDirection: 'row',
justifyContent: 'flex-start',
padding: 15,
},
itemName: {
fontSize: 18,
color: '#4A90E2',
},
itemDetails: {
fontSize: 12,
color: '#BBBBBB',
},
moreContainer: {
justifyContent: 'center',
alignItems: 'center'
},
moreIcon: {
color: "#d6d7da"
}
});
module.exports = ProjectListItemRenderer;
The only difference is I replaced {width: Dimensions.get('window').width - 50} with {flex: 1, flexDirection: 'column'}.