React Native 自定义实现 自下而上淡入淡出弹框

选择弹出模态框

import React from 'react'
import {Animated, Easing, Dimensions,TouchableOpacity,BackHandler} from 'react-native'
const { width, height } = Dimensions.get("screen")

/**
 * 自定义自下而上淡入淡出弹框
 */
export class OptionModel extends React.Component{
    constructor(state) {
        super(state)
        this.state = {
          offset: new Animated.Value(0),
          fadeOutOpacity: new Animated.Value(0),
          show: false,
        };
    }
    
    componentDidMount(){
        BackHandler.addEventListener('hardwareBackPress',this.onBackAndroid)
    }

    componentWillUnmount(){
        this.hide()
        BackHandler.removeEventListener('hardwareBackPress',this.onBackAndroid);
    }

    onBackAndroid=()=>{
        this.hide()
        if(this.state.show){
            return true;
        }else{
            return false;
        }
    }

    show(){
        this.setState({show:true})
        Animated.parallel(
            [
              Animated.timing(
                this.state.fadeOutOpacity,
                {
                    toValue: 1,//透明度动画最终值
                    duration: 300,//动画时长3000毫秒
                    easing:Easing.inOut(Easing.poly(4)),
                    useNativeDriver: true
                }
              ),
              Animated.spring(
                this.state.offset,
                {
                  friction:7,    //弹跳系数
                  tension:20, 
                //   easing: Easing.out(Easing.poly(4)),
                //   duration: 250,
                  toValue: 1,
                  useNativeDriver: true
                }
              )
            ],
            {
              stopTogether: false
            }
          ).start()
    }

    hide(){
        Animated.parallel(
            [
              Animated.timing(
                this.state.fadeOutOpacity,
                {
                    toValue: 0,//透明度动画最终值
                    duration: 300,//动画时长3000毫秒
                    easing: Easing.in(Easing.poly(8)),
                    useNativeDriver: true
                }
              ),
              Animated.spring(
                this.state.offset,
                {
                    friction:7,    //弹跳系数
                    tension:20, 
                //   easing: Easing.in(Easing.poly(4)),
                //   duration: 250,
                    toValue: 0,
                    useNativeDriver: true
                }
              )
            ],
            {
              stopTogether: false
            }
          ).start()
          setTimeout(
            () => this.setState({ show: false }),
            300
          )
    }

    render(){
        const {heights,children} = this.props;

        if(this.state.show){
            return(<Animated.View style={{width:width,backgroundColor: 'rgba(0, 0, 0, 0.3)',position:'absolute',
                top: 0,
                zIndex: 9,
                height: height ,
                opacity: this.state.fadeOutOpacity
                }}>
                <TouchableOpacity style={{flex:1}} onPress={()=>this.hide()}></TouchableOpacity>
                <Animated.View style={{zIndex:15,
                 transform: [{
                  translateY: this.state.offset.interpolate({
                    inputRange: [0, 1],
                    outputRange: [heights,0]
                  }),
                }]
              }}>
                {children}
                </Animated.View>
            </Animated.View>)
        }else{
            return false
        }
    }
}

实现代码

点击显示按钮

<TouchableOpacity onPress={() => this.refs.OptionModelView.show()} >
  <Text style={{fontSize : 18}} >显示</Text>
</TouchableOpacity>

实现代码

data数据结构,也可以自己自定义;
data = [
{name : string, value : srting},
{name : string, value : srting},
{name : string, value : srting}
]

<OptionModel ref={'OptionModelView'} heights={300}>
    <View style={{height:300, backgroundColor:'white', width : '100%', paddingVertical : 10, paddingBottom : 100 }} >
            <ScrollView  showsHorizontalScrollIndicator={false} >
                {
                    data.map((item ,index) => {
                        let check = (item['value'] === defaultValue);
                        return(
                          <TouchableOpacity
                            key={`${index}`}
                            style={{
                                width:'100%', flexDirection:'row', justifyContent:'center',
                                paddingVertical : 10,borderBottomWidth : 1, borderBottomColor : '#eee', textAlign : 'center'
                            }}
                            onPress={() => {
                            this.setState({ defaultValue: item['value']})
                            }}
                          >
                              <Text style={{color:(check ? '#0793D2' : 'black'), fontSize : 18}} >{item['name'] || '--'}</Text>
                          </TouchableOpacity>
                        )
                    })
                }
            </ScrollView>
        </View>
    </OptionModel>

实现效果 在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简青子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值