Related
There are 2 gradients, when I press the inactive one, I want the
active one to slowly shift the color of the other, how can I do that?
import React, { useState } from "react";
import { StyleSheet, Text, View, TouchableOpacity,Button } from "react-native";
import LinearGradient from 'react-native-linear-gradient';
import Animated, {useSharedValue,useAnimatedStyle,} from 'react-native-reanimated';
const atciveTab = ['#0067FF', '#00C2FF']
const inactiveTab = ['rgba(0,0,0,0)', 'rgba(0,0,0,0)']
const App = () => {
const [selectedTab, setSelectedTab] = useState({
tickets: true,
collectibles: false
})
const selectTicketTab = () => {
setSelectedTab({
tickets: true,
collectibles: false
})
}
const selectCollectiblesTab = () => {
setSelectedTab({
tickets: false,
collectibles: true
})
}
const offset = useSharedValue(0);
const animatedStyles = useAnimatedStyle(() => {
return {
transform: [{ translateX: offset.value * 255 }],
};
});
The gradient in the background will scroll when I click on it.
return (
<View style={styles.container}>
<TouchableOpacity
onPress={selectTicketTab}
style={styles.mainview}>
<LinearGradient
style={styles.ticketTab}
colors={selectedTab.tickets ? atciveTab : inactiveTab}
start={{ x: 1, y: 2 }}
end={{ x: 0, y: 0 }}
>
<Text style={styles.text}>Tickets</Text>
</LinearGradient>
</TouchableOpacity>
<TouchableOpacity
onPress={selectCollectiblesTab}
style={styles.mainview2}>
<LinearGradient
style={styles.collectiblesTab}
colors={selectedTab.collectibles ? atciveTab : inactiveTab}
start={{ x: 1, y: 2 }}
end={{ x: 0, y: 0 }}
>
<Text style={styles.text}>Collectibles</Text>
</LinearGradient>
</TouchableOpacity>
<Animated.View style={[styles.box, animatedStyles]} />
<Button onPress={() => (offset.value = Math.random())} title="Move" />
</View>
)
}
export default App;
I want the background color to be transferred to the other by sliding
slowly I tried many ways but I couldn't
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
padding: 20,
backgroundColor: '#050035',
flex: 1,
justifyContent: 'center'
},
text: {
fontWeight: '400',
color: 'white',
textAlign: 'center',
padding: 10,
fontSize: 14,
letterSpacing: 0.1,
},
mainview: {
width: 163,
gap: 10,
backgroundColor: 'rgba(209, 214, 219, 0.1)',
height: 40,
borderTopLeftRadius: 8,
borderBottomLeftRadius: 8,
},
mainview2: {
width: 163,
gap: 10,
backgroundColor: 'rgba(209, 214, 219, 0.1)',
marginLeft: 3,
height: 40,
borderTopRightRadius: 8,
borderBottomRightRadius: 8,
},
ticketTab: {
borderTopLeftRadius: 8,
borderBottomLeftRadius: 8,
},
collectiblesTab: {
borderTopRightRadius: 8,
borderBottomRightRadius: 8,
},
box: {
width: 150,
height: 150,
backgroundColor: 'red'
}
})
Today I want to make an animation to be determined by the user. In my example is when the user moves the square close and hit the red rectangle for example to write something in console. But i don't know how to calculate distance to the rectangle and I can't determine when the square touched the rectangle? So my code sa far -
import React from "react";
import { StyleSheet, View } from "react-native";
import {
GestureHandlerRootView,
PanGestureHandler,
PanGestureHandlerGestureEvent,
} from "react-native-gesture-handler";
import Animated, {
useAnimatedGestureHandler,
useAnimatedStyle,
useSharedValue,
withSpring,
withTiming,
} from "react-native-reanimated";
const SIZE = 100.0;
const CIRCLE_RADIUS = SIZE * 2;
type ContextType = {
translateX: number;
translateY: number;
size: number;
};
export default function App() {
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const size = useSharedValue(100);
const panGestureEvent = useAnimatedGestureHandler<
PanGestureHandlerGestureEvent,
ContextType
>({
onStart: (event, context) => {
context.translateX = translateX.value;
context.translateY = translateY.value;
size.value = 122;
},
onActive: (event, context) => {
translateX.value = event.translationX + context.translateX;
translateY.value = event.translationY + context.translateY;
},
onEnd: () => {
const distance = Math.sqrt(translateX.value ** 2 + translateY.value ** 2);
size.value = 100;
if (distance < CIRCLE_RADIUS + SIZE / 2) {
translateX.value = withSpring(30);
translateY.value = withSpring(50);
}
},
});
const rStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateX: translateX.value,
},
{
translateY: translateY.value,
},
],
width: withTiming(size.value, { duration: 160 }),
height: withTiming(size.value, { duration: 160 }),
};
});
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<View style={styles.container}>
<View style={styles.circle}>
<PanGestureHandler onGestureEvent={panGestureEvent}>
<Animated.View
style={[
{
width: size.value,
height: size.value,
backgroundColor: "rgba(0, 0, 256, 0.5)",
borderRadius: 20,
},
rStyle,
]}
/>
</PanGestureHandler>
</View>
<View
style={{ width: 30, height: 50, backgroundColor: "red", top: 80 }}
></View>
</View>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
circle: {
width: CIRCLE_RADIUS * 2,
height: CIRCLE_RADIUS * 2,
alignItems: "center",
justifyContent: "center",
borderRadius: CIRCLE_RADIUS,
borderWidth: 5,
borderColor: "rgba(0, 0, 256, 0.5)",
},
});
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')
I am now using react-native-qrcode-scanner to read the QRcode but now have trouble when trying to add the text inside of the camera view. (Not top or bottom of the camera view but inside of it - more exactly under the marker position with align center)
The text is not displayed even though I add Text field with position: 'absolute'
import QRCodeScanner from 'react-native-qrcode-scanner';
return (
<QRCodeScanner
onRead={onSuccess}
reactivate={true}
showMarker
containerStyle={styles.cameraContainer}
cameraStyle={{
...styles.camera,
height: Dimensions.get('window').height - topOffset,
}}
topViewStyle={styles.topView}
markerStyle={styles.marker}
bottomViewStyle={styles.bottomView}
cameraProps={{
type: 'back',
}}
/>
);
const styles = StyleSheet.create({
cameraContainer: {
backgroundColor: theme.colors.background,
},
camera: {},
bottomView: {
height: 0,
flex: 0,
},
topView: {
height: 0,
flex: 0,
},
marker: {
borderWidth: 2,
borderRadius: 10,
borderColor: theme.colors.white,
}
});
You can use styling with position: absolute for the text element within a container.
Following sample works for me on iOS:
/* eslint-disable react-native/no-color-literals */
// #ts-nocheck
import React from "react"
// eslint-disable-next-line react-native/split-platform-components
import { View, StyleSheet, TouchableOpacity, Text, ToastAndroid } from "react-native"
import QRCodeScanner from "react-native-qrcode-scanner"
import { RNCamera } from "react-native-camera"
import Clipboard from "#react-native-community/clipboard"
const styles = StyleSheet.create({
cameraContainer: {
flex: 1,
},
container: {
backgroundColor: "#fff",
flex: 1,
height: "100%",
width: "100%",
},
flash: {
alignItems: "center",
backgroundColor: "#CCC",
borderRadius: 19,
height: 38,
justifyContent: "center",
position: "absolute",
right: 20,
top: 20,
width: 100,
zIndex: 1,
},
markerStyle: {
borderColor: "#ffffff",
top: -40,
},
})
export const BarcodeScannerScreen: React.FC = () => {
const [flashOn, setFlashOn] = React.useState(false)
const barcodeScanned = (barcode) => {
ToastAndroid.show("Code copied to clipboard", ToastAndroid.LONG)
Clipboard.setString(JSON.stringify(barcode.data))
console.log("Barcode: ", barcode.data)
}
const toggleFlash = () => {
setFlashOn(!flashOn)
}
const androidCameraPermissionOptions = {
title: "Camera permission required",
message: "To test QR-Code scan camera permission is required",
}
return (
<View style={styles.container}>
<TouchableOpacity style={styles.flash} onPress={toggleFlash}>
<Text>Flash on</Text>
</TouchableOpacity>
<QRCodeScanner
onRead={barcodeScanned}
cameraProps={{
androidCameraPermissionOptions: androidCameraPermissionOptions,
flashMode: flashOn
? RNCamera.Constants.FlashMode.torch
: RNCamera.Constants.FlashMode.off,
barCodeTypes: [RNCamera.Constants.BarCodeType.qr],
type: RNCamera.Constants.Type.back,
}}
showMarker={true}
reactivate={true}
reactivateTimeout={3000}
cameraStyle={styles.cameraContainer}
markerStyle={styles.markerStyle}
/>
<View
style={{
position: "absolute",
alignSelf: "center",
top: 300,
width: 50,
height: 50,
backgroundColor: "#ff00ff",
}}
>
<Text>Text</Text>
</View>
</View>
)
}
/* eslint-disable react-native/no-color-literals */
// #ts-nocheck
import React from "react"
// eslint-disable-next-line react-native/split-platform-components
import { View, StyleSheet, TouchableOpacity, Text, ToastAndroid } from "react-native"
import QRCodeScanner from "react-native-qrcode-scanner"
import { RNCamera } from "react-native-camera"
import Clipboard from "#react-native-community/clipboard"
const styles = StyleSheet.create({
cameraContainer: {
flex: 1,
},
container: {
backgroundColor: "#fff",
flex: 1,
height: "100%",
width: "100%",
},
flash: {
alignItems: "center",
backgroundColor: "#CCC",
borderRadius: 19,
height: 38,
justifyContent: "center",
position: "absolute",
right: 20,
top: 20,
width: 100,
zIndex: 1,
},
markerStyle: {
borderColor: "#ffffff",
top: -40,
},
})
export const BarcodeScannerScreen: React.FC = () => {
const [flashOn, setFlashOn] = React.useState(false)
const barcodeScanned = (barcode) => {
ToastAndroid.show("Code copied to clipboard", ToastAndroid.LONG)
Clipboard.setString(JSON.stringify(barcode.data))
console.log("Barcode: ", barcode.data)
}
const toggleFlash = () => {
setFlashOn(!flashOn)
}
const androidCameraPermissionOptions = {
title: "Camera permission required",
message: "To test QR-Code scan camera permission is required",
}
return (
<View style={styles.container}>
<TouchableOpacity style={styles.flash} onPress={toggleFlash}>
<Text>Flash on</Text>
</TouchableOpacity>
<QRCodeScanner
onRead={barcodeScanned}
cameraProps={{
androidCameraPermissionOptions: androidCameraPermissionOptions,
flashMode: flashOn
? RNCamera.Constants.FlashMode.torch
: RNCamera.Constants.FlashMode.off,
barCodeTypes: [RNCamera.Constants.BarCodeType.qr],
type: RNCamera.Constants.Type.back,
}}
showMarker={true}
reactivate={true}
reactivateTimeout={3000}
cameraStyle={styles.cameraContainer}
markerStyle={styles.markerStyle}
/>
<View
style={{
position: "absolute",
alignSelf: "center",
top: 300,
width: 50,
height: 50,
backgroundColor: "#ff00ff",
}}
>
<Text>Text</Text>
</View>
</View>
)
}
I'm creating a touchable button in react native with an animation. When the button is pressed, it should scale down a little bit. When the pressure is released, it should scale back to normal.
This is my code:
export const TouchableButton = (props) => {
const { onPress, text, icon } = props
const animatedValue = new Animated.Value(0)
const animatedValueInterpolateScale = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [1, 0.95]
})
const pressInHandler = () => {
Animated.timing(
animatedValue,
{
toValue: 1,
duration: 150
}
).start()
}
const pressOutHandler = () => {
Animated.timing(
animatedValue,
{
toValue: 0,
duration: 150
}
).start()
}
return (
<TouchableWithoutFeedback onPress={onPress} onPressIn={pressInHandler} onPressOut={pressOutHandler}>
<View style={{ alignItems: 'center' }}>
<Animated.View style={{ width: '100%', height: 40, borderRadius: 5, overflow: 'hidden', transform: [{ scaleX: animatedValueInterpolateScale }, { scaleY: animatedValueInterpolateScale }] }}>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: Color.GrayLight }}>
<Text style={{ marginTop: 2.5, fontFamily: 'AlegreyaSans-Medium', fontSize: 15, color: Color.White }}>{text}</Text>
<View style={{ position: 'absolute', left: 12.5, top: 12.5 }}>
<Icon lib={icon.lib} icon={icon.icon} color={Color.White} size={15} />
</View>
</View>
</Animated.View>
</View>
</TouchableWithoutFeedback>
)
}
When the button is pressed, the animation in pressInHandler is started, and the scale is animated from 1 to 0.95. This works. But when I release the pressure (onPressOut is called), the scale snaps back to 1 without a smooth animation. It seems like pressOutHandler (and the animation in it) never is called.
I have another button with the same properties but instead of scaling I set the background color, and this works like it should.
Make it simple.
Note: ALWAYS USE useNativeDriver: true
const App = () => {
const animation = new Animated.Value(0);
const inputRange = [0, 1];
const outputRange = [1, 0.8];
const scale = animation.interpolate({inputRange, outputRange});
const onPressIn = () => {
Animated.spring(animation, {
toValue: 1,
useNativeDriver: true,
}).start();
};
const onPressOut = () => {
Animated.spring(animation, {
toValue: 0,
useNativeDriver: true,
}).start();
};
return (
<View style={styles.container}>
<Animated.View style={[styles.button, {transform: [{scale}]}]}>
<TouchableOpacity
style={styles.btn}
activeOpacity={1}
onPressIn={onPressIn}
onPressOut={onPressOut}>
<Text style={styles.btnText}>BUTTON</Text>
</TouchableOpacity>
</Animated.View>
</View>
);
};
export default App;
const styles = StyleSheet.create({
container: {flex: 1, alignItems: 'center', justifyContent: 'center'},
button: {
height: 70,
width: 200,
backgroundColor: 'red',
marginBottom: 20,
borderRadius: 10,
},
btn: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
btnText: {
color: '#fff',
fontSize: 25,
},
});
Here is a pretty simple solution without any animations which looks almost as native (at least on iOS):
import React from "react"
import { Pressable, PressableProps, StyleProp, ViewStyle } from "react-native"
type TouchableButtonProps = PressableProps & {
scale?: number;
style?: StyleProp<ViewStyle>;
}
const PressableScale: React.FC<TouchableButtonProps> = ({ scale, style, children, ...otherProps }) => {
return (
<Pressable style={({ pressed }) => [style, { transform: [{ scale: pressed ? (scale ?? 0.98) : 1 }] }]} {...otherProps}>
{children}
</Pressable>
)
}
Usage:
<PressableScale style={{ flex: 1, justifyContent: 'center', alignContent: 'center', backgroundColor: 'black', padding: 50, borderRadius: 12 }}>
<Text style={{ color: 'white' }}>This is pressable button</Text>
</PressableScale>