Skip to content
This repository has been archived by the owner on Nov 26, 2019. It is now read-only.

Commit

Permalink
Basic implementation of screen header
Browse files Browse the repository at this point in the history
  • Loading branch information
satya164 committed May 20, 2019
1 parent f026959 commit 279ef91
Show file tree
Hide file tree
Showing 22 changed files with 529 additions and 62 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.DS_Store

node_modules
.expo
90 changes: 46 additions & 44 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,75 @@
import * as React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import Stack, { SceneProps, Route } from './components/Stack';
import Card from './components/Card';
import { SlideFromRightIOS } from './TransitionConfigs/TransitionPresets';

type CustomRoute = Route & { initial?: boolean };

type State = {
routes: CustomRoute[];
closing: string[];
initialRoutes: string[];
closingRoutes: string[];
};

export default class App extends React.Component<{}, State> {
state: State = {
routes: [{ key: '0', initial: true }, { key: '1', initial: true }],
closing: [],
routes: [{ key: '0' }, { key: '1' }],
initialRoutes: ['0', '1'],
closingRoutes: [],
};

private key = 2;

private renderScene = (
{ route, ...rest }: SceneProps<CustomRoute>,
index: number
) => {
private renderScene = ({ route, index }: SceneProps<CustomRoute>) => {
return (
<Card
{...rest}
closing={this.state.closing.includes(route.key)}
onClose={() =>
this.setState(state => ({
routes: state.routes.filter(r => r !== route),
closing: state.closing.filter(key => key !== route.key),
}))
}
gesturesEnabled={index !== 0}
animationsEnabled={!route.initial}
{...SlideFromRightIOS}
>
<View style={styles.scene}>
<Text style={styles.item}>{index}</Text>
<View style={styles.scene}>
<Text style={styles.item}>{index}</Text>
<View style={styles.item}>
<Button
title="Add screen"
onPress={() => {
this.setState(state => ({
routes: [...state.routes, { key: String(this.key++) }],
}));
}}
/>
</View>
{index !== 0 ? (
<View style={styles.item}>
<Button
title="Add screen"
onPress={() => {
title="Go back"
onPress={() =>
this.setState(state => ({
routes: [...state.routes, { key: String(this.key++) }],
}));
}}
closingRoutes: [...state.closingRoutes, route.key],
}))
}
/>
</View>
{index !== 0 ? (
<View style={styles.item}>
<Button
title="Go back"
onPress={() =>
this.setState(state => ({
closing: [...state.closing, route.key],
}))
}
/>
</View>
) : null}
</View>
</Card>
) : null}
</View>
);
};

render() {
return <Stack routes={this.state.routes} renderScene={this.renderScene} />;
return (
<Stack
routes={this.state.routes}
initialRoutes={this.state.initialRoutes}
closingRoutes={this.state.closingRoutes}
onGoBack={({ route }) =>
this.setState(state => ({
closingRoutes: [...state.closingRoutes, route.key],
}))
}
onCloseRoute={({ route }) =>
this.setState(state => ({
routes: state.routes.filter(r => r !== route),
closingRoutes: state.closingRoutes.filter(key => key !== route.key),
initialRoutes: state.initialRoutes.filter(key => key !== route.key),
}))
}
renderScene={this.renderScene}
/>
);
}
}

Expand Down
Binary file added src/assets/back-icon-mask.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/back-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions src/components/BorderlessButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as React from 'react';
import { Animated, Platform } from 'react-native';
import { BaseButton } from 'react-native-gesture-handler';

const AnimatedBaseButton = Animated.createAnimatedComponent(BaseButton);

type Props = React.ComponentProps<typeof BaseButton> & {
activeOpacity: number;
};

export default class BorderlessButton extends React.Component<Props> {
static defaultProps = {
activeOpacity: 0.3,
borderless: true,
};

private opacity = new Animated.Value(1);

private handleActiveStateChange = (active: boolean) => {
if (Platform.OS !== 'android') {
Animated.spring(this.opacity, {
stiffness: 1000,
damping: 500,
mass: 3,
overshootClamping: true,
restDisplacementThreshold: 0.01,
restSpeedThreshold: 0.01,
toValue: active ? this.props.activeOpacity : 1,
useNativeDriver: true,
}).start();
}

this.props.onActiveStateChange && this.props.onActiveStateChange(active);
};

render() {
const { children, style, enabled, ...rest } = this.props;

return (
<AnimatedBaseButton
{...rest}
onActiveStateChange={this.handleActiveStateChange}
style={[
style,
Platform.OS === 'ios' && enabled && { opacity: this.opacity },
]}
>
{children}
</AnimatedBaseButton>
);
}
}
10 changes: 7 additions & 3 deletions src/components/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { StyleSheet } from 'react-native';
import { View, StyleSheet } from 'react-native';
import Animated from 'react-native-reanimated';
import {
PanGestureHandler,
Expand Down Expand Up @@ -363,7 +363,7 @@ export default class Card extends React.Component<Props> {
: this.handleGestureEventHorizontal;

return (
<React.Fragment>
<View style={styles.container} pointerEvents="box-none">
<Animated.Code exec={this.translate} />
{overlayStyle ? (
<Animated.View
Expand All @@ -380,18 +380,22 @@ export default class Card extends React.Component<Props> {
{children}
</Animated.View>
</PanGestureHandler>
</React.Fragment>
</View>
);
}
}

const styles = StyleSheet.create({
container: {
flex: 1
},
card: {
...StyleSheet.absoluteFillObject,
shadowOffset: { width: -1, height: 1 },
shadowRadius: 5,
shadowColor: '#000',
backgroundColor: 'white',
elevation: 2
},
overlay: {
...StyleSheet.absoluteFillObject,
Expand Down
Loading

0 comments on commit 279ef91

Please sign in to comment.