Hi I'm using this package as component it shwos and get vlaues but how can I get input values from root component.
in root page
import AnimatedVerification from '../../components/AnimatedVerification/AnimatedVerification';
inside this code is all comes from this example
I just want to get this 4 number values from root component how to make it. Thank you
Expo
/*
*/
import {Animated, Image, SafeAreaView, Text, View} from 'react-native';
import React, {useState} from 'react';
import {
CodeField,
Cursor,
useBlurOnFulfill,
useClearByFocusCell,
} from 'react-native-confirmation-code-field';
import styles, {
ACTIVE_CELL_BG_COLOR,
CELL_BORDER_RADIUS,
CELL_SIZE,
DEFAULT_CELL_BG_COLOR,
NOT_EMPTY_CELL_BG_COLOR,
} from './styles';
const {Value, Text: AnimatedText} = Animated;
const CELL_COUNT = 4;
const source = {
uri:
'https://user-images.gitx.com/4xxxxxxx.png',
};
const animationsColor = [...new Array(CELL_COUNT)].map(() => new Value(0));
const animationsScale = [...new Array(CELL_COUNT)].map(() => new Value(1));
const animateCell = ({hasValue, index, isFocused}) => {
Animated.parallel([
Animated.timing(animationsColor[index], {
useNativeDriver: false,
toValue: isFocused ? 1 : 0,
duration: 250,
}),
Animated.spring(animationsScale[index], {
useNativeDriver: false,
toValue: hasValue ? 0 : 1,
duration: hasValue ? 300 : 250,
}),
]).start();
};
const AnimatedVerification = () => {
const [value, setValue] = useState('');
const [props, getCellOnLayoutHandler] = useClearByFocusCell({
value,
setValue,
});
const renderCell = ({index, symbol, isFocused}) => {
const hasValue = Boolean(symbol);
const animatedCellStyle = {
backgroundColor: hasValue
? animationsScale[index].interpolate({
inputRange: [0, 1],
outputRange: [NOT_EMPTY_CELL_BG_COLOR, ACTIVE_CELL_BG_COLOR],
})
: animationsColor[index].interpolate({
inputRange: [0, 1],
outputRange: [DEFAULT_CELL_BG_COLOR, ACTIVE_CELL_BG_COLOR],
}),
borderRadius: animationsScale[index].interpolate({
inputRange: [0, 1],
outputRange: [CELL_SIZE, CELL_BORDER_RADIUS],
}),
transform: [
{
scale: animationsScale[index].interpolate({
inputRange: [0, 1],
outputRange: [0.2, 1],
}),
},
],
};
// Run animation on next event loop tik
// Because we need first return new style prop and then animate this value
setTimeout(() => {
animateCell({hasValue, index, isFocused});
}, 0);
return (
<AnimatedText
key={index}
style={[styles.cell, animatedCellStyle]}
onLayout={getCellOnLayoutHandler(index)}>
{symbol || (isFocused ? <Cursor /> : null)}
</AnimatedText>
);
};
return (
<SafeAreaView style={styles.root}>
<CodeField
ref={props.ref}
{...props}
value={value}
onChangeText={setValue}
cellCount={CELL_COUNT}
rootStyle={styles.codeFiledRoot}
keyboardType="number-pad"
textContentType="oneTimeCode"
renderCell={renderCell}
/>
</SafeAreaView>
);
};
export default AnimatedVerification;
If I understand, you want to get the value of the child component in parent component ?
Your CodeField component has a ref in the parent component ref={props.ref}.
In your CodeField component define a method who return the inputs values. And in the parent you can call the method with the ref.
Related
I have made a bit of re-usable animation code. It works great but I an unsure if it is possible to get the animations back to their original values after a button is pressed easily.
The only way I can think of it to use useShared Values to store all the before and after values and set them as required but this would involve alot of values but because the animations have already ran, there must be a way to just take them back to their original start?
The code I am using for the animations is : -
EntryAnimation.js
import React, { useEffect } from 'react';
import Animated, {
useAnimatedStyle,
useSharedValue,
useDerivedValue,
interpolate,
withDelay,
withTiming,
withSpring,
Easing,
} from 'react-native-reanimated';
export const EntryAnimation = ({
children,
index,
rotateV,
scaleV,
offsetXV,
offsetYX,
}) => {
const play = useSharedValue(play);
const progress = useDerivedValue(() => {
return play.value
? withDelay(50 * (index ?? 0), withSpring(1, { duration: 350 }))
: 0;
});
useEffect(() => {
play.value = play;
}, []);
const animatedStyle = useAnimatedStyle(() => {
// const opacity = interpolate(progress.value, [0, 1], [0, 1]);
const translateY = interpolate(progress.value, [0, 1], [0, offsetYX]);
const translateX = interpolate(progress.value, [0, 1], [0, offsetXV]);
const rotate = interpolate(progress.value, [0, 1], [0, rotateV]);
const scale = interpolate(progress.value, [0, 1], [1, scaleV]);
return {
transform: [{ translateY }, { translateX }, { rotate }, { scale }],
};
});
return <Animated.View style={animatedStyle}>{children}</Animated.View>;
};
And to use on an element in my main code, I use :-
<EntryAnimation
index={1}
rotateV={0}
scaleV={0.8}
offsetXV={0}
offsetYX={-270}>
<Animated.Image
source={{ uri: item.poster }}
style={[styles.posterImage, { zIndex: 6 }]}
/>
</EntryAnimation>
I have tried using the code below but because its in a ternary statement I am getting errors?
{animStarted ? (
<EntryAnimation
index={1}
rotateV={0}
scaleV={0.8}
offsetXV={0}
offsetYX={-270}
>
) : (
<EntryAnimation
index={1}
rotateV={0}
scaleV={1}
offsetXV={0}
offsetYX={0}
>
)}
Any ideas?
I want to add a listener to an interpolated Animated value, but the callback isn't being called at all...
My code is below, am I doing something wrong?
import React, { useEffect } from 'react';
import {View, Animated } from 'react-native';
export default App = () => {
const y = new Animated.Value(0);
const yInt = y.interpolate({
inputRange: [-100, 100],
outputRange: [0, 10],
});
yInt.addListener(({value}) => console.log('yInt', value))
useEffect(() => {
Animated.timing(y, {
toValue: 1,
duration: 2000,
useNativeDriver: true,
}).start();
}, []);
return <View />;
};
I'm building an translateY e opacity component to animate my submit button that appears at the end of the form. The problem is that everytime the prop changes too fast the button stops working
[...]
class ShyButton extends PureComponent {
constructor(props) {
super(props)
this.state = { height: 0, visible: props.isVisible }
this.animatedValue = new Animated.Value(props.isVisible ? 1 : 0)
}
componentDidUpdate(prevProps, prevState) {
const { isVisible } = this.props
if (prevProps.isVisible !== isVisible) {
if (isVisible) { this.toggleVisibility(prevState, true) }
Animated.timing(this.animatedValue,
{ toValue: isVisible ? 1 : 0, duration: 800, useNativeDriver: true }
).start(() => { if (!isVisible) { this.toggleVisibility(prevState, false) } })
}
}
toggleVisibility = (prevState, visible) => this.setState({ ...prevState, visible })
onLayout = event => this.setState({ height: event.nativeEvent.layout.height })
render() {
const { isVisible, style, children, ...props } = this.props
const { height, visible } = this.state
const animatedStyle = {
opacity: this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
}),
transform: [
{
translateY: this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [height, 0],
extrapolate: 'clamp'
})
}
]
}
const combinedStyle = StyleSheet.flatten([style, { opacity: 0, transform: [{ translateY: 0 }] }])
const animatingStyle = StyleSheet.flatten([combinedStyle, animatedStyle])
return (
<Animated.View onLayout={this.onLayout} style={visible ? animatingStyle : combinedStyle} {...props}>
{visible ? children : null}
</Animated.View>
)
}
}
[...]
The biggest problem is when auto-correct is used on the first word the text length goes to zero (test used to show or hide it) and back too fast, blocking the animation
Imgur
I have a wrapper flat list component used in react navigation library.
This component is in different stacknavigation tab to handle the header's animation.
import React, { Component } from "react";
import { Constants } from 'expo';
// import PropTypes from "prop-types";
import {
Animated,
Dimensions,
// PanResponder,
// Platform,
// ScrollView,
StyleSheet,
FlatList,
// ScrollView,
// StatusBar,
// Text,
// TouchableWithoutFeedback,
// View
} from "react-native";
// import Icon from "react-native-vector-icons/Ionicons";
// Get screen dimensions
const { width, height } = Dimensions.get("window");
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
const HEADER_HEIGHT= 40;
const FILTER_HEIGHT= 50;
const STATUS_BAR_HEIGHT = Constants.statusBarHeight;
const NAVBAR_HEIGHT = HEADER_HEIGHT+FILTER_HEIGHT-2;
const scrollAnim = new Animated.Value(0);
const offsetAnim = new Animated.Value(0);
export default class AnimatedFlatListComp extends React.PureComponent {
// Define state
state = {
scrollAnim,
offsetAnim,
clampedScroll: Animated.diffClamp(
Animated.add(
scrollAnim.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolateLeft: 'clamp',
}),
offsetAnim,
),
0,
// NAVBAR_HEIGHT - STATUS_BAR_HEIGHT,
HEADER_HEIGHT //i mede this one cuz the code abode not work is the value 40
),
};
componentWillUnmount() {
console.log('smontoooo');
// this._isMounted = false;
// Don't forget to remove the listeners!
// this.state.scrollAnim.removeAllListeners();
// this.state.offsetAnim.removeAllListeners();
this._disableListener();
}
componentDidMount() {
this._clampedScrollValue = 0;
this._offsetValue = 0;
this._scrollValue = 0;
this._enableLister()
this._handleScroll()
}
_onMomentumScrollBegin = () => {
console.log('_onMomentumScrollBegin');
clearTimeout(this._scrollEndTimer);
}
_onScrollEndDrag = () => {
this._scrollEndTimer = setTimeout(this._onMomentumScrollEnd, 250);
}
_onMomentumScrollEnd = () => {
console.log('_onMomentumScrollEnd');
console.log(this._scrollValue, NAVBAR_HEIGHT, this._clampedScrollValue, (NAVBAR_HEIGHT - STATUS_BAR_HEIGHT) / 2);
const toValue = this._scrollValue > NAVBAR_HEIGHT &&
this._clampedScrollValue > (NAVBAR_HEIGHT - STATUS_BAR_HEIGHT) / 2
? this._offsetValue + NAVBAR_HEIGHT
: this._offsetValue - NAVBAR_HEIGHT;
Animated.timing(this.state.offsetAnim, {
toValue,
duration: 350,
useNativeDriver: true,
}).start();
}
_handleScroll = () => this.props._handleScroll(this.state.clampedScroll)
// _handleScroll = event => {
// const { y } = event.nativeEvent.contentOffset;
// // // console.log(y);
// this.setState({ scrollOffset: y }, () => {
// this.props._handleScroll(this.state.clampedScroll)
// });
//
// };
_scrollToTop = () => {
console.log('_scrollToTop');
if (!!this.flatListRef) {
// this.flatListRef.getNode().scrollTo({ y: 0, animated: true });
this.flatListRef.getNode().scrollToOffset({ offset: 0, animated: true });
}
};
_enableLister = () => {
// this._firstMountFunction();
this.state.scrollAnim.addListener(({ value }) => {
// This is the same calculations that diffClamp does.
const diff = value - this._scrollValue;
this._scrollValue = value;
this._clampedScrollValue = Math.min(
Math.max(this._clampedScrollValue + diff, 0),
NAVBAR_HEIGHT - STATUS_BAR_HEIGHT,
);
});
this.state.offsetAnim.addListener(({ value }) => {
this._offsetValue = value;
});
}
_disableListener = () => {
this.state.scrollAnim.removeAllListeners();
this.state.offsetAnim.removeAllListeners();
}
_keyExtractor = (item, index) => index.toString();
// _onScroll = event => {
//
// }
render() {
return (
<AnimatedFlatList
{...this.props}
ref={(ref) => { this.flatListRef = ref; }}
showsVerticalScrollIndicator={false}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.scrollAnim}}}],
{
useNativeDriver: true,
// listener: this._handleScroll
},
)}
// onScroll={this._onScroll}
removeClippedSubviews={true}
keyExtractor={this._keyExtractor}
onMomentumScrollBegin={this._onMomentumScrollBegin}
onMomentumScrollEnd={this._onMomentumScrollEnd}
onScrollEndDrag={this._onScrollEndDrag}
scrollEventThrottle={1}
/>
);
}
}
this is the parent
_handleScroll = clampedScroll => this.setState({ clampedScroll: clampedScroll })
render(){
const { clampedScroll } = this.state;
//
const navbarTranslate = clampedScroll.interpolate({
inputRange: [0, NAVBAR_HEIGHT - STATUS_BAR_HEIGHT],
outputRange: [0, -(NAVBAR_HEIGHT - STATUS_BAR_HEIGHT)],
extrapolate: 'clamp',
});
return (
<AnimatedFlatList
// debug={true}
ref={(ref) => { this.flatListRef = ref; }}
maxToRenderPerBatch={4}
contentContainerStyle={{
paddingTop: NAVBAR_HEIGHT+STATUS_BAR_HEIGHT,
}}
data={this.state.dataSource}
renderItem={
({item, index}) =>
<CardAgenda
item={JSON.parse(item.JSON)}
ChangeSelectedEvent={this.ChangeSelectedEvent}
colorTrail={JSON.parse(item.colorTrail)}
// _sendBackdata={this._getChildrenCategoryData}
searchData={JSON.parse(item.searchData)}
NumAncillary={item.NumAncillary}
indexItinerary={item.id}
index={index}
/>
}
ListEmptyComponent={this._emptyList}
ItemSeparatorComponent={() => <View style={{width: width-40, backgroundColor: 'rgba(0,0,0,0.1)', height: 1, marginTop: 20, marginLeft: 20, marginRight: 20}}/>}
_handleScroll={this._handleScroll}
/>
)}
Its working fine but onscroll event triggers the this.state.scrollAnim variable of ALL wrappers.
I mean if i scroll up the first AnimatedFlatList the header goes up but also the different one header in new navigation page goes up.
The correct behavior must be that all header must be independent to the own flatlist.
Thanks in advance
This is because you are setting up a reference to the state when creating animated Values obj. You should not keep them as constants outside your class boundary.
Try remove your following constants.
const scrollAnim = new Animated.Value(0);
const offsetAnim = new Animated.Value(0);
Then define them inside the constructor.
export default class AnimatedFlatListComp extends React.PureComponent {
constructor(props){
super(props);
this.scrollAnim = new Animated.Value(0);
this.offsetAnim = new Animated.Value(0);
// Define state
state = {
scrollAnim: this.scrollAnim,
offsetAnim: this.offsetAnim,
clampedScroll: Animated.diffClamp(
Animated.add(
this.scrollAnim.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolateLeft: 'clamp',
}),
this.offsetAnim,
),
0,
// NAVBAR_HEIGHT - STATUS_BAR_HEIGHT,
HEADER_HEIGHT //i mede this one cuz the code abode not work is
the value 40
),
};
}
I followed the below code to implement Screen transition animation but it doesn't seem to be working. I am using react-navigation(1.0.0-beta.26) with redux.
const transitionConfig = () => {
return {
transitionSpec: {
duration: 750,
easing: Easing.out(Easing.poly(4)),
timing: Animated.timing,
useNativeDriver: true,
},
screenInterpolator: sceneProps => {
const { position, layout, scene, index, scenes } = sceneProps
const toIndex = index
const thisSceneIndex = scene.index
const height = layout.initHeight
const width = layout.initWidth
const translateX = position.interpolate({
inputRange: [thisSceneIndex - 1, thisSceneIndex, thisSceneIndex + 1],
outputRange: [width, 0, 0]
})
const translateY = position.interpolate({
inputRange: [0, thisSceneIndex],
outputRange: [height, 0]
})
const slideFromRight = { transform: [{ translateX }] }
const slideFromBottom = { transform: [{ translateY }] }
const lastSceneIndex = scenes[scenes.length - 1].index
if (lastSceneIndex - toIndex > 1) {
if (scene.index === toIndex) return
if (scene.index !== lastSceneIndex) return { opacity: 0 }
return slideFromBottom
}
return slideFromRight
},
}}
export const AppNavigator = StackNavigator({
Screen1: {screen: Screen1, navigationOptions:{header:null}},
Screen2: {screen: Screen2, navigationOptions:{header:null}},
}, {
initialRouteName: 'Screen1',
transitionConfig,
});
class App extends Component {
return (
<View>
<AppNavigator />
</View>
)
}
I am navigating using the redux dispatch as mentioned below
this.props.navigation.dispatch({ type: 'Screen2' })