Add image example, make shadow and translate apply to different views, hide shadow on inactive screens
This commit is contained in:
parent
f334c7645a
commit
50e54ebaf8
|
@ -6,6 +6,7 @@ import { createStackNavigator } from 'react-navigation-stack';
|
||||||
import { ListSection, Divider } from 'react-native-paper';
|
import { ListSection, Divider } from 'react-native-paper';
|
||||||
|
|
||||||
import SimpleStack from './src/SimpleStack';
|
import SimpleStack from './src/SimpleStack';
|
||||||
|
import ImageStack from './src/ImageStack';
|
||||||
import TransparentStack from './src/TransparentStack';
|
import TransparentStack from './src/TransparentStack';
|
||||||
import ModalStack from './src/ModalStack';
|
import ModalStack from './src/ModalStack';
|
||||||
import GestureInteraction from './src/GestureInteraction';
|
import GestureInteraction from './src/GestureInteraction';
|
||||||
|
@ -20,6 +21,7 @@ useScreens();
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{ component: SimpleStack, title: 'Simple', routeName: 'SimpleStack' },
|
{ component: SimpleStack, title: 'Simple', routeName: 'SimpleStack' },
|
||||||
|
{ component: ImageStack, title: 'Image', routeName: 'ImageStack' },
|
||||||
{ component: ModalStack, title: 'Modal', routeName: 'ModalStack' },
|
{ component: ModalStack, title: 'Modal', routeName: 'ModalStack' },
|
||||||
{
|
{
|
||||||
component: TransparentStack,
|
component: TransparentStack,
|
||||||
|
@ -29,11 +31,15 @@ const data = [
|
||||||
{ component: GestureInteraction, title: 'Gesture Interaction', routeName: 'GestureInteraction' },
|
{ component: GestureInteraction, title: 'Gesture Interaction', routeName: 'GestureInteraction' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Expo.Asset.loadAsync(require('react-navigation/src/views/assets/back-icon.png'));
|
||||||
|
Expo.Asset.loadAsync(require('react-navigation/src/views/assets/back-icon-mask.png'));
|
||||||
|
|
||||||
class Home extends React.Component {
|
class Home extends React.Component {
|
||||||
static navigationOptions = {
|
static navigationOptions = {
|
||||||
title: 'Examples',
|
title: 'Examples',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
_renderItem = ({ item }) => (
|
_renderItem = ({ item }) => (
|
||||||
<ListSection.Item
|
<ListSection.Item
|
||||||
title={item.title}
|
title={item.title}
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Dimensions, Button, Image, View, Text } from 'react-native';
|
||||||
|
import { createStackNavigator } from 'react-navigation-stack';
|
||||||
|
import { FlatList, BorderlessButton } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
|
class ListScreen extends React.Component {
|
||||||
|
static navigationOptions = ({ navigation }) => ({
|
||||||
|
title: 'Image list',
|
||||||
|
headerBackTitle: 'Back',
|
||||||
|
headerLeft: (
|
||||||
|
<Button title="Back" onPress={() => navigation.navigate('Home')} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
state = {
|
||||||
|
items: Array.apply(null, Array(60)).map((v, i) => {
|
||||||
|
return {
|
||||||
|
id: i,
|
||||||
|
src: `https://source.unsplash.com/random/400x${400 + i}`,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<FlatList
|
||||||
|
data={this.state.items}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<View style={{ flex: 1, flexDirection: 'column', margin: 1 }}>
|
||||||
|
<BorderlessButton
|
||||||
|
onPress={() =>
|
||||||
|
this.props.navigation.navigate('Details', {
|
||||||
|
id: item.id,
|
||||||
|
src: item.src,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Image style={{ height: 100 }} source={{ uri: item.src }} />
|
||||||
|
</BorderlessButton>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
numColumns={3}
|
||||||
|
keyExtractor={(item, index) => index}
|
||||||
|
style={{ flex: 1, backgroundColor: '#fff' }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DetailsScreen extends React.Component {
|
||||||
|
static navigationOptions = {
|
||||||
|
title: 'Random image from Unsplash',
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let id = this.props.navigation.getParam('id', 0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
source={{
|
||||||
|
uri: `https://source.unsplash.com/random/1080x${1920 + id}`,
|
||||||
|
}}
|
||||||
|
style={{ width: Dimensions.get('window').width, height: 400 }}
|
||||||
|
resizeMode="cover"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
title="Go back"
|
||||||
|
onPress={() => this.props.navigation.goBack()}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createStackNavigator(
|
||||||
|
{
|
||||||
|
List: ListScreen,
|
||||||
|
Details: DetailsScreen,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
initialRouteName: 'List',
|
||||||
|
}
|
||||||
|
);
|
|
@ -5,7 +5,14 @@ import { createStackNavigator } from 'react-navigation-stack';
|
||||||
class ListScreen extends React.Component {
|
class ListScreen extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: Math.random() > 0.5 ? '#eee' : '#ccc',
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Text>List Screen</Text>
|
<Text>List Screen</Text>
|
||||||
<Text>A list may go here</Text>
|
<Text>A list may go here</Text>
|
||||||
<Button
|
<Button
|
||||||
|
@ -24,7 +31,14 @@ class ListScreen extends React.Component {
|
||||||
class DetailsScreen extends React.Component {
|
class DetailsScreen extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: Math.random() > 0.5 ? '#eee' : '#ccc',
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Text>Details Screen</Text>
|
<Text>Details Screen</Text>
|
||||||
<Button
|
<Button
|
||||||
title="Go to Details... again"
|
title="Go to Details... again"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "react-navigation-stack",
|
"name": "react-navigation-stack",
|
||||||
"version": "1.0.0-alpha.10",
|
"version": "1.0.0-alpha.11",
|
||||||
"description": "Stack navigator component for React Navigation",
|
"description": "Stack navigator component for React Navigation",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, Platform } from 'react-native';
|
import { Animated, StyleSheet, Platform } from 'react-native';
|
||||||
import { Screen } from 'react-native-screens';
|
import { Screen } from 'react-native-screens';
|
||||||
import createPointerEventsContainer from './createPointerEventsContainer';
|
import createPointerEventsContainer from './createPointerEventsContainer';
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ function getAccessibilityProps(isActive) {
|
||||||
class Card extends React.Component {
|
class Card extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
animatedStyle,
|
||||||
children,
|
children,
|
||||||
pointerEvents,
|
pointerEvents,
|
||||||
style,
|
style,
|
||||||
|
@ -42,27 +43,35 @@ class Card extends React.Component {
|
||||||
extrapolate: 'clamp',
|
extrapolate: 'clamp',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { shadowOpacity, ...containerAnimatedStyle } = animatedStyle;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Screen
|
<Screen
|
||||||
pointerEvents={pointerEvents}
|
pointerEvents={pointerEvents}
|
||||||
onComponentRef={this.props.onComponentRef}
|
onComponentRef={this.props.onComponentRef}
|
||||||
style={[transparent ? styles.transparent : styles.main, style]}
|
style={[StyleSheet.absoluteFill, containerAnimatedStyle, style]}
|
||||||
active={active}
|
active={active}
|
||||||
{...getAccessibilityProps(isActive)}
|
|
||||||
>
|
>
|
||||||
{children}
|
<Animated.View
|
||||||
|
{...getAccessibilityProps(isActive)}
|
||||||
|
style={[
|
||||||
|
transparent ? styles.transparent : styles.card,
|
||||||
|
{ shadowOpacity },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Animated.View>
|
||||||
</Screen>
|
</Screen>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
main: {
|
card: {
|
||||||
...StyleSheet.absoluteFillObject,
|
flex: 1,
|
||||||
backgroundColor: '#E9E9EF',
|
backgroundColor: '#fff',
|
||||||
shadowColor: '#000',
|
shadowOffset: { width: -3, height: 0 },
|
||||||
shadowOffset: { width: -4, height: 0 },
|
shadowRadius: 5,
|
||||||
shadowRadius: 6,
|
|
||||||
},
|
},
|
||||||
transparent: {
|
transparent: {
|
||||||
...StyleSheet.absoluteFillObject,
|
...StyleSheet.absoluteFillObject,
|
||||||
|
|
|
@ -223,7 +223,7 @@ class StackViewLayout extends React.Component {
|
||||||
if (Platform.OS === 'ios' && supportsImprovedSpringAnimation()) {
|
if (Platform.OS === 'ios' && supportsImprovedSpringAnimation()) {
|
||||||
Animated.spring(position, {
|
Animated.spring(position, {
|
||||||
toValue,
|
toValue,
|
||||||
stiffness: 8000,
|
stiffness: 7000,
|
||||||
damping: 600,
|
damping: 600,
|
||||||
mass: 3,
|
mass: 3,
|
||||||
useNativeDriver: USE_NATIVE_DRIVER,
|
useNativeDriver: USE_NATIVE_DRIVER,
|
||||||
|
@ -735,7 +735,8 @@ class StackViewLayout extends React.Component {
|
||||||
realPosition={this.props.transitionProps.position}
|
realPosition={this.props.transitionProps.position}
|
||||||
key={`card_${scene.key}`}
|
key={`card_${scene.key}`}
|
||||||
transparent={this.props.transparentCard}
|
transparent={this.props.transparentCard}
|
||||||
style={[style, { paddingTop }, this.props.cardStyle]}
|
animatedStyle={style}
|
||||||
|
style={[{ paddingTop }, this.props.cardStyle]}
|
||||||
scene={scene}
|
scene={scene}
|
||||||
>
|
>
|
||||||
{this._renderInnerScene(scene)}
|
{this._renderInnerScene(scene)}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { I18nManager } from 'react-native';
|
import { I18nManager } from 'react-native';
|
||||||
import getSceneIndicesForInterpolationInputRange from '../../utils/getSceneIndicesForInterpolationInputRange';
|
import getSceneIndicesForInterpolationInputRange from '../../utils/getSceneIndicesForInterpolationInputRange';
|
||||||
|
|
||||||
|
const EPS = 1e-5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility that builds the style for the card in the cards stack.
|
* Utility that builds the style for the card in the cards stack.
|
||||||
*
|
*
|
||||||
|
@ -56,16 +58,15 @@ function forHorizontal(props) {
|
||||||
: [width, 0, width * -0.3],
|
: [width, 0, width * -0.3],
|
||||||
extrapolate: 'clamp',
|
extrapolate: 'clamp',
|
||||||
});
|
});
|
||||||
const translateY = 0;
|
|
||||||
|
|
||||||
const shadowOpacity = position.interpolate({
|
const shadowOpacity = position.interpolate({
|
||||||
inputRange: [first, index, last],
|
inputRange: [first - EPS, first, index, last, last + EPS],
|
||||||
outputRange: [0.01, 0.2, 0.01],
|
outputRange: [0, 0.02, 0.25, 0.02, 0],
|
||||||
extrapolate: 'clamp',
|
extrapolate: 'clamp',
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
transform: [{ translateX }, { translateY }],
|
transform: [{ translateX }],
|
||||||
shadowOpacity,
|
shadowOpacity,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -91,10 +92,9 @@ function forVertical(props) {
|
||||||
outputRange: [height, 0, 0],
|
outputRange: [height, 0, 0],
|
||||||
extrapolate: 'clamp',
|
extrapolate: 'clamp',
|
||||||
});
|
});
|
||||||
const translateX = 0;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
transform: [{ translateX }, { translateY }],
|
transform: [{ translateY }],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue