This is an example code as I'm trying to learn Animated from react native. If I want to press a button and double the size of this text smoothly, how would I do that? From what I understood I need to add Transform: scale x/y somehow but I'm super confused by this. Thanks
import React, { useRef, useEffect } from 'react';
import { Animated, Text, View } from 'react-native';
const FadeInView = (props) => {
const fadeAnim = useRef(new Animated.Value(0)).current
useEffect(() => {
Animated.timing(
fadeAnim,
{
toValue: 1,
duration: 2000,
useNativeDriver: true
}
).start();
}, [])
return (
<Animated.View style={{...props.style, opacity: fadeAnim}}>
{props.children}
</Animated.View>
);
}
export default () => {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<FadeInView>
<Text style={{fontSize: 28, textAlign: 'center', padding: 10}}>Fading in</Text>
</FadeInView>
</View>
)
}
Let's say you want to scale the text when it's clicked. You can do this:
export default () => {
const scaleAnim = useRef(new Animated.Value(1)).current;
const animateTextSize = () => {
Animated.timing(
scaleAnim,
{
toValue: 2,
duration: 2000,
useNativeDriver: true
}
).start();
}
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<FadeInView>
<Animated.Text style={{fontSize: 28, textAlign: 'center', padding: 10, transform:[{scale:scaleAnim}]}} onPress={animateTextSize}>Fading in</Animated.Text>
</FadeInView>
</View>
)}
snack demo
Related
I have to make a countdown timer in an react-native app but i dont know how, i already looked it up and and found some librarys such as react-native-countdown component but it didnt worked as id like, and got some other solutions like setInterval but i dont know how to implement it in my code and make it display on the screen as in the images below:
The time goes from 00:00 to 60:00 (MM:SS) as the user slides the bar, that changes the number 05:00 by 05:00, ive already done that but with a static number, i couldnt make it countdown.
Heres how my code is looking right now:
import { useNavigation } from '#react-navigation/core';
import React, { useEffect, useState } from 'react';
import { SafeAreaView, Text, Image, TouchableOpacity, StyleSheet, Dimensions, TextInput, KeyboardAvoidingView, Platform, View } from 'react-native';
import Slider from '#react-native-community/slider';
import CountDown from 'react-native-countdown-component';
import abacatezinImg from '../assets/abacatezinin.png';
import botaoStop from '../assets/botaoStop.png';
import botaoPlay from '../assets/botaoPlay.png';
export function Timer(){
const [range, setRange] = useState('0');
const [sliding, setSliding] = useState('Inactive');
const [isSecureEntry,setIsSecureEntry]=useState(true);
const navigation = useNavigation<any>();
function handleQuit(){
navigation.navigate('Quit');
}
if(isSecureEntry){
return(
<SafeAreaView style={styles.container}>
<Text style={styles.texto}>{range}</Text>
<View style={styles.container2}>
<Slider
style={styles.slider}
minimumValue={0}
maximumValue={60}
minimumTrackTintColor='#7E9F70'
maximumTrackTintColor='#A7C99A'
thumbImage={abacatezinImg}
value={30}
onValueChange={value => setRange(parseInt(value) + ':00')}
onSlidingStart={() => setSliding('Sliding')}
onSlidingComplete={() => setSliding('Inactive')}
step={5}
/>
<TouchableOpacity onPress={() =>{
setIsSecureEntry((prev)=> !prev)
}}>
<Image source={botaoPlay} style={styles.bPlay}/>
</TouchableOpacity>
</View>
</SafeAreaView>
);
}
else{
return(
<SafeAreaView style={styles.container}>
<Text style={styles.texto}>{range}</Text>
<View style={styles.container3}>
<TouchableOpacity onPress={handleQuit}>
<Image source={botaoStop} style={styles.bStop}/>
</TouchableOpacity>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container:{
flex: 1,
alignItems: 'center',
justifyContent: 'flex-start',
},
container2:{
backgroundColor: '#E4F0E2',
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
borderRadius: 100,
width: 327,
height: 66,
paddingHorizontal: 19,
marginTop: 20,
},
container3:{
alignItems: 'center',
justifyContent:'space-between',
marginTop: 20,
},
slider:{
width: 209,
height: 50,
transform: [{scaleY: 4}]
},
bPlay:{
width: 50,
height: 50,
},
bStop:{
width: 66,
height: 66,
},
texto:{
fontWeight: '300',
fontSize: 58,
lineHeight: 87,
letterSpacing: 0.03,
color: '#1B3810',
},
})
If anyone has any idea how to make it Id appreciate the help
Hooks(using useEffect) to countdown using setInterval in react - native:
const [timerCount, setTimer] = useState(60)
useEffect(() => {
let interval = setInterval(() => {
setTimer(lastTimerCount => {
if (lastTimerCount == 0) {
//your redirection to Quit screen
} else {
lastTimerCount <= 1 && clearInterval(interval)
return lastTimerCount - 1
}
})
}, 1000) //each count lasts for a second
//cleanup the interval on complete
return () => clearInterval(interval)
}, []);
use the state variable timerCount as:
<Text>{timerCount}</Text>
How to scroll to image[x] in ScrollView at the first time component load?
I want when we open this screen, ScrollView will scroll to the 4th image.
This is my demo
export default function App() {
const scrollX = useRef(new Animated.Value(0));
const imageRef = createRef(scrollX);
useEffect(() => {
imageRef.current?.scrollTo(new Animated.Value(3));
}, []);
return (
<SafeAreaView style={styles.container}>
<View style={styles.scrollContainer}>
<ScrollView
ref={imageRef}
horizontal={true}
pagingEnabled
showsHorizontalScrollIndicator={false}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: scrollX.current,
},
},
},
],
{ useNativeDriver: false }
)}
scrollEventThrottle={1}
>
{children}
</ScrollView>
</View>
</SafeAreaView>
);
}
scrollTo accept separate compoenents. You don't need to use animated component and the onScroll method for react scrollview. Just enter {x: value, animated: true} in scrollTo as it accepts object
Here is the code updated from snack:
import React, { useRef, useEffect, createRef } from "react";
import {
SafeAreaView,
ScrollView,
Text,
StyleSheet,
View,
ImageBackground,
Animated,
Dimensions,
} from "react-native";
const images = new Array(6).fill(
"https://images.unsplash.com/photo-1556740749-887f6717d7e4"
);
export const WIDTH = Dimensions.get("window").width;
export default function App() {
const imageRef = useRef();
useEffect(() => {
imageRef.current?.scrollTo({x: WIDTH * 3});
},[]);
return (
<SafeAreaView style={styles.container}>
<View style={styles.scrollContainer}>
<ScrollView
ref={imageRef}
horizontal={true}
pagingEnabled
showsHorizontalScrollIndicator={false}
>
{images.map((image, imageIndex) => {
return (
<View
style={{
width: WIDTH,
height: 250,
}}
key={imageIndex}
>
<ImageBackground source={{ uri: image }} style={styles.card}>
<View style={styles.textContainer}>
<Text style={styles.infoText}>
{"Image - " + imageIndex}
</Text>
</View>
</ImageBackground>
</View>
);
})}
</ScrollView>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
scrollContainer: {
height: 300,
alignItems: "center",
justifyContent: "center",
},
card: {
flex: 1,
marginVertical: 4,
marginHorizontal: 16,
borderRadius: 5,
overflow: "hidden",
alignItems: "center",
justifyContent: "center",
},
textContainer: {
backgroundColor: "rgba(0,0,0, 0.7)",
paddingHorizontal: 24,
paddingVertical: 8,
borderRadius: 5,
},
infoText: {
color: "white",
fontSize: 16,
fontWeight: "bold",
},
});
I want to send basic data from Home.js component to details.js component.
My home.js
import React, { useState, useEffect } from 'react'
import { View, TouchableHighlight, Image, FlatList, ActivityIndicator, Text, StyleSheet } from 'react-native'
function HomeScreen({ navigation }) {
const [isLoading, setIsLoading] = useState(true)
const [dataSource, setDataSource] = useState([])
useEffect(() => {
fetch('http://www.json-generator.com/api/json/get/bVxGaxSSgi?indent=2')
.then((response) => response.json())
.then((responseJson) => {
setIsLoading(false)
setDataSource(responseJson)
})
.catch((error) => {
alert(error)
});
})
if (isLoading) {
return (
<View style={{ flex: 1, padding: 20 }}>
<ActivityIndicator />
</View>
)
}
return (
<View style={{ flex: 1, paddingTop: 20, paddingHorizontal: 20 }}>
<FlatList
data={dataSource}
renderItem={({ item }) =>
<TouchableHighlight onPress={() => navigation.navigate('Details',{text:'alperen'})} underlayColor="white">
<View style={styles.button}>
<View style={styles.div}>
<View style={styles.inlineDiv}>
<Image source={{ uri: 'https://source.unsplash.com/random/900�/?fruit' }} style={styles.pic} />
<Text>{item.name}, {item.about}</Text>
</View>
</View>
</View>
</TouchableHighlight>
}
keyExtractor={({ _id }, index) => _id}
/>
</View>
)
}
export default HomeScreen
const styles = StyleSheet.create({
pic: {
width: '100%',
height: 200,
borderRadius: 20,
},
div: {
shadowColor: "#fff",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.20,
shadowRadius: 50,
elevation: 0,
marginBottom: 10
},
inlineDiv: {
padding: 5,
},
button: {
alignItems: 'center',
},
});
This is my details.js component
import React, { useEffect } from 'react'
import { View, Text } from 'react-native'
function DetailsScreen( navigation ) {
useEffect(() => {
alert(navigation.text)
})
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
export default DetailsScreen
I want to go to the other page and at the same time I want to send and print the data. This code is currently returning undefined. How Can I send data ? Probably I can use props but I don't know usage.
Change
function DetailsScreen( navigation ) {
useEffect(() => {
alert(navigation.text)
})
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
to
function DetailsScreen({navigation}) {
useEffect(() => {
alert(navigation.state.params.text)
})
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
And try
In first screen
<TouchableHighlight onPress={() => navigation.navigate('Details',{item})} underlayColor="white">
In next screen you can get data
this.props.navigation.state.params.item
Example:
<Image source={this.props.navigation.state.params.item.img}/>
<Text>{this.props.navigation.state.params.item.text}</Text>
Sending data operation is success but details page is not working. I looked 'react-navigation documentation ' (https://reactnavigation.org/docs/en/params.html). There is a keyword ('route') we have to use it.
function DetailsScreen({ route }) {
const { text } = route.params;
useEffect(() => {
var a = JSON.stringify(text)
alert(a)
})
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
I tried this code and its working success.
Hi I have an image in my HeaderRight and I want to animate it with an effect of zoom-in/zoom-out. How can I use the Animated library in order to work it out ?
Thanks !
let headerRight = (
<TouchableOpacity onPress = {() => {this.openDialog(true)} }>
<View style={{ flexDirection:'row', justifyContent: 'space-around'}}>
<View style={{borderRadius: 30, padding:4, overflow: 'hidden', alignItems: 'center',backgroundColor:'white', justifyContent: 'center', marginRight:20 }}>
<Image
style={{ width:28, height: 28}}
source={require("../Images/icone-sonnerie.png")}/>
</View>
</View>
</TouchableOpacity>
);
You can implement animated touchableOpacity like this
create class
import React from 'react'
import {
Animated,
TouchableOpacity
} from 'react-native'
const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity)
class AnimatedTouchableOpacity extends React.Component {
state = {
scale: new Animated.Value(1)
}
ScaleTheTouchable(toValue, withDuration) { //Call this function in this class in onPress or another event call you want with your scale (1 is the normal size) and duration in miliseconds
Animated.timing(
this.state.scale,
{
toValue: toValue,
duration: withDuration
},
).start()
}
render() {
return (
<AnimatedTouchable
style = {[
{
transform: [{
scale: this.state.scale
}]
},
this.props.style
]}
>
{this.props.children}//Your image or another view inside button goes here...
</AnimatedTouchable>
)
}
}
then you can call it like this
let headerRight = (
<AnimatedTouchableOpacity style = {{}} >
<View style={{ flexDirection:'row', justifyContent: 'space-around'}}>
<View style={{borderRadius: 30, padding:4, overflow: 'hidden', alignItems: 'center',backgroundColor:'white', justifyContent: 'center', marginRight:20 }}>
<Image
style={{ width:28, height: 28}}
source={require("../Images/icone-sonnerie.png")}/>
</View>
</View>
</AnimatedTouchableOpacity>
)
I have created an extremely large button with a giraffe head and a blue sky with clouds behind. I am wondering how when you click on the giraffe head you can make the image (sky behind) disappear and then reappear when you click the giraffe again. I need lots of these buttons so I have tried to make a reusable button component.
I made a Stack of the Components.
https://snack.expo.io/#tamsynjennifer/custom-button
Otherwise this is the code:
REUSABLE BUTTON.JS
import React from 'react';
import { View, StyleSheet, Image, TouchableWithoutFeedback } from 'react-native';
const Button = ({ backgroundImage, mainImage, onPress }) => (
<View style={styles.container}>
<Image
style={styles.bgImage}
source={backgroundImage}
resizeMode={'contain'}
/>
<TouchableWithoutFeedback
onPress={onPress}
style={styles.button}
>
<Image
style={styles.image}
source={mainImage}
resizeMode={'contain'}
/>
</TouchableWithoutFeedback>
</View>
);
const styles = StyleSheet.create({
container: {
height: 250,
width: 250,
justifyContent: 'center',
alignItems: 'center',
marginTop: 0,
},
button: {
height: 200,
width: 200
},
bgImage: {
alignSelf: 'center',
justifyContent: 'center',
position: 'absolute',
height: 250,
width: 250,
},
image: {
alignSelf: 'center',
justifyContent: 'center',
position: 'absolute',
height: 200,
width: 200
},
});
export default Button;
APP.JS
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Constants } from 'expo';
const bgImage = require("./assets/BgImage.png");
const mainImage = require("./assets/MainImage.png");
import Button from './Button';
class App extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.button}>
<Button
backgroundImage={bgImage}
mainImage={mainImage}
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
height: 300,
width: 300,
justifyContent: 'center',
alignItems: 'center'
},
button: {
height: 250,
width: 250,
alignSelf: 'center',
position: 'absolute'
},
});
export default App;
This is how you can do it, I have fixed your code. Firstly you need to setState and change state onPress, so that the component re-render and change the image. Simply replace your class with this.
Expo Link
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Constants } from 'expo';
const bgImage = require("./assets/BgImage.png");
const mainImage = require("./assets/MainImage.png");
import Button from './Button';
class App extends Component {
constructor(props){
super(props)
this.state = {
imageVisibility: true,
backgroundImagePath: require("./assets/BgImage.png")
}
}
render() {
return (
<View style={styles.container}>
<View style={styles.button}>
<Button
backgroundImage={this.state.backgroundImagePath}
mainImage={mainImage}
onPress= {() => {this.changeImgaeVisibility()}}
/>
</View>
</View>
);
}
changeImgaeVisibility = () => {
if(this.state.imageVisibility){
this.setState({imageVisibility: false, backgroundImagePath: null})
}else{
this.setState({imageVisibility: true, backgroundImagePath: require("./assets/BgImage.png")})
}
}
}
const styles = StyleSheet.create({
container: {
height: 300,
width: 300,
justifyContent: 'center',
alignItems: 'center'
},
button: {
height: 250,
width: 250,
alignSelf: 'center',
position: 'absolute'
},
});
export default App;
You can add a function as a javascript object to your JSX to render the background image, this method will return the object that you need to render, as you can see in the example bellow:
const handleBackgroundImg = (imageBg, backgroundiImage) => {
if (imageBg === true) {
return <Image style={styles.bgImage} source={backgroundImage} resizeMode={'contain'}/>
}
return <Image />;
};
To add this function to your JSX code you have to change it like this:
const Button = ({ backgroundImage, mainImage, onPress, imageBg }) => (
<View style={styles.container}>
{handleBackgroundImg(imageBg, backgroundImage)}
<TouchableWithoutFeedback
onPress={onPress}
style={styles.button}
>
<Image
style={styles.image}
source={mainImage}
resizeMode={'contain'}
/>
</TouchableWithoutFeedback>
</View>
);
Now when you use this component you have to pass the imageBg boolean as well, considering true when you want to show the bg and false when you want to hide it. See the code below:
<Button
backgroundImage={bgImage}
mainImage={mainImage}
imageBg={true}
/>
If you have any doubt, ask here again and I can help you.