Add image example, make shadow and translate apply to different views, hide shadow on inactive screens

This commit is contained in:
Brent Vatne 2018-10-02 16:28:30 -07:00
parent f334c7645a
commit 50e54ebaf8
7 changed files with 140 additions and 21 deletions

View File

@ -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}

89
example/src/ImageStack.js Normal file
View File

@ -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',
}
);

View File

@ -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"

View File

@ -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": [

View File

@ -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,

View File

@ -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)}

View File

@ -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 }],
}; };
} }