mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-29 12:55:21 +08:00
fix: send events even is stack animation is vain (#270)
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Button, View, Text, Dimensions, Switch } from 'react-native';
|
import {
|
||||||
|
Button,
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
Dimensions,
|
||||||
|
Switch,
|
||||||
|
TextInput,
|
||||||
|
} from 'react-native';
|
||||||
import {
|
import {
|
||||||
createStackNavigator,
|
createStackNavigator,
|
||||||
CardStyleInterpolators,
|
CardStyleInterpolators,
|
||||||
@@ -127,6 +134,10 @@ class DetailsScreen extends React.Component<NavigationStackScreenProps> {
|
|||||||
title="Go to Details... again"
|
title="Go to Details... again"
|
||||||
onPress={() => this.props.navigation.push('Details')}
|
onPress={() => this.props.navigation.push('Details')}
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
title="Go to inputs..."
|
||||||
|
onPress={() => this.props.navigation.push('Inputs')}
|
||||||
|
/>
|
||||||
<Button
|
<Button
|
||||||
title="Go to List"
|
title="Go to List"
|
||||||
onPress={() => this.props.navigation.navigate('List')}
|
onPress={() => this.props.navigation.navigate('List')}
|
||||||
@@ -143,12 +154,34 @@ class DetailsScreen extends React.Component<NavigationStackScreenProps> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function InputsScreen({ navigation }: NavigationStackScreenProps) {
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
||||||
|
<Text>Inputs Screen</Text>
|
||||||
|
<TextInput
|
||||||
|
defaultValue="sample"
|
||||||
|
autoFocus
|
||||||
|
style={{ backgroundColor: 'blue' }}
|
||||||
|
/>
|
||||||
|
<TextInput defaultValue="sample" style={{ backgroundColor: 'red' }} />
|
||||||
|
<TextInput defaultValue="sample" style={{ backgroundColor: 'green' }} />
|
||||||
|
<Button
|
||||||
|
title="Go to inputs... again"
|
||||||
|
onPress={() => navigation.push('Inputs')}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default createStackNavigator(
|
export default createStackNavigator(
|
||||||
{
|
{
|
||||||
List: ListScreen,
|
List: ListScreen,
|
||||||
Details: DetailsScreen,
|
Details: DetailsScreen,
|
||||||
Modal: Modal,
|
Modal: Modal,
|
||||||
|
Inputs: {
|
||||||
|
screen: InputsScreen,
|
||||||
|
navigationOptions: { gestureDirection: 'vertical' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
initialRouteName: 'List',
|
initialRouteName: 'List',
|
||||||
|
|||||||
@@ -351,6 +351,7 @@ export default class Card extends React.Component<Props> {
|
|||||||
private offset = new Value(0);
|
private offset = new Value(0);
|
||||||
private velocityUntraversed = new Value(0);
|
private velocityUntraversed = new Value(0);
|
||||||
private velocity = new Value(0);
|
private velocity = new Value(0);
|
||||||
|
private didMovementHappen = new Value(0);
|
||||||
|
|
||||||
private gestureState = new Value(0);
|
private gestureState = new Value(0);
|
||||||
|
|
||||||
@@ -404,98 +405,126 @@ export default class Card extends React.Component<Props> {
|
|||||||
private runTransition = (isVisible: Binary | Animated.Node<number>) => {
|
private runTransition = (isVisible: Binary | Animated.Node<number>) => {
|
||||||
const { open: openingSpec, close: closingSpec } = this.props.transitionSpec;
|
const { open: openingSpec, close: closingSpec } = this.props.transitionSpec;
|
||||||
|
|
||||||
return cond(eq(this.props.current, isVisible), NOOP_NODE, [
|
return [
|
||||||
cond(clockRunning(this.clock), NOOP_NODE, [
|
|
||||||
// Animation wasn't running before
|
|
||||||
// Set the initial values and start the clock
|
|
||||||
set(this.toValue, isVisible),
|
|
||||||
// The velocity value is ideal for translating the whole screen
|
|
||||||
// But since we have 0-1 scale, we need to adjust the velocity
|
|
||||||
set(
|
|
||||||
this.transitionVelocity,
|
|
||||||
multiply(
|
|
||||||
cond(
|
|
||||||
this.distance,
|
|
||||||
divide(this.velocity, this.distance),
|
|
||||||
FALSE_NODE
|
|
||||||
),
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
),
|
|
||||||
set(this.frameTime, FALSE_NODE),
|
|
||||||
set(this.transitionState.time, FALSE_NODE),
|
|
||||||
set(this.transitionState.finished, FALSE_NODE),
|
|
||||||
set(this.isVisible, isVisible),
|
|
||||||
startClock(this.clock),
|
|
||||||
call([this.isVisible], ([value]: ReadonlyArray<Binary>) => {
|
|
||||||
this.handleStartInteraction();
|
|
||||||
|
|
||||||
const { onTransitionStart } = this.props;
|
|
||||||
this.noAnimationStartedSoFar = false;
|
|
||||||
this.isRunningAnimation = true;
|
|
||||||
onTransitionStart && onTransitionStart({ closing: !value });
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
cond(
|
cond(
|
||||||
eq(isVisible, TRUE_NODE),
|
eq(this.props.current, isVisible),
|
||||||
openingSpec.animation === 'spring'
|
call(
|
||||||
? memoizedSpring(
|
[this.didMovementHappen, this.isVisible],
|
||||||
this.clock,
|
([didMovementHappen]: ReadonlyArray<Binary>) => {
|
||||||
{ ...this.transitionState, velocity: this.transitionVelocity },
|
if (didMovementHappen) {
|
||||||
// @ts-ignore
|
// if we go back to the same position,
|
||||||
{
|
// let's pretend that whole animation happen
|
||||||
...(this.openingSpecConfig as AnimatedSpringConfig),
|
// for making the logic consistent
|
||||||
toValue: this.toValue,
|
// It's especially vital for having inputs properly focused.
|
||||||
}
|
this.handleStartInteraction();
|
||||||
)
|
const { onTransitionStart } = this.props;
|
||||||
: timing(
|
onTransitionStart && onTransitionStart({ closing: true });
|
||||||
this.clock,
|
this.handleTransitionEnd();
|
||||||
{ ...this.transitionState, frameTime: this.frameTime },
|
this.props.onOpen(true);
|
||||||
{
|
}
|
||||||
...(this.openingSpecConfig as AnimatedTimingConfig),
|
|
||||||
toValue: this.toValue,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
closingSpec.animation === 'spring'
|
|
||||||
? memoizedSpring(
|
|
||||||
this.clock,
|
|
||||||
{ ...this.transitionState, velocity: this.transitionVelocity },
|
|
||||||
// @ts-ignore
|
|
||||||
{
|
|
||||||
...(this.closingSpecConfig as AnimatedSpringConfig),
|
|
||||||
toValue: this.toValue,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
: timing(
|
|
||||||
this.clock,
|
|
||||||
{ ...this.transitionState, frameTime: this.frameTime },
|
|
||||||
{
|
|
||||||
...(this.closingSpecConfig as AnimatedTimingConfig),
|
|
||||||
toValue: this.toValue,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
cond(this.transitionState.finished, [
|
|
||||||
// Reset values
|
|
||||||
set(this.isSwipeGesture, FALSE_NODE),
|
|
||||||
set(this.gesture, FALSE_NODE),
|
|
||||||
set(this.velocity, FALSE_NODE),
|
|
||||||
// When the animation finishes, stop the clock
|
|
||||||
stopClock(this.clock),
|
|
||||||
call([this.isVisible], ([value]: ReadonlyArray<Binary>) => {
|
|
||||||
const isOpen = Boolean(value);
|
|
||||||
const { onOpen, onClose } = this.props;
|
|
||||||
|
|
||||||
this.handleTransitionEnd();
|
|
||||||
|
|
||||||
if (isOpen) {
|
|
||||||
onOpen(true);
|
|
||||||
} else {
|
|
||||||
onClose(true);
|
|
||||||
}
|
}
|
||||||
}),
|
),
|
||||||
]),
|
[
|
||||||
]);
|
cond(clockRunning(this.clock), NOOP_NODE, [
|
||||||
|
// Animation wasn't running before
|
||||||
|
// Set the initial values and start the clock
|
||||||
|
set(this.toValue, isVisible),
|
||||||
|
// The velocity value is ideal for translating the whole screen
|
||||||
|
// But since we have 0-1 scale, we need to adjust the velocity
|
||||||
|
set(
|
||||||
|
this.transitionVelocity,
|
||||||
|
multiply(
|
||||||
|
cond(
|
||||||
|
this.distance,
|
||||||
|
divide(this.velocity, this.distance),
|
||||||
|
FALSE_NODE
|
||||||
|
),
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
),
|
||||||
|
set(this.frameTime, FALSE_NODE),
|
||||||
|
set(this.transitionState.time, FALSE_NODE),
|
||||||
|
set(this.transitionState.finished, FALSE_NODE),
|
||||||
|
set(this.isVisible, isVisible),
|
||||||
|
startClock(this.clock),
|
||||||
|
call([this.isVisible], ([value]: ReadonlyArray<Binary>) => {
|
||||||
|
this.handleStartInteraction();
|
||||||
|
|
||||||
|
const { onTransitionStart } = this.props;
|
||||||
|
this.noAnimationStartedSoFar = false;
|
||||||
|
this.isRunningAnimation = true;
|
||||||
|
onTransitionStart && onTransitionStart({ closing: !value });
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
cond(
|
||||||
|
eq(isVisible, TRUE_NODE),
|
||||||
|
openingSpec.animation === 'spring'
|
||||||
|
? memoizedSpring(
|
||||||
|
this.clock,
|
||||||
|
{
|
||||||
|
...this.transitionState,
|
||||||
|
velocity: this.transitionVelocity,
|
||||||
|
},
|
||||||
|
// @ts-ignore
|
||||||
|
{
|
||||||
|
...(this.openingSpecConfig as AnimatedSpringConfig),
|
||||||
|
toValue: this.toValue,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
: timing(
|
||||||
|
this.clock,
|
||||||
|
{ ...this.transitionState, frameTime: this.frameTime },
|
||||||
|
{
|
||||||
|
...(this.openingSpecConfig as AnimatedTimingConfig),
|
||||||
|
toValue: this.toValue,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
closingSpec.animation === 'spring'
|
||||||
|
? memoizedSpring(
|
||||||
|
this.clock,
|
||||||
|
{
|
||||||
|
...this.transitionState,
|
||||||
|
velocity: this.transitionVelocity,
|
||||||
|
},
|
||||||
|
// @ts-ignore
|
||||||
|
{
|
||||||
|
...(this.closingSpecConfig as AnimatedSpringConfig),
|
||||||
|
toValue: this.toValue,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
: timing(
|
||||||
|
this.clock,
|
||||||
|
{ ...this.transitionState, frameTime: this.frameTime },
|
||||||
|
{
|
||||||
|
...(this.closingSpecConfig as AnimatedTimingConfig),
|
||||||
|
toValue: this.toValue,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
cond(this.transitionState.finished, [
|
||||||
|
// Reset values
|
||||||
|
set(this.isSwipeGesture, FALSE_NODE),
|
||||||
|
set(this.gesture, FALSE_NODE),
|
||||||
|
set(this.velocity, FALSE_NODE),
|
||||||
|
// When the animation finishes, stop the clock
|
||||||
|
stopClock(this.clock),
|
||||||
|
call([this.isVisible], ([value]: ReadonlyArray<Binary>) => {
|
||||||
|
const isOpen = Boolean(value);
|
||||||
|
const { onOpen, onClose } = this.props;
|
||||||
|
|
||||||
|
this.handleTransitionEnd();
|
||||||
|
|
||||||
|
if (isOpen) {
|
||||||
|
onOpen(true);
|
||||||
|
} else {
|
||||||
|
onClose(true);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
set(this.didMovementHappen, 0),
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
private extrapolatedPosition = add(
|
private extrapolatedPosition = add(
|
||||||
@@ -576,6 +605,7 @@ export default class Card extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
onChange(this.gestureUntraversed, set(this.didMovementHappen, 1)),
|
||||||
cond(
|
cond(
|
||||||
eq(this.gestureState, GestureState.ACTIVE),
|
eq(this.gestureState, GestureState.ACTIVE),
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in New Issue
Block a user