Please have a look this image
I have an issue in the animation of the circle.
The flow is:
When user will click on button 1, the circle will animate from real position to position 1,
When clicking button2, a circle will move from position 1 to position 2,
and
When clicking on button2, a circle will animate back on the real position.
I need 1 sec. time while animate and I want to set circle position at particular Y position.
mean the first position on Y=400, second position on Y= 100.
Thanks in advance
You need to use the Animated library from react-native. Check out the library for more details on how to animate objects.
Meanwhile check the working example in Snack.io
Here's the code.
import React, { Component } from "react";
import { View, Text, StyleSheet, Animated, TouchableOpacity } from "react-native";
export default class App extends Component {
constructor() {
super();
this.state = {
posY: new Animated.Value(400)
};
}
moveBall = (yPos) => {
Animated.timing(this.state.posY, {
toValue: yPos,
duration: 1000
}).start()
};
renderRectangle = () => {
const animatedStyle = { top: this.state.posY };
return (
<Animated.View style={[styles.rectangle, animatedStyle]}>
</Animated.View>
);
};
render() {
return (
<View style={styles.container}>
<View style={{ flex: 0.9, alignItems: 'center' }}>
{this.renderRectangle()}
</View>
<View style={styles.buttonsContainer}>
<TouchableOpacity
style={styles.buttonStyle}
onPress={() => this.moveBall(250)}
>
<Text>Button 1</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.buttonStyle}
onPress={() => this.moveBall(100)}
>
<Text>Button 2</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.buttonStyle}
onPress={() => this.moveBall(400)}
>
<Text>Button 3</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
rectangle: {
backgroundColor: "#2c3e50",
width: 50,
height: 50,
borderRadius: 50,
position: 'absolute'
},
buttonsContainer: {
flex: 0.1,
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: 20,
paddingRight: 20
},
buttonStyle: {
padding: 5,
height: 30,
backgroundColor: 'limegreen'
}
});
Related
I am not sure if the heading is accurate but I want to implement something like this in react-native
Notice how it automatically scrolls for a while when the user scrolls quickly from right to left.
This is what I have
This is how my code looks like
<ScrollView
style={{ ...styles.scrollView }}
horizontal={true}
contentContainerStyle={styles.scrollViewContainer}
showsHorizontalScrollIndicator={false}>
{profileData.map((profile, index) => {
return (
<TouchableWithoutFeedback
key={`${index}Profile`}
onPress={() => setActive(index)}>
<View style={styles.imageCircle}>
<ImageCircle uri={profile.path} active={index === active} />
</View>
</TouchableWithoutFeedback>
);
})}
</ScrollView>
Any idea how I can fix it/apply it in my component? Below are the relevant styles.
import { StyleSheet, Dimensions } from 'react-native';
const { width } = Dimensions.get('window');
const styles = StyleSheet.create({
scrollView: {
height: 100,
},
scrollViewContainer: {
paddingHorizontal: width * 0.5 - width * 0.1,
},
imageCircle: {
width: width * 0.2,
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
},
});
export default styles;
I am trying to create 6 customized button (3 buttons in each row) using TouchableOpacity. I was able to add the 3 buttons in the first row but when try to add the other three buttons in the next row, for some reason it pushes the the first row up. I want the gap/height between each rows to be at most 10px.
and my other question is, when I try to wrap the customized card with TouchableOpacity, it ignores the width I specify on the StyleSheet.
I am new to react native. So, if this is dumb question to ask, I apologize.
Here is the code I have,
//Card component
import React from "react";
import { StyleSheet, View, TouchableOpacity } from "react-native";
function Card(props) {
return (
<View style={{ ...styles.CardSytle, ...props.style }}>
{props.children}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
CardSytle: {
shadowColor: "black",
shadowOffset: { width: 0, height: 2 },
shadowRadius: 6,
shadowOpacity: 0.26,
elevation: 10,
backgroundColor: "white",
padding: 20,
borderRadius: 10,
marginHorizontal: 10,
marginVertical: 10,
},
});
export default Card;
//MainPage
import React from "react";
import { View, StyleSheet, Dimensions } from "react-native";
import Card from "../components/Card";
const MainPageScreen = (props) => {
return (
<View style={styles.body}>
<View style={styles.cardContainer}>
<Card style={styles.card} />
<Card style={styles.card} />
<Card style={styles.card} />
</View>
<View style={styles.cardContainer}>
<Card style={styles.card} />
<Card style={styles.card} />
<Card style={styles.card} />
</View>
</View>
);
};
const styles = StyleSheet.create({
body: {
flex: 1,
backgroundColor: "white",
},
cardContainer: {
flex: 1,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
},
card: {
width: Dimensions.get("window").width / 3,
maxWidth: "28%",
height: 150,
maxHeight: "28%",
},
});
export default MainPageScreen;
//Here is screenshot of the buttons
[1]: https://i.stack.imgur.com/9z84U.png
You are setting a maxHeight of 28% which is setting the button height to 28% of parent and creates a blank space under the row. So you should remove it.
card: {
width: Dimensions.get('window').width / 3,
maxWidth: '28%',
height: 150,
},
As for the touchable opacity, Rather than wrapping the view you can use it as the main wrapper and style it Like below.
function Card(props) {
return (
<TouchableOpacity style={[styles.CardSytle, props.style]}>
{props.children}
</TouchableOpacity>
);
}
I have a TouchableOpacity with key="red" and another one with key="black" and everytime a button is pushed the value should be added to the array. I've searched the internet for about one hour to find a way of doing this and I can't find nothing
import React from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
var RedBlackArray = [ "Red", "Black", "Red"];
export default class App extends React.Component {
constructor() {
super();
this.state = {
countRed: 0,
countBlack: 0
};
}
handlePressRed = () => {
this.setState(prevState => ({ countRed: prevState.countRed + 1 }));
}
handlePressBlack = () => {
this.setState(prevState => ({ countBlack: prevState.countBlack + 1 }));
}
render() {
return (
<View>
<View style={styles.container}>
<View style={styles.col1}>
<Text>red: {this.state.countRed}</Text>
<TouchableOpacity key='red' onPress={this.handlePressRed}>
<Text style={styles.button}>red!</Text>
</TouchableOpacity>
</View>
<View style={styles.col2}>
<Text>black: {this.state.countBlack}</Text>
<TouchableOpacity key='black' onPress={this.handlePressBlack}>
<Text style={styles.button.buton2}>black!</Text>
</TouchableOpacity>
</View>
</View>
<View style={{marginTop: 30, paddingLeft: 20, paddingRight:20}}>
<Text>So far the order has been:</Text>
{RedBlackArray.map((item, key)=> (
<Text key={key}>{item}</Text>
))}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
marginTop: 50,
backgroundColor: 'red',
borderColor: 'white',
borderWidth: 1,
borderRadius: 12,
color: 'white',
fontSize: 20,
fontWeight: 'bold',
overflow: 'hidden',
padding: 12,
textAlign:'center',
buton2: {
marginTop: 50,
backgroundColor: 'black',
borderColor: 'white',
borderWidth: 1,
borderRadius: 12,
color: 'white',
fontSize: 20,
fontWeight: 'bold',
overflow: 'hidden',
padding: 12,
textAlign:'center'
}
},
container: {
flexDirection: 'row',
justifyContent: 'center'
},
col1: {
paddingTop: 50,
paddingRight: 30,
justifyContent: 'center'
},
col2: {
paddingTop: 50,
paddingLeft: 30,
justifyContent: 'center'
}
});
The result would be that when Red or Black buttons are pushed, the key should be added to the array so it would be displayed in the lower part of the code but I can't find the way of doing it. Here is the full code. Also, any other advice about what I'm doing wrong is welcomed. I've just started learning React. Thank you all!
You should read basic documentation of react-native the key prop in TouchableOpacity is work as id not for key value like array. Try following code
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = {
red: 0,
black: 0,
};
}
onClick = (name) => {
let selected = this.state[name];
selected++;
this.setState({ [name]: selected });
};
renderButton = (name) => {
return (
<TouchableOpacity onPress={this.onClick.bind(this, name)}>
<Text>{name}</Text>
</TouchableOpacity>
);
};
render() {
const { red, black } = this.state;
return (
<View>
{this.renderButton('red')}
{this.renderButton('black')}
{red.map(() => (
<Text>red</Text>
))}
{black.map(() => (
<Text>black</Text>
))}
</View>
);
}
}
Maybe you could try to pass the desired value to the function called onPress to add it to the desired array.
handlePressBlack(passedValue) {
this.setState(prevState => ({ countBlack: prevState.countBlack + 1 });
this.setState(RedBlackArray: this.RedBlackArray.concat(passedValue));
}
<TouchableOpacity key='black' onPress={() => this.handlePressBlack('Black')}>
<Text style={styles.button.buton2}>black!</Text>
</TouchableOpacity>
I am using a custom component with image and text. The image is relative to the text. Please see the screenshot.
image 1
image 2.
I have used the TouchableOpacity component as root view for that.
In screenshots when long press on the component, two views are overlapping with shadow. It looks ugly when long press.
Please see the code below for reusable component.
'use strict';
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Image,
} from 'react-native';
export default class ExampleButton extends Component {
constructor (props) {
super (props);
}
_handleOnPress = () => {
console.log('pressed!!!');
};
render () {
console.log (this.props);
return (
<TouchableOpacity
onPress={this.handleOnPress}
>
<View style={styles.btnCompContainer}>
<View
style={{
backgroundColor: '#FFF',
justifyContent: 'center',
borderRadius: 30,
height: 50,
width: '100%',
}}
>
<Text style={styles.btnTxt}>{this.props.buttonText}</Text>
</View>
<View style={[styles.btnElmContainer]}>
<Image
style={[{height: 30, width: 30,resizeMode:'stretch'}]}
source={this.props.image}
/>
</View>
</View>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create ({
btnCompContainer: {
flexDirection: 'row',
alignItems: 'center',
height: 60,
marginLeft: 10,
marginRight: 20,
},
btnElmContainer: {
position: 'absolute',
justifyContent: 'center',
alignItems: 'center',
width: 60,
height: 60,
backgroundColor:'#fff',
borderRadius: 30,
shadowColor: '#000000',
shadowOffset: {
width: 1,
height: 1,
},
elevation:5,
shadowRadius: 2,
shadowOpacity: 0.3,
},
btnTxt: {
marginLeft: 80,
color: '#9e9e9e',
fontSize: 16,
fontWeight: 'bold',
textAlign: 'left',
},
});
Here I am using this reusable component in code.
'use strict';
import React, {Component} from 'react';
import {
Animated,
StyleSheet,
Text,
TextInput,
View,
Image,
ImageBackground,
TouchableOpacity,
Button,
StatusBar,
Easing
} from 'react-native';
// Custom Components
const searchBGImg = require('../assets/search-bg-kit.png');
const houseLogo = require('../Resources/house.png');
import ExampleButton from './components/common/example-button';
export default class TypeSelect extends Component<Props> {
// Navigation Option
static navigationOptions = {
header: null
}
constructor() {
super();
this.state = {
visible: false,
x: new Animated.Value(-100),
};
}
slide = () => {
Animated.spring(this.state.x, {
toValue: 0,
easing: Easing.easeOutBack
}).start();
this.setState({
visible: true,
});
};
gotoSearch = () =>{
this.props.navigation.navigate('DocSearch')
}
componentDidMount(){
this.slide();
}
render() {
return (
<View style={styles.container}>
<ImageBackground source={searchBGImg} style={styles.imgBG}>
<View style={{alignItems:'center', marginBottom:20}}>
<Image style={{height:57, width:69, marginBottom:12}} source={houseLogo} />
</View>
<View>
<Animated.View
style={[styles.slideView, {
transform: [
{
translateX: this.state.x
}
]
}]}>
<ExampleButton image={houseLogo} buttonText={'Click here'} />
<ExampleButton image={houseLogo} buttonText={'Click here'} />
</Animated.View>
</View>
</ImageBackground>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
imgBG:{
flex: 1,
flexDirection: "column",
justifyContent:"center",
width: "100%",
height: "100%"
}
})
It is working fine in iOS, but it's not working in android up to the mark. Please help me to work it in android.
Thanks in advance.
You should use renderToHardwareTextureAndroid prop on <View /> component.
In your example like this:
<View style={styles.btnCompContainer} renderToHardwareTextureAndroid >
<View
style={{
backgroundColor: '#FFF',
justifyContent: 'center',
borderRadius: 30,
height: 50,
width: '100%',
}}
>
<Text style={styles.btnTxt}>{this.props.buttonText}</Text>
</View>
<View style={[styles.btnElmContainer]}>
<Image
style={[{height: 30, width: 30,resizeMode:'stretch'}]}
source={this.props.image}
/>
</View>
</View>
I am trying to have my Animated View come downward and over the content of the ScrollView instead of over my top fixed position bar, but when the Animation begins the animated view ends up eating the space of the container bar. I have played with paddingTop, marginTop, but seems to be a hack.
Here is a self contained code sample that shows what I'm trying to do:
import React, { Component } from 'react';
import {
AppRegistry, StyleSheet, Text, View, Animated, Dimensions, ScrollView,
Button
} from 'react-native';
const { width } = Dimensions.get('window');
const make_text = (text='Hello', color='blue') => (
<Text
style={{textAlign: 'center', fontSize: 24, backgroundColor: color, margin: 20}}>
{text}
</Text>
);
class Fix_bar extends Component {
state = { height: new Animated.Value(0) };
expand_dropdown = () => {
Animated.timing(this.state.height, {
toValue: 100
}).start();
}
fold_dropdown = () => {
Animated.timing(this.state.height, {
toValue: 0
}).start();
}
render () {
const s = {
position: 'absolute', height: 150, backgroundColor: 'red', paddingTop: 20, width
};
return (
<View style={s}>
<View style={{flexDirection: 'row', flex: 1, justifyContent: 'space-between'}}>
<Text style={{fontSize: 24, paddingTop: 50}}> Left side thing</Text>
<Text style={{fontSize: 24, paddingTop: 50}}> Right side thing</Text>
</View>
<Button title={'Expand'} onPress={this.expand_dropdown}/>
<Button title={'Fold'} onPress={this.fold_dropdown}/>
<View style={{backgroundColor: 'black', height: 1}}/>
<Animated.View style={{height: this.state.height}}>
{make_text('world', 'aliceblue')}
{make_text('world', 'aliceblue')}
{make_text('world', 'aliceblue')}
</Animated.View>
</View>
);
}
}
class animate_example extends Component {
render() {
return (
<View style={{backgroundColor: 'orange', flex: 1}}>
<Fix_bar/>
<ScrollView style={{marginTop: 150}}>
<View style={{justifyContent: 'space-between'}}>
{make_text()}
{make_text()}
{make_text()}
{make_text()}
{make_text()}
</View>
</ScrollView>
</View>
);
}
}
AppRegistry.registerComponent('animate_example', () => animate_example);
One idea I had was to make a trailing View in that fix_bar component with transparency with the height that I intend for the dropdown but haven't explored that idea.
I would suggest the following hierarchy:
const ScrollViewContainer = () =>
<ScrollView style={{marginTop: 150}}>
<View style={{justifyContent: 'space-between'}}>
{make_text()}
{make_text()}
{make_text()}
{make_text()}
{make_text()}
</View>
</ScrollView>;
const ExpandableBar = (props: {expanded: boolean}) =>
<View style={{position: "absolute", top: 0, left: 0, right: 0, bottom: 0}} />
const render = () =>
<View>
<Fix_bar />
<View style={{flex: 1}}> // container which fills remaining space
<ScrollViewContainer />
<ExpandableBar />
</View>
Then in ExpandableBar you'd animate down if expanded is true. also please note that ExpandableBar should be a class (obviously).