Creating an AnimatedTextInput causes the keyboard to close immediately - android

I'm having trouble getting an AnimatedTextInput to work properly where a normal TextInput works properly. When I press the TextInput to start typing, there are no problems, and I can start typing immediately. However, on an AnimatedTextInput, the software keyboard closes immediately.
So, this works just fine:
return (
<View>
<TextInput style={[style, styles.input, { paddingTop: 20, paddingBottom: 20 }]} {...restOfProps} onFocus={() => handleFocus()} onBlur={handleBlur} ref={refInput} />
<Animated.View style={[styles.labelContainer, { opacity: opacity}]}>
<Text style={styles.label}>{label}</Text>
</Animated.View>
</View>
)
However this:
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput)
return (
<View>
<AnimatedTextInput style={[style, styles.input, { paddingTop: paddingTop, paddingBottom: paddingBottom }]} {...restOfProps} onFocus={() => handleFocus()} onBlur={handleBlur} ref={refInput} />
<Animated.View style={[styles.labelContainer, { opacity: opacity}]}>
<Text style={styles.label}>{label}</Text>
</Animated.View>
</View>
)
Immediately causes the software keyboard to quickly open then close when touching the input to gain focus/to start typing. On searching, answers I've seen say this is related to being part of a scrollview, but this happens whether in a scrollview or not.
For reference, here's the entire file:
import React, { useRef } from 'react';
import { Animated, StyleSheet, Text, TextInput, View } from 'react-native';
const styles = StyleSheet.create({
input: {
padding: 24,
borderColor: 'transparent',
borderWidth: 1,
borderRadius: 4,
fontFamily: 'Avenir-Medium',
fontSize: 16,
backgroundColor: '#F8F8F8',
},
labelContainer: {
position: 'absolute',
left: 16,
top: 9,
paddingHorizontal: 8,
},
label: {
color: '#ABB4BD',
fontFamily: 'Avenir-Heavy',
fontSize: 12,
},
})
// extend from native TextInput props
const TextField = (props) => {
const { label, style, ...restOfProps } = props;
const [isFocused, setIsFocused] = React.useState(false);
const opacity = useRef(new Animated.Value(0)).current;
const paddingTop = useRef(new Animated.Value(20)).current;
const paddingBottom = useRef(new Animated.Value(20)).current;
const refInput = useRef();
React.useEffect(() => {
Animated.timing(
paddingBottom,
{
useNativeDriver: false,
toValue: isFocused ? 10 : 20,
duration: 200,
}
).start();
Animated.timing(
paddingTop,
{
useNativeDriver: false,
toValue: isFocused ? 30 : 20,
duration: 200,
}
).start();
Animated.timing(
opacity,
{
useNativeDriver: false,
toValue: isFocused ? 1 : 0,
duration: 200,
}
).start();
}, [isFocused])
const handleFocus = (input) => {
console.log('here')
setIsFocused(true);
}
const handleBlur = () => {
console.log('there')
setIsFocused(false);
}
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput)
return (
<View>
<AnimatedTextInput style={[style, styles.input, { paddingTop: paddingTop, paddingBottom: paddingBottom }]} {...restOfProps} onFocus={() => handleFocus()} onBlur={handleBlur} ref={refInput} />
<Animated.View style={[styles.labelContainer, { opacity: opacity}]}>
<Text style={styles.label}>{label}</Text>
</Animated.View>
</View>
)
};
export default TextField;

Related

ReactNative animation is not working after the api call

