React Native 通告消息竖向轮播组件封装

移动开发 waitig 1121℃ 百度已收录 0评论
import React, {Component} from 'react'
import {
    Text,
    View,
    Animated,
    Easing,
    StyleSheet,
} from 'react-native'

export default class ScrollVertical extends Component {
    static defaultProps = {
        enableAnimation: true,
    };

    constructor(props) {
        super(props)
        let translateValue= new Animated.ValueXY({x: 0, y: 0})
        translateValue.addListener(({x,y})=>{
           // Log('value',x,y)
        })
        this.state = {
            translateValue: translateValue,
            // 滚屏高度
            scrollHeight: this.props.scrollHeight || 32,
            // 滚屏内容
            kb_content: [],
            // Animated.View 滚动到的 y轴坐标
            kb_tempValue: 0,
            // 最大偏移量
            kb_contentOffsetY: 0,
            // 每一次滚动切换之前延迟的时间
            delay: this.props.delay || 500,
            // 每一次滚动切换的持续时间
            duration: this.props.duration || 500,
            enableAnimation: true,
        }
    }

    render() {
        return (
            <View style={[styles.kbContainer, {height: this.state.scrollHeight}, this.props.kbContainer]}>
                {
                    this.state.kb_content.length !== 0 ?
                        <Animated.View
                            style={[
                                {flexDirection: 'column'},
                                {
                                    transform: [
                                        {translateY: this.state.translateValue.y}
                                    ]
                                }
                            ]}>
                            {this.state.kb_content.map(this._createKbItem.bind(this))}
                        </Animated.View> : null
                }
            </View>
        )
    }

    componentWillReceiveProps(nextProps) {
        Log('componentWillReceiveProps', nextProps)
            this.setState({
                    enableAnimation: nextProps.enableAnimation?true:false
                }, () => {
                    this.startAnimation();
                }
            )
    }

    componentDidMount() {
        Log('componentDidMount')
        let content = this.props.data || []
        if (content.length !== 0) {
            let h = (content.length + 1) * this.state.scrollHeight
            this.setState({
                kb_content: content.concat(content[0]),
                kb_contentOffsetY: h
            })

            // 开始动画
            // this._startAnimation()
            this.startAnimation();
        }
    }


    _createKbItem(kbItem, index) {
        return (
            <View key={index}
                  style={[{justifyContent: 'center', height: this.state.scrollHeight}, this.props.scrollStyle]}>
                <Text style={[styles.kb_text_c, this.props.textStyle]}>{kbItem.content}</Text>
            </View>
        )
    }

    startAnimation = () => {
        if (this.state.enableAnimation) {
            if(!this.animation){
                this.animation = setTimeout(() => {
                    this.animation=null;
                    this._startAnimation();
                }, this.state.delay);
            }

        }

    }

    componentWillUnmount() {
        if (this.animation) {
            clearTimeout(this.animation);
        }
        if(this.state.translateValue){
            this.state.translateValue.removeAllListeners();
        }
    }

    _startAnimation = () => {
        this.state.kb_tempValue -= this.state.scrollHeight;
        if (this.props.onChange) {
            let index = Math.abs(this.state.kb_tempValue) / (this.state.scrollHeight);
            this.props.onChange(index<this.state.kb_content.length-1?index:0);
        }
        Animated.sequence([

            // Animated.delay(this.state.delay),
            Animated.timing(
                this.state.translateValue,
                {
                    isInteraction: false,
                    toValue: {x: 0, y: this.state.kb_tempValue},
                    duration: this.state.duration, // 动画持续的时间(单位是毫秒),默认为500
                    easing: Easing.linear
                }
            ),
        ])
            .start(() => {
                // 无缝切换
                // Log('end')
                if (this.state.kb_tempValue - this.state.scrollHeight === -this.state.kb_contentOffsetY) {
                    // 快速拉回到初始状态
                    this.state.translateValue.setValue({x: 0, y: 0});
                    this.state.kb_tempValue = 0;
                }
                this.startAnimation();



            })
    }
}

const styles = StyleSheet.create({
    kbContainer: {
        // 必须要有一个背景或者一个border,否则本身高度将不起作用
        backgroundColor: 'transparent',
        overflow: 'hidden'
    },
    kb_text_c: {
        fontSize: 18,
        color: '#181818',
    }

使用

import React, {Component} from 'react';
import {
    StyleSheet,
    View,
    TouchableOpacity,
    Alert,
    ScrollView,
    ART,
    TouchableHighlight,
    ListView,
    Dimensions,
    Text
} from 'react-native';

import ScrollVertical from '../../app-widget/scroll-vertical'


const dataArray = [
    {
        title: '降价了',
    },
    {
        title: '全场五折',
    },
    {
        title: '打到骨折',
    }
]
export default class extends React.Component {

    render() {
        let array = [{ content: '' }];
        if (dataArray && dataArray.length > 0) {
            array = [];
            for (let item of dataArray) {
                array.push({ content: item.title});
            }
        }
        return (
            <View style={{ padding: Constant.sizeMarginDefault, paddingBottom: 0, backgroundColor: '#FFFFFF' }}>
                <TouchableOpacity onPress={() => {
                    if (dataArray && dataArray.length > 0) {
                       Log(dataArray[this.index].title)
                    }
                }} style={{ flexDirection: 'row', backgroundColor: "#FFFFFF", alignItems: 'center', borderRadius: 8, paddingLeft: 5, paddingRight: 5 }}>
                    <Text style={{ fontSize: Constant.scaleFontSize(14) }} fontWeight={'bold'}>公告</Text>
                    <View style={{ marginLeft: 5, marginRight: 8, backgroundColor: '#b01638', borderRadius: 8, width: 22, alignItems: 'center', }}>
                        <Text style={{ color: 'white', fontSize: Constant.fontSizeSmall }}></Text>
                    </View>
                    <View style={{ flexDirection: 'row', flex: 1 }}>
                        <ScrollVertical
                            onChange={(index => {
                                this.index = index;
                            })}
                            enableAnimation={true}
                            data={array}
                            delay={2500}
                            duration={1000}
                            scrollHeight={34}
                            scrollStyle={{ alignItems: 'flex-start' }}
                            textStyle={{ color: Constant.colorTxtContent, fontSize: Constant.fontSizeSmall }} />
                    </View>
                    <View style={{ height: 14, width: 1, backgroundColor: Constant.colorTxtContent }} />
                    <Text style={{ color: Constant.colorTxtContent, paddingLeft: Constant.sizeMarginDefault, fontSize: Constant.fontSizeSmall }}>查看</Text>
                </TouchableOpacity>
            </View>
        );

    }
};

这里写图片描述


本文由【waitig】发表在等英博客
本文固定链接:React Native 通告消息竖向轮播组件封装
欢迎关注本站官方公众号,每日都有干货分享!
等英博客官方公众号
点赞 (0)分享 (0)