[React Native]从状态栏下面滑出Banner

以Toast banner形式显示一些状态信息,为了更友好,加上动画效果。

注意第一次得到layout需要initBanner,否则showBanner的效果坐标不对。
也就是实际上上先收起来,再滑出来。

代码如下,banner内容自定义即可。

import React from 'react';
import {
  StyleSheet,
  Text, View, TouchableHighlight,
  Animated
} from 'react-native';


export default class AboutComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      bannerHeight: 0
    };
    this.position = new Animated.ValueXY(0, 0)
  }

  moveBanner = (duration, yPos) => {
    Animated.timing(this.position, {
      useNativeDriver: false,
      duration: duration,
      toValue: { x: 0, y: yPos }
    }).start()
  }

  initBanner = () => {
    this.moveBanner(1, 0 - this.state.bannerHeight);
  }

  showBanner = () => {
    this.moveBanner(500, 0);
  }

  hideBanner = () => {
    this.moveBanner(500, 0 - this.state.bannerHeight);
  }

  onBannerLayout = (e) => {
    this.setState({
      bannerHeight: e.nativeEvent.layout.height,
    }, () => {
      this.initBanner();
    });
  }

  render() {

    return (
      
        
          
            Banner Message
            
              Content
            
             this.hideBanner()} >
              Hide Banner
            
             this.showBanner()} >
              Show Banner
            
          
        
      
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'gray',
  },
  button: {
    alignSelf: 'center',
    color: 'blue',
    fontSize: 20,
  },
  square: {
    backgroundColor: 'red',
    padding: 20,
    alignSelf: 'center',
    width: '100%',
  }

});

改进版(自适应高度)

import React from 'react';
import {
  StyleSheet,
  Text, View, TouchableHighlight,
  Animated
} from 'react-native';

const bannerMargin = 10;

export default class BannerTestComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      message: '',
      makeBannerBackground: true,
      marginAnimation: new Animated.Value(0),
    };
    this.displayBanner = false;
    this.bannerHeight = 0;
    this.messages = [
      "Banner\nBanner\n\Banner",
      "Simple one line message",
      "Two lines message.\nTwo lines message.\n"
    ];
    this.count = 0
  }

  moveBanner = (duration, marginTop) => {
    console.log(`moveBanner ${duration} ${marginTop}`);
    Animated.timing(
      this.state.marginAnimation, {
      useNativeDriver: false,
      toValue: marginTop,
      duration
    }).start();
  }

  initBanner = () => {
    console.log('initBanner');
    this.moveBanner(0, 0 - this.bannerHeight);
  }

  showBanner = () => {
    console.log('showBanner');
    this.count += 1;
    const message = this.messages[this.count % this.messages.length];
    this.displayBanner = true;
    this.setState({
      message,
    });
  }

  hideBanner = () => {
    console.log('hideBanner');
    this.displayBanner = false;
    this.moveBanner(500, 0 - this.bannerHeight);
    setTimeout(() => {
      this.moveBanner(0, 0);
      this.setState({
        message: '',
        makeBannerBackground: true
      });
    }, 600);
  }

  onBannerLayout = (e) => {
    const bannerHeight = e.nativeEvent.layout.height;
    console.log(`onBannerLayout ${bannerHeight}`);
    if (bannerHeight > 0 && this.displayBanner) {
      console.log(`onBannerLayout 2 ${bannerHeight}`);
      this.bannerHeight = bannerHeight + bannerMargin * 2;
      this.setState({
        makeBannerBackground: false
      });
      this.initBanner();
      setTimeout(() => {
        this.moveBanner(500, 0)
      }, 1);
    }
  }

  render() {
    console.log('Render')
    return (
      
        
          
            {
              this.displayBanner && (
                
                  {this.state.message}
                
              )
            }
            
              Content
            
             this.hideBanner()} >
              Hide Banner
            
             this.showBanner('Banner Message\nBanner Message')} >
              Show Banner
            
          
        
      
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'gray',
  },
  button: {
    alignSelf: 'center',
    color: 'blue',
    fontSize: 20,
  },
  square: {
    backgroundColor: 'red',
    margin: bannerMargin,
    alignSelf: 'center',
    width: '100%',
  }
});

你可能感兴趣的:([React Native]从状态栏下面滑出Banner)