here is my code.
const actionButtonsAnimated = new Animated.Value(0);
const animated = new Animated.Value(255);
const animateTrendingCardSheet = () => {
Animated.timing(animated, {
toValue: 0,
duration: 1500,
useNativeDriver: true,
}).start();
Animated.timing(actionButtonsAnimated, {
toValue: -180,
duration: 1000,
useNativeDriver: true,
}).start();
};
<Animated.View
style={[
{
transform: [{ translateY: actionButtonsAnimated }],
},
]}
>
<MainActionButtons />
</Animated.View>
<Animated.View
style={[
{
transform: [{ translateY: animated }],
width: "100%",
position: "absolute",
bottom: 0,
},
]}
>
<View style={styles.trendingCards}>
<Text h5 center color={colors.trendingText}>
Trending in your area...
</Text>
<View style={styles.flatlistWrapper}>
<FlatList
horizontal={true}
data={trendingCards}
renderItem={({ item }) => <TrendingCardComponent card={item} />}
/>
</View>
</View>
</Animated.View>
so if i call the animateTrendingCardSheet function inside useEffect like this.
useEffect(() => {
animateTrendingCardSheet()
}, [])
it works as expected but once i put it in a condition that it should be called after the API call has been finished it does not work at all if i again save the file it hot reload animation works
useEffect(() => {
if (loadTrendingCard) {
animateTrendingCardSheet();
}
}, [loadTrendingCard]);
Your issue is that after the first call to animateTrendingCardSheet the toValue that you are animating to is the current value of your Animated variables; so it looks like nothing is happening. You can counteract this by resetting your animation variables before calling your animation function:
import * as React from 'react';
import {
Text,
View,
StyleSheet,
Animated,
TouchableOpacity,
FlatList,
Button
} from 'react-native';
import Constants from 'expo-constants';
const MainActionButtons = () => {
return (
<View
style={{
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
}}>
<TouchableOpacity>Btn 1</TouchableOpacity>
<TouchableOpacity>Btn 2</TouchableOpacity>
<TouchableOpacity>Btn 3</TouchableOpacity>
<TouchableOpacity>Btn 4</TouchableOpacity>
</View>
);
};
const TrendingCardComponent = ({ card }) => {
return (
<View style={{ width: '100%' }}>
<Text>{card.title}</Text>
<Text>{card.message}</Text>
</View>
);
};
const trendingCards = [
{ title: 'A Cool Card', message: 'A cool message' },
{ title: 'Card 1', message: 'A cool message' },
{ title: 'A Cool Card', message: 'A cool message' },
{ title: 'A Cool Card', message: 'A cool message' },
];
const initialActionButton = 0;
const initialAnimated = 255;
export default function App() {
const actionButtonsAnimated = new Animated.Value(initialActionButton);
const animated = new Animated.Value(initialAnimated);
const opacity = new Animated.Value(1)
const onApiCall = ()=>{
// set opacity to 0
Animated.timing(opacity,{toValue:0,duration:500}).start(()=>{
// when view is invisible do resets
animated.setValue(initialAnimated)
actionButtonsAnimated.setValue(initialActionButton)
Animated.timing(opacity,{toValue:1,duration:500}).start()
animateTrendingCardSheet()
})
}
const animateTrendingCardSheet = () => {
Animated.timing(animated, {
toValue: 0,
duration: 1500,
useNativeDriver: true,
}).start();
Animated.timing(actionButtonsAnimated, {
toValue: -180 ,
duration: 1000,
useNativeDriver: true,
}).start();
};
// React.useEffect(() => {
// animateTrendingCardSheet();
// }, []);
return (
<View style={styles.container}>
<Button title="Simulate API call" onPress={onApiCall}/>
<Animated.View
style={[
{
transform: [{ translateY: actionButtonsAnimated }],
opacity
},
]}>
<MainActionButtons />
</Animated.View>
<Animated.View
style={[
{
transform: [{ translateY: animated }],
width: '100%',
position: 'absolute',
bottom: 0,
opacity
},
]}>
<View style={styles.trendingCards}>
<Text>Trending in your area...</Text>
<View style={styles.flatlistWrapper}>
<FlatList
style={{ flex: 1 }}
horizontal={true}
data={trendingCards}
renderItem={({ item }) => <TrendingCardComponent card={item} />}
/>
</View>
</View>
</Animated.View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
flatlistWrapper: {
width: '100%',
height: 200,
},
});
Demo
The above answer is good but it does not solve my problem, its all due to a stupid mistake, the issue was i was setting the state before calling the animation call function, as the state changes and it interfere the animation i had to use useRef like this.
const actionButtonsAnimated = useRef(new Animated.Value(initialActionButton)).current;
const animated = useRef(new Animated.Value(initialAnimated)).current;
it reference the state and animation works as expected.

Blur doesn't work correctly on Android #react-native-community/blur

On Android elements wrapped in BlurVIew don't positioning right.
It works on iOS devices fine. But on Android, elements wrapped in <BlurView>{children}</BlurView> run into each other. Screenshot is below
Sometimes when I change something in styles in dev mode, it works correctly, but when I build apk, bug appears again.
How can I fix it on Android?
Code
const BottomNavigationTabs: React.FC<BottomTabBarProps> = ({
descriptors,
state,
navigation,
}) => {
const focusedOptions = descriptors[state.routes[state.index].key].options;
return (
<>
<BlurView blurType="light"
blurAmount={15} style={{ height: 85, width: '100%', position: 'absolute', bottom: 0, }}>
<View style={{ display: 'flex', flexDirection: 'row', position: 'absolute', bottom: 0, justifyContent: 'space-between' }}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const focusedColor = isFocused ? colors.text1 : colorsOld.black;
//Weird snippet, to render passed icon just call function with any return value, then just set color
const icon =
options.tabBarIcon &&
React.cloneElement(
//#ts-ignore
options.tabBarIcon((props: any) => props),
{ color: focusedColor }
);
const onPress = () => {
const event = navigation.emit({
type: "tabPress",
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};
const onLongPress = () => {
navigation.emit({
type: "tabLongPress",
target: route.key,
});
};
const tabBtn = (
<TouchableOpacity
accessibilityRole="button"
accessibilityState={isFocused ? { selected: true } : {}}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}
onPress={onPress}
style={styles.tabButton}
onLongPress={onLongPress}
activeOpacity={0.7}
key={route.key}
>
<View style={styles.tabItem}>
<View style={styles.tabItemIcon}>{icon}</View>
<Text style={{ ...styles.tabItemLabel, color: focusedColor }}>
{label}
</Text>
</View>
</TouchableOpacity>
);
return tabBtn;
})}
</View>
</BlurView>
</>
);
};
const styles = StyleSheet.create({
container: {
alignItems: "center",
justifyContent: "center",
paddingTop: 9,
paddingBottom: 15,
},
tabButton: {
paddingTop: 8,
paddingBottom: 15,
paddingHorizontal: 10,
borderRadius: 10,
zIndex: 10000
},
tabsContainer: {
backgroundColor: colors.secondaryBg(0.5),
width: "100%",
left: 0,
bottom: 0,
zIndex: 999,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-around",
},
tabItem: {
justifyContent: "center",
alignItems: "center",
},
tabItemIcon: {
marginBottom: 6,
},
tabItemLabel: {
fontSize: 12,
fontFamily: "Inter-Medium",
},
});
Found a solution here https://github.com/Kureev/react-native-blur/issues/483#issuecomment-1199210714.
Solution is to not set to <BlurView> position: absolute and to not wrapping anything with it. In my case looks like:
import React from "react";
import {
Text,
View,
ImageBackground,
TouchableOpacity,
StyleSheet,
} from "react-native";
import { BlurView } from "#react-native-community/blur";
import { BottomTabBarProps } from "#react-navigation/bottom-tabs";
import colorsOld from "src/theme/colorsOld";
import colors from "src/theme/colors";
const BottomNavigationTabs: React.FC<BottomTabBarProps> = ({
descriptors,
state,
navigation,
}) => {
const focusedOptions = descriptors[state.routes[state.index].key].options;
return (
<View
style={{
display: "flex",
flexDirection: "row",
backgroundColor: colors.secondaryBg(0.5),
position: "absolute",
bottom: 0,
justifyContent: "space-between",
}}
>
<BlurView
blurType="light"
blurAmount={15}
style={{ height: 85, width: "100%", bottom: 0 }}
/>
<View style={styles.tabsContainer}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const focusedColor = isFocused ? colors.text1 : colorsOld.black;
//Weird snippet, to render passed icon just call function with any return value, then just set color
const icon =
options.tabBarIcon &&
React.cloneElement(
//#ts-ignore
options.tabBarIcon((props: any) => props),
{ color: focusedColor }
);
const onPress = () => {
const event = navigation.emit({
type: "tabPress",
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};
const onLongPress = () => {
navigation.emit({
type: "tabLongPress",
target: route.key,
});
};
const tabBtn = (
<TouchableOpacity
accessibilityRole="button"
accessibilityState={isFocused ? { selected: true } : {}}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}
onPress={onPress}
style={styles.tabButton}
onLongPress={onLongPress}
activeOpacity={0.7}
key={route.key}
>
<View style={styles.tabItem}>
<View style={styles.tabItemIcon}>{icon}</View>
<Text style={{ ...styles.tabItemLabel, color: focusedColor }}>
{label}
</Text>
</View>
</TouchableOpacity>
);
return tabBtn;
})}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
alignItems: "center",
justifyContent: "center",
paddingTop: 9,
paddingBottom: 15,
},
tabButton: {
paddingTop: 8,
paddingBottom: 15,
paddingHorizontal: 10,
borderRadius: 10,
zIndex: 10000,
},
tabsContainer: {
width: "100%",
left: 0,
bottom: 0,
zIndex: 999,
position: 'absolute',
flexDirection: "row",
alignItems: "center",
justifyContent: "space-around",
},
tabItem: {
justifyContent: "center",
alignItems: "center",
},
tabItemIcon: {
marginBottom: 6,
},
tabItemLabel: {
fontSize: 12,
fontFamily: "Inter-Medium",
},
});
export default BottomNavigationTabs;

Bottom sheet is not getting closed in react native android

I am using #gorhom/bottom-sheet library to create my bottomsheet which have some weird behaviour in android devices. I am unable to close or swap top bottom the bottomsheet in android only. Also when keyboard appears this bottomsheet keeps transparent background.
Component
const BottomSheetComponent = (props: BottomSheetComponentProps, ref) => {
const theme = useCustomTheme();
const styles = useMemo(() => makeStyles(theme), [theme]);
const {children, visible, onClose, header, snapPoints = ['70%', '70%'], enablePanDownToClose = true, renderBackdrop = true } = props;
// const bottomSheetRef = useRef<BottomSheet>(null);
const detached = true;
/**
* onClick outside to close bottomsheet
*/
const renderBackdropComponent = useCallback(
props => <BottomSheetBackdrop {...props} />,
[],
);
return (
<Modal visible={visible} transparent>
<BottomSheet
ref={ref}
onClose={onClose}
backdropComponent={renderBackdrop ? renderBackdropComponent : null}
snapPoints={snapPoints}
detached={detached}
enablePanDownToClose={enablePanDownToClose}
keyboardBehavior={'interactive'}
keyboardBlurBehavior={'restore'}
style={styles.container}
handleStyle={styles.handleStyle}
handleIndicatorStyle={styles.indicatorStyle}
>
<View style={styles.contentContainer}>
{header}
{children}
</View>
</BottomSheet>
</Modal>
);
};
export default forwardRef(BottomSheetComponent);
Styles
const makeStyles = (theme: ColorTheme) => StyleSheet.create({
container: {
flex: 1,
backgroundColor: theme.primaryDark,
shadowColor: theme.white,
shadowOffset: {
width: 0,
height: 12
},
shadowOpacity: 0.5,
shadowRadius: 16,
elevation: 24
},
handleStyle: {
backgroundColor: theme.primaryDark,
// borderTopColor: theme.backgroundGrey,
},
indicatorStyle: {
backgroundColor: theme.secondaryGrey,
width: scaleWidth(56),
},
contentContainer: {
flex: 1,
backgroundColor: theme.primaryDark,
},
});
What I tried
I tried to work with gesture handler and reinstalled it in the application but it doesn't seems to work
Your BottomSheet need to be wrapped with gestureHandlerRootHOC
return (
<Modal visible={visible} transparent>
<YourButtomSheet />
</Modal>
)
const YourButtomSheet = gestureHandlerRootHOC((props: Props) => {
...
return (
<BottomSheet
ref={ref}
onClose={onClose}
backdropComponent={renderBackdrop ? renderBackdropComponent : null}
snapPoints={snapPoints}
detached={detached}`enter code here`
enablePanDownToClose={enablePanDownToClose}
keyboardBehavior={'interactive'}
keyboardBlurBehavior={'restore'}
style={styles.container}
handleStyle={styles.handleStyle}
handleIndicatorStyle={styles.indicatorStyle}
>
<View style={styles.contentContainer}>
{header}
{children}
</View>
</BottomSheet>
)
})
export default YourButtomSheet
https://docs.swmansion.com/react-native-gesture-handler/docs/1.10.3/

