Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, { Component } from 'react';
- import {
- ActivityIndicator,
- Platform,
- StyleSheet,
- Text,
- TouchableHighlight,
- TouchableNativeFeedback,
- View
- } from 'react-native';
- import Animated, { Easing } from 'react-native-reanimated';
- const {
- set,
- interpolate,
- cond,
- startClock,
- stopClock,
- clockRunning,
- block,
- timing,
- debug,
- Value,
- Clock,
- } = Animated;
- const Spinner = () =>
- <View style={spinnerStyle.main}>
- <ActivityIndicator/>
- </View>;
- const magicVal = 1.4142133;
- const spinnerStyle = StyleSheet.create({
- main: {
- backgroundColor: '#1b9779',
- width: 70,
- justifyContent: 'center',
- alignItems: 'center',
- height: 70,
- borderRadius: 35
- }
- });
- const ButtonWrapper = Platform.OS === 'android' ? TouchableNativeFeedback : TouchableHighlight;
- function runTiming(clock, value, dest) {
- const state = {
- finished: new Value(0),
- position: new Value(0),
- time: new Value(0),
- frameTime: new Value(0),
- };
- const config = {
- duration: 1000,
- toValue: new Value(0),
- easing: Easing.inOut(Easing.ease),
- };
- return block([
- cond(clockRunning(clock), 0, [
- set(state.finished, 0),
- set(state.time, 0),
- set(state.position, value),
- set(state.frameTime, 0),
- set(config.toValue, dest),
- startClock(clock),
- ]),
- timing(clock, state, config),
- cond(state.finished, debug('stop clock', stopClock(clock))),
- state.position,
- ]);
- }
- class Loadable extends React.Component {
- constructor(props) {
- super(props);
- if (props.isLoading) {
- console.warn('Should not load at the very beginning');
- }
- this.state = {
- hiding: false,
- showing: false
- };
- }
- _spinnerWidth = new Value(0);
- _spinnerHeight = new Value(0);
- _buttonWidth = new Value(0);
- _buttonHeight = new Value(0);
- _trans = runTiming(new Clock(), 0, 1);
- _onLayoutSpinner = event => {
- const { width, height } = event.nativeEvent.layout;
- this._spinnerHeight = height;
- this._spinnerWidth = width;
- };
- _onLayoutButton = event => {
- const { width, height } = event.nativeEvent.layout;
- this._buttonHeight = height;
- this._buttonWidth = width;
- };
- shouldComponentUpdate(newProps) {
- if (!this.props.isLoading && newProps.isLoading) {
- this.setState({
- hiding: false,
- showing: true
- });
- }
- if (this.props.isLoading && !newProps.isLoading) {
- this.setState({
- hiding: true,
- showing: false
- });
- }
- return true;
- }
- renderButtonWrapper = (disabled = false) =>
- <ButtonWrapper
- disabled={disabled}
- style={{ borderRadius: 5 }}
- onPress={this.props.onPress}
- >
- {this.props.renderButton()}
- </ButtonWrapper>;
- render() {
- return (
- <View style={styles.container}>
- {!this.state.showing && !this.state.hiding &&
- <View style={styles.box}>
- <View onLayout={this._onLayoutSpinner} style={{
- position: 'absolute',
- opacity: 0
- }}>
- {this.props.renderLoading()}
- </View>
- <View onLayout={this._onLayoutButton} style={{
- position: 'absolute',
- justifyContent: 'center',
- alignItems: 'center',
- }}>
- {this.renderButtonWrapper()}
- </View>
- </View>
- }
- {this.state.showing &&
- <View style={styles.box}>
- <Animated.View style={{
- position: 'absolute',
- opacity: interpolate(this._trans, {
- inputRange: [0.4, 1],
- outputRange: [0, 1]
- }),
- }}>
- {this.props.renderLoading()}
- </Animated.View>
- <Animated.View style={{
- position: 'absolute',
- justifyContent: 'center',
- alignItems: 'center',
- borderRadius: interpolate(this._trans, {
- inputRange: [0.3, 0.6],
- outputRange: [4, this._spinnerWidth * magicVal]
- }),
- width: interpolate(this._trans, {
- inputRange: [0.2, 0.5, 1],
- outputRange: [this._buttonWidth, this._spinnerWidth, this._spinnerWidth]
- }),
- height: interpolate(this._trans, {
- inputRange: [0, 0.6, 1],
- outputRange: [this._buttonHeight, this._spinnerHeight, this._spinnerHeight]
- }),
- overflow: 'hidden',
- opacity: interpolate(this._trans, {
- inputRange: [0.6, 1],
- outputRange: [1, 0]
- }),
- }}>
- {this.renderButtonWrapper(true)}
- </Animated.View>
- </View>
- }
- {this.state.hiding &&
- <View style={styles.box}>
- <Animated.View style={{
- position: 'absolute',
- opacity: interpolate(this._trans, {
- inputRange: [0, 0.3],
- outputRange: [1, 0]
- }),
- }}>
- {this.props.renderLoading()}
- </Animated.View>
- <Animated.View style={{
- position: 'absolute',
- justifyContent: 'center',
- alignItems: 'center',
- borderRadius: interpolate(this._trans, {
- inputRange: [0, 0.4, 0.7],
- outputRange: [this._spinnerWidth * magicVal, this._spinnerWidth * magicVal, 4]
- }),
- width: interpolate(this._trans, {
- inputRange: [0, 0.2, 0.5, 1],
- outputRange: [this._spinnerWidth, this._spinnerWidth, this._buttonWidth, this._buttonWidth]
- }),
- height: interpolate(this._trans, {
- inputRange: [0, 0.6, 1],
- outputRange: [this._spinnerHeight, this._buttonHeight, this._buttonHeight]
- }),
- overflow: 'hidden',
- opacity: interpolate(this._trans, {
- inputRange: [0, 0.45, 1],
- outputRange: [0, 1, 1]
- }),
- }}>
- {this.renderButtonWrapper()}
- </Animated.View>
- </View>
- }
- </View>
- );
- }
- }
- export default class Example extends React.Component {
- state = {
- isLoading: false
- };
- _timeout;
- componentWillUnmount() {
- clearTimeout(this._timeout);
- }
- renderButton = () =>
- <View style={styles.button}>
- <Text style={{ color: 'white' }}>
- Press me press me say that you pres me
- </Text>
- </View>;
- renderLoading = () =>
- <Spinner/>;
- render() {
- return (
- <View style={styles.container}>
- <Loadable
- onPress={() => {
- clearTimeout(this._timeout);
- this.setState({ isLoading: true });
- this._timeout = setTimeout(() => this.setState({ isLoading: false }), 5000);
- }}
- isLoading={this.state.isLoading}
- renderButton={this.renderButton}
- renderLoading={this.renderLoading}
- />
- </View>
- );
- }
- }
- const styles = StyleSheet.create({
- button: {
- borderRadius: 5,
- backgroundColor: '#3167ff',
- justifyContent: 'center',
- alignItems: 'center',
- width: 220,
- height: 100
- },
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: 'white',
- },
- box: {
- justifyContent: 'center',
- alignItems: 'center',
- },
- box2: {
- width: 20,
- height: 60,
- backgroundColor: 'red',
- marginBottom: 40
- }
- });
Add Comment
Please, Sign In to add comment