React Native - Stack Navigator - Passing stack to API - react-native

I recently started trying to make my first app, have some experience in web design and with JS.
I'm trying to use a Stack Navigator to move around my screens, but I'm struggling to pass the Stack to an API that handles the onPress input, or I believe thats the issue.
I have my home screen, in the centre is a circle button api I installed, and the main.js for the API contains the onPress event. However, whatever I try to plug into the button, it just errors out, so I must be missing something rudimentary. I did try following a few guides and troubleshooting myself but I just can't figure out why.
App.js
import { StatusBar } from 'expo-status-bar';
import React, {Component} from 'react';
import { Button, Image, StyleSheet, Text, View, Dimensions, Alert, ImageBackground } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator, Screen } from '#react-navigation/stack';
import CircleButton from 'react-native-circle-button';
import { LinearGradient } from 'expo-linear-gradient';
import logomain from './assets/LogoMain.png';
import logobackground from './assets/1024.png';
import { HomeScreen } from './Home'
import { CreateScreen } from './Create'
import { ReadScreen } from './Read'
import { SavedScreen } from './Saved'
import { SettingsScreen } from './Settings'
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"
headerMode="none">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Create" component={CreateScreen} />
<Stack.Screen name="Read" component={ReadScreen} />
<Stack.Screen name="Saved" component={SavedScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Home.js
import { StatusBar } from 'expo-status-bar';
import React, { Component } from 'react';
import { Button, Image, StyleSheet, Text, View, Dimensions, Alert, ImageBackground } from 'react-native';
import CircleButton from 'react-native-circle-button';
import { LinearGradient } from 'expo-linear-gradient';
import logomain from './assets/LogoMain.png';
import logobackground from './assets/1024.png';
export function HomeScreen(props: any) {
return (
<View style={styles.container}>
<LinearGradient
colors={['rgba(0,212,255,0.4) 0%', 'rgba(112,128,144,1) 50%', 'rgba(30,40,70,1) 100%']}
start={{ x: 0, y: 0 }}
end={{x: 1, y: 1 }}
paddingLeft={(Dimensions.get('window').width/2)-1}
paddingRight={(Dimensions.get('window').width/2)-1}
>
<View style={styles.containerlogo}>
<Image style={styles.containerbackground} source={logobackground} />
<Image style={styles.logomain} source={logomain} />
</View>
<View style={styles.buttoncontainer}>
<CircleButton
size={Dimensions.get('window').width/3.5}
primaryColor={'#000'}
secondaryColor={'rgba(30,40,70,1)'}
/>
</View>
<StatusBar style="auto" />
</LinearGradient>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
//backgroundColor: '#7488a1',
alignItems: 'center',
justifyContent: 'center',
},
containerbackground: {
width: Dimensions.get('window').width,
resizeMode: 'cover',
alignItems: 'center',
justifyContent: 'center',
opacity: 0.25,
zIndex: 0,
position: 'absolute',
top: -46,
},
containerlogo: {
flex: 2,
alignItems: 'center',
justifyContent: 'center',
paddingTop: 50,
zIndex: 1,
},
logomain: {
height: Dimensions.get('window').width-50,
//backgroundColor: 'rgba(150,150,150,0.7)',
//borderWidth: 7,
//borderColor: 'rgba(150,150,150,0.7)',
width: Dimensions.get('window').width-50,
resizeMode: 'contain',
position: 'absolute',
top: 20,
zIndex: 2,
},
buttoncontainer: {
flex: 1,
alignItems: 'center',
paddingTop: 50,
paddingBottom: 150,
opacity: 1,
zIndex: 1,
},
});
Read.js (placeholder page)
import { StatusBar } from 'expo-status-bar';
import React, {Component} from 'react';
export function ReadScreen(props: any) {
return (
<View style={styles.container}>
<LinearGradient
colors={['rgba(0,212,255,0.4) 0%', 'rgba(112,128,144,1) 50%', 'rgba(30,40,70,1) 100%']}
start={{ x: 0, y: 0 }}
end={{x: 1, y: 1 }}
paddingLeft={(Dimensions.get('window').width/2)-1}
paddingRight={(Dimensions.get('window').width/2)-1}
>
<StatusBar style="auto" />
</LinearGradient>
</View>
);
}
API main.js
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
View,
TouchableOpacity,
StyleSheet,
Image,
Animated,
Easing,
} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import iconAdd from './images/add.png';
import iconSetting from './images/setting.png';
import iconScan from './images/view.png';
import iconPerson from './images/person.png';
import iconAttach from './images/list.png';
class CircleButton extends Component {
constructor() {
super();
this.state = {
isClicked: false,
};
this.rotateAnimated = new Animated.Value(0);
this.scaleAnimated = new Animated.Value(0);
this.bringToBackAnimated = new Animated.Value(0);
this.bringToLeftAnimated = new Animated.Value(0);
this.bringToRightAnimated = new Animated.Value(0);
this.bringToTopAnimated = new Animated.Value(0);
this.bringToBottomAnimated = new Animated.Value(0);
this.fadeAnimated = new Animated.Value(0);
this._buttonCenter = this._buttonCenter.bind(this);
this._buttonTop = this._buttonTop.bind(this);
this._buttonRight = this._buttonRight.bind(this);
this._buttonBottom = this._buttonBottom.bind(this);
this._buttonLeft = this._buttonLeft.bind(this);
}
createAnimation(obj, toValue, duration, easing) {
return Animated.timing(obj, {
toValue,
duration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
}
startAnimation() {
this.createAnimation(this.rotateAnimated, 1, 200);
this.createAnimation(this.scaleAnimated, 1, 200);
this.createAnimation(this.bringToBackAnimated, 1, 150);
this.createAnimation(this.bringToLeftAnimated, 1, 200);
this.createAnimation(this.bringToRightAnimated, 1, 200);
this.createAnimation(this.bringToTopAnimated, 1, 200);
this.createAnimation(this.bringToBottomAnimated, 1, 200);
this.createAnimation(this.fadeAnimated, 1, 200);
}
endAnimation() {
this.createAnimation(this.rotateAnimated, 2, 200);
this.createAnimation(this.scaleAnimated, 0, 200);
this.createAnimation(this.bringToBackAnimated, 0, 2000);
this.createAnimation(this.bringToLeftAnimated, 0, 200);
this.createAnimation(this.bringToRightAnimated, 0, 200);
this.createAnimation(this.bringToTopAnimated, 0, 200);
this.createAnimation(this.bringToBottomAnimated, 0, 200);
this.createAnimation(this.fadeAnimated, 0, 200);
}
_buttonCenter() {
this.startAnimation();
this.setState({isClicked: !this.state.isClicked});
if (this.state.isClicked) this.endAnimation();
}
_buttonTop() {
this.setState({isClicked: !this.state.isClicked});
this.endAnimation();
this.props.onPressButtonTop();
}
_buttonRight() {
this.setState({isClicked: !this.state.isClicked});
this.endAnimation();
this.props.onPressButtonRight();
}
_buttonBottom() {
this.setState({isClicked: !this.state.isClicked});
this.endAnimation();
this.props.onPressButtonBottom();
}
_buttonLeft() {
this.setState({isClicked: !this.state.isClicked});
this.endAnimation();
this.props.onPressButtonLeft();
}
render() {
const {size, primaryColor, secondaryColor} = this.props;
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
},
buttonWrapper: {
right: size * 2 - 10,
},
buttonLeft: {
alignItems: 'center',
justifyContent: 'center',
width: size - 5,
height: size - 5,
borderRadius: 360,
},
buttonRight: {
alignItems: 'center',
justifyContent: 'center',
width: size - 5,
height: size - 5,
borderRadius: 360,
},
buttonCenter: {
alignItems: 'center',
justifyContent: 'center',
width: size,
height: size,
borderRadius: 360,
backgroundColor: primaryColor,
},
buttonTop: {
right: -size * 2 + 7,
alignItems: 'center',
justifyContent: 'center',
width: size - 5,
height: size - 5,
borderRadius: 360,
},
buttonBottom: {
right: size - 7,
alignItems: 'center',
justifyContent: 'center',
width: size - 5,
height: size - 5,
borderRadius: 360,
},
text: {
color: '#EECE69',
fontWeight: 'bold',
letterSpacing: 1,
},
centerImage: {
width: size - 5,
height: size - 5,
},
childImage: {
width: size - 15,
height: size - 15,
},
circle: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 360,
backgroundColor: secondaryColor,
},
});
const rotateMe = this.rotateAnimated.interpolate({
inputRange: [0, 1, 2],
outputRange: ['0deg', '45deg', '0deg'],
});
const scaleMe = this.scaleAnimated.interpolate({
inputRange: [0, 1],
outputRange: [size, size * 3],
});
const bringToBack = this.bringToBackAnimated.interpolate({
inputRange: [0, 1],
outputRange: [99, -1],
});
const bringMeToLeft = this.bringToLeftAnimated.interpolate({
inputRange: [0, 1],
outputRange: [size, 0],
});
const bringMeToRight = this.bringToRightAnimated.interpolate({
inputRange: [0, 1],
outputRange: [0, size],
});
const bringMeToTop = this.bringToTopAnimated.interpolate({
inputRange: [0, 1],
outputRange: [0, -size + 2],
});
const bringMeToBottom = this.bringToBottomAnimated.interpolate({
inputRange: [0, 1],
outputRange: [0, size - 2],
});
const fadeInOut = this.fadeAnimated.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
});
return (
<View style={styles.container}>
<Animated.View
style={[styles.circle, {width: scaleMe, height: scaleMe}]}>
<Animated.View style={{top: bringMeToTop}}>
<TouchableOpacity
onPress={this._buttonTop}
activeOpacity={1}
style={styles.buttonTop}>
<Animated.Image
source={this.props.iconButtonTop}
style={[styles.childImage, {opacity: fadeInOut}]}
/>
</TouchableOpacity>
</Animated.View>
<Animated.View style={{left: bringMeToLeft}}>
<TouchableOpacity
onPress={this._buttonLeft}
activeOpacity={1}
style={styles.buttonLeft}>
<Animated.Image
source={this.props.iconButtonLeft}
style={[styles.childImage, {opacity: fadeInOut}]}
/>
</TouchableOpacity>
</Animated.View>
<Animated.View style={{left: bringMeToRight}}>
<TouchableOpacity
onPress={this._buttonRight}
activeOpacity={1}
style={styles.buttonRight}>
<Animated.Image
source={this.props.iconButtonRight}
style={[styles.childImage, {opacity: fadeInOut}]}
/>
</TouchableOpacity>
</Animated.View>
<Animated.View style={{top: bringMeToBottom}}>
<TouchableOpacity
onPress={this._buttonBottom}
activeOpacity={1}
style={styles.buttonBottom}>
<Animated.Image
source={this.props.iconButtonBottom}
style={[styles.childImage, {opacity: fadeInOut}]}
/>
</TouchableOpacity>
</Animated.View>
<Animated.View
style={[styles.buttonWrapper, {transform: [{rotate: rotateMe}]}]}>
<TouchableOpacity
onPress={this._buttonCenter}
activeOpacity={1}
style={styles.buttonCenter}>
<Animated.Image
source={this.props.iconButtonCenter}
style={styles.centerImage}
/>
</TouchableOpacity>
</Animated.View>
</Animated.View>
</View>
);
}
}
CircleButton.defaultProps = {
size: 40,
onPressButtonTop: () => {navigation.navigate('Create')},
onPressButtonRight: () => {navigation.navigate('Read')},
onPressButtonBottom: () => {navigation.navigate('Saved')},
onPressButtonLeft: () => {navigation.navigate('Settings')},
iconButtonCenter: iconAdd,
iconButtonTop: iconAdd,
iconButtonRight: iconScan,
iconButtonBottom: iconSetting,
iconButtonLeft: iconAttach,
primaryColor: '#41727E',
secondaryColor: '#459186',
};
CircleButton.propTypes = {
size: PropTypes.number,
onPressButtonTop: PropTypes.func,
onPressButtonRight: PropTypes.func,
onPressButtonBottom: PropTypes.func,
onPressButtonLeft: PropTypes.func,
iconButtonCenter: PropTypes.number,
iconButtonTop: PropTypes.number,
iconButtonRight: PropTypes.number,
iconButtonBottom: PropTypes.number,
iconButtonLeft: PropTypes.number,
primaryColor: PropTypes.string,
secondaryColor: PropTypes.string,
};
module.exports = CircleButton;
Believed problem area in API main.js:
onPressButtonTop: () => {navigation.navigate('Create')},
onPressButtonRight: () => {navigation.navigate('Read')},
onPressButtonBottom: () => {navigation.navigate('Saved')},
onPressButtonLeft: () => {navigation.navigate('Settings')},

Solved: Navigation prop isn't passed into the component directly, therefore the onPressButton props need to be declared in the function body instead
<CircleButton
size={Dimensions.get('window').width/3.5}
primaryColor={'#000'}
secondaryColor={'rgba(30,40,70,1)'}
onPressButtonTop={() => {navigation.navigate('Create')}}
onPressButtonRight={() => {navigation.navigate('Read')}}
onPressButtonBottom={() => {navigation.navigate('Saved')}}
onPressButtonLeft={() => {navigation.navigate('Settings')}}
/>

Related

Flipping card, and sliding off/on screen in React Native

I have this example: https://snack.expo.dev/#skjones90/0b47db
...of a card-flipping animation in RN. It seems to work fine (although a bit outdated). But I can't figure out how to get the card to slide off the screen to the left while another slides in from the right.
Is there a simple way to do this without some external library?
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity,
Animated
} from 'react-native';
export default class animatedbasic extends Component {
componentWillMount() {
this.animatedValue = new Animated.Value(0);
this.value = 0;
this.animatedValue.addListener(({ value }) => {
this.value = value;
})
this.frontInterpolate = this.animatedValue.interpolate({
inputRange: [0, 180],
outputRange: ['0deg', '180deg'],
})
this.backInterpolate = this.animatedValue.interpolate({
inputRange: [0, 180],
outputRange: ['180deg', '360deg']
})
this.frontOpacity = this.animatedValue.interpolate({
inputRange: [89, 90],
outputRange: [1, 0]
})
this.backOpacity = this.animatedValue.interpolate({
inputRange: [89, 90],
outputRange: [0, 1]
})
}
flipCard() {
if (this.value >= 90) {
Animated.spring(this.animatedValue,{
toValue: 0,
friction: 8,
tension: 10
}).start();
} else {
Animated.spring(this.animatedValue,{
toValue: 180,
friction: 8,
tension: 10
}).start();
}
}
render() {
const frontAnimatedStyle = {
transform: [
{ rotateY: this.frontInterpolate }
]
}
const backAnimatedStyle = {
transform: [
{ rotateY: this.backInterpolate }
]
}
return (
<View style={styles.container}>
<View>
<Animated.View style={[styles.flipCard, frontAnimatedStyle, {opacity: this.frontOpacity}]}>
<Text style={styles.flipText}>
This text is flipping on the front.
</Text>
</Animated.View>
<Animated.View style={[styles.flipCard, styles.flipCardBack, backAnimatedStyle, {opacity: this.backOpacity}]}>
<Text style={styles.flipText}>
This text is flipping on the back.
</Text>
</Animated.View>
</View>
<TouchableOpacity onPress={() => this.flipCard()}>
<Text>Flip!</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text>Next card</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
flipCard: {
width: 200,
height: 200,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'blue',
backfaceVisibility: 'hidden',
},
flipCardBack: {
backgroundColor: "red",
position: "absolute",
top: 0,
},
flipText: {
width: 90,
fontSize: 20,
color: 'white',
fontWeight: 'bold',
}
});
AppRegistry.registerComponent('animatedbasic', () => animatedbasic);

How to animate increasing height of a View and then on some state change, reverse animation (decreasing height of View)?

I have a button when pressing that, want to increase height of view in an animated way. And then after pressing that button again, want to reverse the animation to get the initial height of view.
I have done animating increasing the height of view but when I give the new state to my component, reverse animation is not happening. How to solve this problem?
This is my screen:
import React, { useEffect, useRef, useState } from "react";
import {
Animated,
Easing,
Pressable,
StyleSheet,
Text,
View,
} from "react-native";
import AnimatedTile from "../components/AnimatedTile";
function Test(props) {
const [start, setStart] = useState(false);
return (
<View style={styles.container}>
<View style={styles.animationContainer}>
<Pressable
android_ripple={{ color: "red" }}
onPress={() => setStart(!start)}
>
<Text>animate</Text>
</Pressable>
<AnimatedTile startAnimation={start} /> // ---->My animated component
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
animationContainer: {
flexDirection: "row",
width: "60%",
height: "20%",
justifyContent: "space-between",
alignItems: "center",
},
});
export default Test;
And this is my animated component:
import React, { useEffect, useRef, useState } from "react";
import {
Animated,
Easing,
Pressable,
StyleSheet,
Text,
View,
} from "react-native";
function AnimatedTile({ startAnimation }) {
const height = new Animated.Value(0);
const isExpanded = useRef(false);
const maxHieght = height.interpolate({
inputRange: [0, 1],
outputRange: isExpanded.current ? [180, 10] : [10, 180],
});
const start = () => {
if (isExpanded.current) {
Animated.timing(height, {
toValue: 0,
duration: 500,
easing: Easing.linear,
useNativeDriver: false,
}).start();
} else {
Animated.timing(height, {
toValue: 1,
duration: 500,
easing: Easing.linear,
useNativeDriver: false,
}).start();
}
isExpanded.current = !isExpanded.current;
};
useEffect(() => {
start();
}, [startAnimation]);
return (
<Animated.View
style={{
width: 5,
height: 120,
maxHeight: maxHieght,
backgroundColor: "dodgerblue",
borderRadius: 5,
}}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
animationContainer: {
flexDirection: "row",
width: "60%",
height: "20%",
justifyContent: "space-between",
alignItems: "center",
},
});
export default AnimatedTile;

I want to add Async Storage to my flatlist in todo list app

I want to add Async Storage to my flatlist in todo list app.
this is my App.js code:
import { StatusBar } from 'expo-status-bar';
import {
StyleSheet,
Text,
View,
KeyboardAvoidingView,
FlatList,
TextInput,
TouchableOpacity,
Keyboard,
} from 'react-native';
import React, { useState, useEffect } from 'react';
import {
Poppins_100Thin,
Poppins_100Thin_Italic,
Poppins_200ExtraLight,
Poppins_200ExtraLight_Italic,
Poppins_300Light,
Poppins_300Light_Italic,
Poppins_400Regular,
Poppins_400Regular_Italic,
Poppins_500Medium,
Poppins_500Medium_Italic,
Poppins_600SemiBold,
Poppins_600SemiBold_Italic,
Poppins_700Bold,
Poppins_700Bold_Italic,
Poppins_800ExtraBold,
Poppins_800ExtraBold_Italic,
Poppins_900Black,
Poppins_900Black_Italic,
} from '#expo-google-fonts/poppins';
import { useFonts } from 'expo-font';
import Task from './components/Task';
import AppLoading from 'expo-app-loading';
export default function App() {
const [task, setTask] = useState();
const [taskItems, setTaskItems] = useState([]);
let [fontsLoaded, error] = useFonts({
Poppins_100Thin,
Poppins_100Thin_Italic,
Poppins_200ExtraLight,
Poppins_200ExtraLight_Italic,
Poppins_300Light,
Poppins_300Light_Italic,
Poppins_400Regular,
Poppins_400Regular_Italic,
Poppins_500Medium,
Poppins_500Medium_Italic,
Poppins_600SemiBold,
Poppins_600SemiBold_Italic,
Poppins_700Bold,
Poppins_700Bold_Italic,
Poppins_800ExtraBold,
Poppins_800ExtraBold_Italic,
Poppins_900Black,
Poppins_900Black_Italic,
});
if (!fontsLoaded) {
return <AppLoading />;
}
const handleAddTask = async () => {
try {
Keyboard.dismiss();
setTaskItems([...taskItems, task]);
setTask('');
} catch (err) {
console.log(err);
}
};
const completeTask = (index) => {
let itemsCopy = [...taskItems];
itemsCopy.splice(index, 1);
setTaskItems(itemsCopy);
};
const deleteItem = (index) => {
let arr = [...taskItems];
arr.splice(index, 1);
setTaskItems(arr);
};
return (
<View style={styles.container}>
{/* Todays Tasks */}
<View style={styles.taskWrapper}>
<Text style={styles.sectionTitle}>Today's Tasks</Text>
<View style={styles.items}>
{/* This is where the tasks will go! */}
<FlatList
data={taskItems}
keyExtractor={(item) => item.id}
renderItem={({ item, index }) => (
<Task text={item} handleDelete={() => deleteItem(index)} />
)}
/>
</View>
</View>
{/* Write a Task */}
<KeyboardAvoidingView style={styles.writeTaskWrapper}>
<TextInput
style={styles.input}
placeholder={'Write A Task'}
value={task}
onChangeText={(text) => setTask(text)}
/>
<TouchableOpacity onPress={() => handleAddTask()}>
<View style={styles.addWrapper}>
<Text style={styles.addText}>+</Text>
</View>
</TouchableOpacity>
</KeyboardAvoidingView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#E8EAED',
},
taskWrapper: {
paddingTop: 80,
paddingHorizontal: 20,
},
sectionTitle: {
fontSize: 24,
backgroundColor: '#fff',
fontFamily: 'Poppins_600SemiBold',
borderRadius: 10,
margin: 'auto',
width: 250,
height: 60,
textAlign: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.2,
shadowRadius: 2,
elevation: 5,
paddingTop: 10,
},
items: {
marginTop: 30,
},
writeTaskWrapper: {
position: 'absolute',
bottom: 60,
width: '100%',
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
},
input: {
paddingVertical: 15,
paddingHorizontal: 15,
backgroundColor: '#fff',
borderRadius: 60,
width: 250,
fontFamily: 'Poppins_400Regular',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.5,
shadowRadius: 2,
elevation: 3,
},
addWrapper: {
width: 60,
height: 60,
backgroundColor: '#fff',
borderRadius: 60,
justifyContent: 'center',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.5,
shadowRadius: 2,
elevation: 3,
},
addText: {},
});
THIS IS MY TASK.JS CODE:
import React from 'react';
import {View,Text,StyleSheet,Dimensions,Animated,TouchableOpacity} from 'react-native';
import AppLoading from 'expo-app-loading'
import {
Poppins_100Thin,
Poppins_100Thin_Italic,
Poppins_200ExtraLight,
Poppins_200ExtraLight_Italic,
Poppins_300Light,
Poppins_300Light_Italic,
Poppins_400Regular,
Poppins_400Regular_Italic,
Poppins_500Medium,
Poppins_500Medium_Italic,
Poppins_600SemiBold,
Poppins_600SemiBold_Italic,
Poppins_700Bold,
Poppins_700Bold_Italic,
Poppins_800ExtraBold,
Poppins_800ExtraBold_Italic,
Poppins_900Black,
Poppins_900Black_Italic
} from '#expo-google-fonts/poppins'
import {useFonts} from 'expo-font'
import Swipeable from 'react-native-gesture-handler/Swipeable';
const SCREEN_WIDTH = Dimensions.get('window').width;
const Task = (props) => {
let [fontsLoaded,error]=useFonts({
Poppins_100Thin,
Poppins_100Thin_Italic,
Poppins_200ExtraLight,
Poppins_200ExtraLight_Italic,
Poppins_300Light,
Poppins_300Light_Italic,
Poppins_400Regular,
Poppins_400Regular_Italic,
Poppins_500Medium,
Poppins_500Medium_Italic,
Poppins_600SemiBold,
Poppins_600SemiBold_Italic,
Poppins_700Bold,
Poppins_700Bold_Italic,
Poppins_800ExtraBold,
Poppins_800ExtraBold_Italic,
Poppins_900Black,
Poppins_900Black_Italic
})
if (!fontsLoaded){
return <AppLoading/>
}
const leftSwipe = (progress, dragX) => {
const scale = dragX.interpolate({
inputRange: [0, 100],
outputRange: [0, 1],
extrapolate: 'clamp',
});
return (
<TouchableOpacity onPress={props.handleDelete} activeOpacity={0.6}>
<View style={styles.deleteBox}>
<Animated.Text style={{transform: [{scale: scale}],color:'#fff',fontFamily:"Poppins_400Regular",fontSize:18}}>
Delete
</Animated.Text>
</View>
</TouchableOpacity>
);
};
return(
<Swipeable renderLeftActions={leftSwipe}>
<View style={styles.item}>
<View style={styles.itemLeft}>
<View style={styles.square}>
</View>
<Text style={styles.itemText}>
{props.text}
</Text>
</View>
<View style={styles.circular}>
</View>
</View>
</Swipeable>
)
}
const styles = StyleSheet.create({
item:{
backgroundColor:'white',
padding:15,
borderRadius:10,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom:20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.5,
shadowRadius: 2,
elevation: 3
},
itemLeft:{
flexDirection: 'row',
alignItems: 'center',
flexWrap:'wrap',
},
square:{
width:24,
height:24,
backgroundColor:'#55BCF6',
opacity:0.5,
borderRadius:5,
marginRight:15,
},
itemText:{
maxWidth:'80%',
fontFamily:'Poppins_400Regular'
},
circular:{
width:12,
height:12,
borderColor:'#55BCF6',
borderWidth:2,
borderRadius:5
},
deleteBox:{
backgroundColor:'red',
justifyContent:'center',
alignItems:'center',
width:100,
height:55,
borderRadius:10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.5,
shadowRadius: 2,
elevation: 5,
}
});
export default Task;
i am learning react native so i dont know much about it
so i want to add async storage such that its shows the tasks which are created after re-opening the app
kindly help with providing code
and yeah i have used expo and swipeable for deleting the tasks
import async-storage
import AsyncStorage from '#react-native-async-storage/async-storage';
get stored task
const task await AsyncStorage.getItem('task')
if(task!=null)
switch(task{
... your cases ...
set a task
await AsyncStorage.setItem('task', 'taskName')
in case refreshing task
await AsyncStorage.removeItem('keyName')

Rect-native Reanimated(v2) interpolate translateY

I am trying to create an animation where the red bar will move along y-axis in an infinite & reverse animation. For some reason, I can not figure out and not able to achieve the desired behavior. Any assistance will be greatly appreciated.
import Animated, {
useAnimatedStyle,
useSharedValue,
interpolate,
withTiming,
withRepeat,
Extrapolate,
} from 'react-native-reanimated';
export default CustomMarker = () => {
const bar = useSharedValue(0);
const barStyle = useAnimatedStyle(() => {
const yValue = interpolate(bar.value, [0, 1], [0, 225]);
return {
transform: [{ translateY: yValue }],
};
});
useEffect(() => {
bar.value = withRepeat(withTiming(1, { duration: 800 }), -1, true);
});
return (
<View
style={{
backgroundColor: COLORS.darkOverlay,
height: 540,
alignItems: 'center',
justifyContent: 'center',
}}>
<View style={styles.rectangleStyle}>
<Animated.View style={[styles.redBarStyle, barStyle]} />
</View>
</View>
);
};
const styles = Stylesheet.create({
rectangleStyle: {
height: 230,
width: 400,
alignItems: 'center',
justifyContent: 'center',
},
redBarStyle: {
position: 'absolute',
top: 0,
height: 10,
width: 225,
backgroundColor: 'red',
borderRadius: 5,
},
})

Hide TabNavigators and Header on Scroll

I want to hide the Header and the TabNavigator tabs onScroll. How do I do that? I want to hide them onScroll and show them on ScrollUp. My code:
import React, { Component } from 'react';
import { View, Text, ScrollView, StyleSheet, TouchableOpacity} from 'react-native';
class ScrollTest extends Component {
render(){
const { params } = this.props.navigation.state;
return(
<View style={styles.container}>
<ScrollView>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
</ScrollView>
</View>
)
}
}
const styles = StyleSheet.create({
container:{
flex:1, padding:5
},
newView:{
height: 200, backgroundColor:'green', margin:10
}
})
export default ScrollTest;
I checked this link for Animated API but not able to figureout how to implement it in onScoll?
So the header HomeScreen and the tabs Tab1 and Tab2 should hide on scroll and show when scrolled up. How do I do that?
Please help getting started on this.
Many thanks.
I was also stuck with the same animation thing, I tried this code for maximizing and minimizing the header using the Animated API of react-native.
You can also do the same for showing and hiding it.
import React, { Component } from 'react';
import { Text, View, StyleSheet, ScrollView, Image,Animated } from 'react-native';
const HEADER_MAX_HEIGHT = 200;// set the initial height
const HEADER_MIN_HEIGHT = 60;// set the height on scroll
const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scrollY: new Animated.Value(0),
};
}
render() {
const headerHeight = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [HEADER_MAX_HEIGHT,HEADER_MIN_HEIGHT],
extrapolate: 'clamp',
});
return(
<View style={{flex: 1}}>
<ScrollView
scrollEventThrottle={1}
onScroll={Animated.event(
[{nativeEvent:
{contentOffset: {y: this.state.scrollY}}}]
)}>
<View style={styles.container}>
<Text style={styles.paragraph}>hello</Text>
<Image source={{uri: "https://static.pexels.com/photos/67843/splashing-splash-aqua-water-67843.jpeg"}} style={styles.imageStyle}/>
<Image source={{uri: "https://www.elastic.co/assets/bltada7771f270d08f6/enhanced-buzz-1492-1379411828-15.jpg" }}
style={styles.imageStyle}/>
</View>
</ScrollView>
<Animated.View style={[styles.footer, {height: headerHeight}]}>
<View style={styles.bar}>
<Text>text here</Text>
</View>
</Animated.View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 24,
backgroundColor: '#ecf0f1',
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
imageStyle: {
height: 360,
width: '100%',
},
footer: {
position:'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: 'red',
},
bar: {
alignItems: 'center',
justifyContent: 'center',
},
});
Hope this helps someone.
I resolved for my case, hope this will be helpful
import React from 'react';
import {
Animated,
Text,
View,
StyleSheet,
ScrollView,
Dimensions,
RefreshControl,
} from 'react-native';
import Constants from 'expo-constants';
import randomColor from 'randomcolor';
const HEADER_HEIGHT = 44 + Constants.statusBarHeight;
const BOX_SIZE = Dimensions.get('window').width / 2 - 12;
const wait = (timeout: number) => {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
};
function App() {
const [refreshing, setRefreshing] = React.useState(false);
const scrollAnim = new Animated.Value(0);
const minScroll = 100;
const clampedScrollY = scrollAnim.interpolate({
inputRange: [minScroll, minScroll + 1],
outputRange: [0, 1],
extrapolateLeft: 'clamp',
});
const minusScrollY = Animated.multiply(clampedScrollY, -1);
const translateY = Animated.diffClamp(minusScrollY, -HEADER_HEIGHT, 0);
const onRefresh = React.useCallback(() => {
setRefreshing(true);
wait(2000).then(() => {
setRefreshing(false);
});
}, []);
return (
<View style={styles.container}>
<Animated.ScrollView
contentContainerStyle={styles.gallery}
scrollEventThrottle={1}
bounces={true}
showsVerticalScrollIndicator={false}
style={{
zIndex: 0,
height: '100%',
elevation: -1,
}}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: scrollAnim } } }],
{ useNativeDriver: true }
)}
overScrollMode="never"
contentInset={{ top: HEADER_HEIGHT }}
contentOffset={{ y: -HEADER_HEIGHT }}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}>
{Array.from({ length: 20 }, (_, i) => i).map((uri) => (
<View style={[styles.box, { backgroundColor: 'grey' }]} />
))}
</Animated.ScrollView>
<Animated.View style={[styles.header, { transform: [{ translateY }] }]}>
<Text style={styles.title}>Header</Text>
</Animated.View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
gallery: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 4,
},
box: {
height: BOX_SIZE,
width: BOX_SIZE,
margin: 4,
},
header: {
flex: 1,
height: HEADER_HEIGHT,
paddingTop: Constants.statusBarHeight,
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: randomColor(),
},
title: {
fontSize: 16,
},
});
export default App;
checkout on Expo https://snack.expo.io/#raksa/auto-hiding-header