How to go from top to bottom of a ScrollView in React Native?

I'm in a React Native project that the client wants the product image scrolls from top to bottom vice versa in a modal, how can I achive this?
I already know how to solve this...
I had to create a counter that increase or decrease Y axis of ScrollView every 0.5 seconds and checking if reached the top or bottom.
In the modal component file:
import React, { useState, useEffect } from 'react';
import { StyleSheet, Modal, ScrollView, View, Image, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
import { Feather } from '#expo/vector-icons';
const ImageModal: React.FC<{ product: ProductType }> = ({ product }) => {
const [ axisY, setAxisY ] = useState<number>(0); // State that is used to know the current Y axis of ScrollView
const [ scrollToTop, setScrollToTop ] = useState<boolean>(false); // State that is used to checks if should go to top or bottom
// Handler that checks if ScrollView is scrolling to top or bottom
const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
// HELP: https://newbedev.com/detect-scrollview-has-reached-the-end
const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent; // Get scroll event properties
// If scrolling to top
if (scrollToTop) {
const isNearTop = contentOffset.y != 0; // Checks if Y axis reached the top of ScrollView
setScrollToTop(isNearTop); // Change the state value to FALSE, making ScrollView goes to bottom
} else {
const isNearBottom = layoutMeasurement.height + contentOffset.y >= contentSize.height; // Checks if Y axis reached the bottom of ScrollView
setScrollToTop(isNearBottom); // Change the state value to TRUE, making ScrollView goes to top
}
}
// Increase or decrease current Y axis every 0.5 seconds
useEffect(() => {
const timer = setInterval(() => {
setAxisY(prev => !scrollToTop ? prev + 1.5 : prev - 1.5);
}, 50);
return () => clearInterval(timer);
}, [scrollToTop]);
return (
<Modal
visible={ true }
transparent={ true }
statusBarTranslucent={ true }
animationType="fade"
>
<View style={ styles.container }>
<View style={ styles.box }>
<ScrollView
overScrollMode="never"
style={ styles.scroll }
scrollEnabled={ false }
showsVerticalScrollIndicator={ false }
contentOffset={{ x: 0, y: axisY }}
onScroll={ handleScroll }
>
<View style={ styles.imageBox }>
<Image source={{ uri: product.image_url }} style={ styles.image } />
</View>
</ScrollView>
<View>
<Text>Some random text!</Text>
</View>
</View>
<TouchableOpacity style={ styles.closeButton } onPress={ onClose }>
<Feather name="x" size={ 30 } color="#fff" />
</TouchableOpacity>
</View>
</Modal>
);
}
// Main Styles
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
padding: 20
},
closeButton: {
width: 60,
height: 60,
borderWidth: 2,
borderRadius: 12,
marginLeft: 20,
borderColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#58585a'
},
box: {
backgroundColor: '#fff',
width: '80%',
borderRadius: 10,
flexDirection: 'column'
},
scroll: {
width: '100%',
height: '80%',
borderBottomWidth: 1,
borderColor: '#58585a'
},
imageBox: {
width: '100%',
height: 600,
},
image: {
width: '100%',
height: '100%',
resizeMode: 'cover',
borderTopLeftRadius: 10,
borderTopRightRadius: 10
}
});
export default ImageModal;

How to smudge part of a view in React Native?

I would like to blur part of an Image wherever user drags his finger, I don't want to blur the whole image. Here is my hacky way of doing blur
I am using #react-native-community/blur for blurring the view
const MyView = () => {
const [locations, setLocation] = useState([]);
const [top, setTop] = useState();
const [left, setLeft] = useState();
return (
<>
<View
style={styles.container}
onTouchEnd={(event) => {
console.log(event.nativeEvent.locationX);
console.log(event.nativeEvent.locationY);
setLocation([
...locations,
{
right: event.nativeEvent.locationX,
bottom: event.nativeEvent.locationY,
top,
left,
},
]);
}}
onTouchStart={(event) => {
console.log('S' + event.nativeEvent.locationX);
console.log('S' + event.nativeEvent.locationY);
setLeft(event.nativeEvent.locationX);
setTop(event.nativeEvent.locationY);
}}>
<ImageBackground
style={{width, height}}
source={{
uri:
'https://images.unsplash.com/photo-1593642634315-48f5414c3ad9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80',
}}>
<Text>Hi there </Text>
</ImageBackground>
</View>
{locations.map((l, index) => {
return (
<BlurView
key={index.toString()}
style={{
width: l.right - l.left,
height: l.bottom - l.top,
backgroundColor: 'rgba(0,0,0,0.1)',
position: 'absolute',
top: parseFloat(l.top),
left: parseFloat(l.left),
right: parseFloat(l.right),
bottom: parseFloat(l.bottom),
// blurR,
// opacity: 0.4,
}}
blurType="light"
blurAmount={4}
reducedTransparencyFallbackColor="white"
/>
);
})}
</>);
};
This is a really hacky way of smudging part of an image where user drags his finger. On Android , the application just stops responding as soon as I move my finger on more than two places. Does anyone know a better way to smudge part of view instead of blurring the whole image view where user drags his finger
You can use PanResponder. I developed an example application for you. There is no blurview on expo snack but i guess you can easily convert that sample to what you want. Here is example code:
import React, { useState, useRef } from 'react'
import { StyleSheet, View, ImageBackground, PanResponder, Animated } from 'react-native'
const CIRCLE_RADIUS = 60
const IAmTheBlurComponent = () => {
return (
<View style={[StyleSheet.absoluteFill, { backgroundColor: 'pink', opacity: 0.5 }]}></View>
)
}
const Component = () => {
const [pointers, setPointers] = useState([])
const refs: any = useRef({}).current;
const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderStart: (evt) => {
setPointers(evt.nativeEvent.touches.map(touch => touch.identifier))
evt.nativeEvent.touches.forEach((event) => {
refs[event.identifier] = { x: new Animated.Value(event.pageX), y: new Animated.Value(event.pageY) }
})
},
onPanResponderMove: (evt) => {
evt.nativeEvent.touches.forEach((event) => {
refs[event.identifier].x.setValue(event.pageX)
refs[event.identifier].y.setValue(event.pageY)
})
},
onPanResponderEnd: (evt) => {
setPointers(evt.nativeEvent.touches.map(touch => touch.identifier))
},
})
).current
return (
<ImageBackground
style={{
flex: 1,
position: 'relative'
}}
source={{
uri:
'https://images.unsplash.com/photo-1593642634315-48f5414c3ad9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80',
}}
{...panResponder.panHandlers}
>
{pointers.map((pnt) => {
return (
<Animated.View
key={pnt}
style={{
overflow: 'hidden',
height: CIRCLE_RADIUS * 2,
width: CIRCLE_RADIUS * 2,
borderRadius: CIRCLE_RADIUS,
position: 'absolute',
transform: [
{
translateX: Animated.subtract(refs[pnt].x, CIRCLE_RADIUS)
},
{
translateY: Animated.subtract(refs[pnt].y, CIRCLE_RADIUS)
}
]
}}
>
<IAmTheBlurComponent />
</Animated.View>
)
})}
</ImageBackground>
)
}
export default function App() {
return (
<View style={styles.container}>
<Component />
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
})
For smooth animations, you can chose Reanimated library. I didnt use ValueXY or similar things, so you can easily convert that sample to reanimated.
This is the sample expo snack: https://snack.expo.io/#kubilaysali/suspicious-ice-cream

Categories

Resources