Skip to content

Instantly share code, notes, and snippets.

@kiok46
Created August 4, 2017 20:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kiok46/58c354d0ec2a42cd104e501a3c2f8de4 to your computer and use it in GitHub Desktop.
Save kiok46/58c354d0ec2a42cd104e501a3c2f8de4 to your computer and use it in GitHub Desktop.
Snapping Header

Snapping Header

import React, { Component } from 'react';
import {
  View,
  Animated,
  PanResponder,
  ActivityIndicator,
  StyleSheet
} from 'react-native';
import {Constants} from 'expo'

export const withSnap = ({
  startValue = 0,
  endValue = 0,
  duration = 200
}) => WrappedComponent => {
  return class SnapHeader extends Component {
    animatedValue = new Animated.Value(startValue);

    componentWillMount() {
      this._panResponder = PanResponder.create({
        onMoveShouldSetResponderCapture: () => true,
        onMoveShouldSetPanResponderCapture: () => true,

        onPanResponderMove: (e, gestureState) => {
          if (gestureState.dy < 0 && Math.abs(gestureState.dy) > 30) {
            Animated.timing(this.animatedValue, {
              duration,
              toValue: endValue,
            }).start();
          } else if (gestureState.dy > 0 && Math.abs(gestureState.dy) > 30) {
            Animated.timing(this.animatedValue, {
              duration,
              toValue: startValue,
            }).start();
          }
        },
      });
    }

    render() {
      return (
        <View>
      <ActivityIndicator size="small" />
    
        <WrappedComponent
          {...this.props}
          snap={{
            panHandlers: this._panResponder.panHandlers,
            animatedValue: this.animatedValue,
          }}
        />
        </View>
      );
    }
  };
};

export const Header = props =>
  <View {...props.snap.panHandlers}>
    <Animated.View
      style={{
        backgroundColor: 'black',
        height: props.snap.animatedValue.interpolate({
          inputRange: [0, 1],
          outputRange: [500, 50],
          extrapolate: 'clamp',
        }),
        justifyContent: 'center',
        alignItems: 'center',
        position: 'relative',
      }}
    >
      <Animated.Text
        style={{
          fontSize: props.snap.animatedValue.interpolate({
            inputRange: [0, 1],
            outputRange: [48, 24],
            extrapolate: 'clamp',
          }),
          fontWeight: 'bold',
          color: 'white',
          textAlign: 'center',
        }}
      >
        OH SNAP!
      </Animated.Text>
    </Animated.View>
  </View>;

const HeaderWithSnap = withSnap({ startValue: 0, endValue: 1, duration: 200 })(Header);

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <HeaderWithSnap />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
  },
});

cool!

@kiok46
Copy link
Author

kiok46 commented Aug 4, 2017

screen shot 2017-08-05 at 2 14 23 am screen shot 2017-08-05 at 2 14 35 am screen shot 2017-08-05 at 2 14 50 am

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment