Skip to content

Instantly share code, notes, and snippets.

@rokkoo
Created May 10, 2023 08:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rokkoo/c7003c9aa6d280b85e5ba01a05840306 to your computer and use it in GitHub Desktop.
Save rokkoo/c7003c9aa6d280b85e5ba01a05840306 to your computer and use it in GitHub Desktop.
Reanimated sticky text input on react native
import React, { useCallback, useState } from 'react';
import {
Pressable,
StyleSheet,
TextInput,
useWindowDimensions,
} from 'react-native';
import { useReanimatedKeyboardAnimation } from 'react-native-keyboard-controller';
import Animated, {
interpolate,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
import AntDesign from '@expo/vector-icons/AntDesign';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const styles = StyleSheet.create({
container: {
justifyContent: 'flex-end',
paddingTop: 24,
borderTopColor: '#EAEDED',
borderTopWidth: 0.8,
width: '100%',
},
box: {
width: 60,
height: 60,
marginVertical: 20,
},
row: {
flexDirection: 'row',
},
});
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
const AnimatedIcon = Animated.createAnimatedComponent(AntDesign);
interface ReanimatedTextInputProps {
onPress: (text: string) => void;
}
export default function ReanimatedTextInput({
onPress,
}: ReanimatedTextInputProps) {
const [text, setText] = useState('');
const insets = useSafeAreaInsets();
const { height, progress } = useReanimatedKeyboardAnimation();
const { width } = useWindowDimensions();
const AnimatedTextInputStyle = useAnimatedStyle(() => {
const defaultB = insets.bottom + 12;
const paddingBottom = interpolate(progress.value, [0, 1], [defaultB, 8]);
return {
transform: [
{
translateY: withSpring(height.value, { mass: 0.4 }),
},
],
paddingBottom,
};
}, [insets, height.value, width]);
const scal = useAnimatedStyle(() => {
const scale = interpolate(progress.value, [0, 1], [0.8, 1]);
return {
transform: [{ scale: withSpring(scale, { mass: 3 }) }],
};
});
const handlePressSendButton = useCallback(() => {
if (text.length > 0) {
onPress(text);
}
setText('');
}, [text, onPress]);
return (
<Animated.View style={[styles.container, AnimatedTextInputStyle]}>
<Animated.View
style={[
{
flexDirection: 'row',
alignContent: 'center',
alignItems: 'center',
},
]}
>
<AnimatedTextInput
value={text}
onChangeText={(t) => setText(t)}
placeholder="Write anything"
multiline
textAlignVertical="center"
style={[
{
flex: 1,
minHeight: 32,
textAlignVertical: 'center',
backgroundColor: '#EAEDED',
paddingHorizontal: 24,
borderRadius: 8,
fontSize: 20,
marginRight: 20,
},
]}
placeholderTextColor="#ABB2B9"
/>
<Pressable onPress={handlePressSendButton}>
<AnimatedIcon
name="rightcircle"
size={32}
color="black"
style={scal}
/>
</Pressable>
</Animated.View>
</Animated.View>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment