React Native 仿天貓物流跟蹤時間軸


最近心血來潮開始學習ReactNative,正好最近有一個項目可能會用到時間軸,頁面原型類似於天貓的物流跟蹤,如下圖

分析之后決定使用ListView來實現,左邊的時間軸則使用Art來繪制。

 

分析左邊的時間軸,其實就是每一行都有一條豎線,第一行和最后一行稍微特殊些,第一行需要單獨繪制一下,最后一行只顯示軸結點上方的線。

為了方便使用,封裝成組件,具體實現如下:

import React, { Component } from 'react';
import {
    View,
    Text,
    ListView,
    StyleSheet,
    ART
} from 'react-native';

const { Surface, Shape, Path } = ART;

export default class TimeAxis extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            rowHeight: 60,
            dataSource: new ListView.DataSource({
                rowHasChanged: (row1, row2) => row1 !== row2,
            }),
        };
    }

    componentDidMount() {
        if (this.props.direction) {
            this.props.dataSource = this.props.dataSource.reverse();
        }
        this.setState({
            rowHeight: this.props.rowHeight ? this.props.rowHeight : this.state.rowHeight,
            dataSource: this.state.dataSource.cloneWithRows(this.props.dataSource ? this.props.dataSource : [])
        })
    }

    _renderRow = (rowData, sectionID, rowID) => {
        var item;
        if (this.props.row) {
            item = this.props.row(rowData, rowID, this.state.dataSource.getRowCount());
        } else {
            item = <Text>{rowData}</Text>
        }
        const line = new Path();
        const circle = new Path();

        let circleColor = "#e1e1e1";
        var back;
        if (rowID == 0) {
            line.moveTo(12, 27).lineTo(12, this.state.rowHeight).close();

            circle.moveTo(12, 9)
                .arc(0, 14, 7)
                .arc(0, -14, 7)
                .close();
            circleColor = "#59c93b";

            back = <ART.Shape style={{ zoom: 999, opacity: 0.1 }} d={new Path()
                .moveTo(12, 6)
                .arc(0, 20, 10)
                .arc(0, -20, 10)
                .close()} fill="#d3e2cf"></ART.Shape>
        }
        else {
            let y = this.state.rowHeight;
            if (rowID == this.state.dataSource.getRowCount() - 1) {
                y = this.state.rowHeight * 0.25;
            }
            line.moveTo(12, 0)
                .lineTo(12, y).close();

            circle.moveTo(12, this.state.rowHeight * 0.25)
                .arc(0, 10, 5)
                .arc(0, -10, 5)
                .close();
        }

        var itemStyles = this.props.itemStyle ? [styles.item_content, this.props.itemStyle] : styles.item_content;

        return (
            <View style={[styles.item, { height: this.state.rowHeight }]}>
                <View style={[styles.item_line]}>
                    <ART.Surface width={24} height={this.state.rowHeight}>
                        {back}
                        <ART.Shape d={circle} fill={circleColor} stroke="#e1e1e1" strokeWidth={1}></ART.Shape>
                        <ART.Shape d={line} stroke="#e1e1e1" strokeWidth={1}></ART.Shape>
                    </ART.Surface>
                </View>
                <View style={itemStyles}>{item}</View>
            </View >
        );
    }

    render() {
        return (
            <ListView
                style={{ marginTop: 5, backgroundColor: '#fff' }}
                dataSource={this.state.dataSource}
                renderRow={this._renderRow.bind(this)}
                renderFooter={this.renderFooter}
            />
        );
    }
}
const styles = StyleSheet.create({
    item: {
        marginTop: 1,
        backgroundColor: '#fff',
        flexDirection: 'row'
    },
    item_line: {
        flex: 2,
        paddingLeft: 5,

    },
    item_content: {
        flex: 13,
        borderBottomWidth: 1,
        borderColor: '#b0b0b0'
    }
});

 使用就簡單了,設置好dataSource

var source = [
            { Text: "包裹等待攬收", Time: "2017-06-02 11:49:00" },
            { Text: "[北京市]XX快遞 北京XX中心收件員XX已攬件", Time: "2017-06-02 15:49:05" },
            { Text: "[北京市]北京XX中心已發出", Time: "2017-06-02 16:20:11" },
            { Text: "[北京市]快件已到達XX站點", Time: "2017-06-02 20:15:04" },
            { Text: "[北京市]XX站點員:XXX正在派件", Time: "2017-06-03 07:35:18" },
            { Text: "[北京市]已完成", Time: "2017-06-03 08:21:48" }
        ];

設置行高(默認60),設置好每行的顯示格式,就可以了。

<TimeAxis
                        itemStyle={{}}
                        rowHeight={60}
                        dataSource={source}
                        row={(rowData, i, count) => {
                            var fontColor = '#757575';
                            if (i == 0) {
                                fontColor = 'green';
                            }
                            return (
                                <View style={{ height: '100%', padding: 5 }}>
                                    <Text style={{ color: fontColor, flex: 1 }}>{rowData.Text}</Text>
                                    <Text style={{ color: fontColor, alignItems: 'flex-end' }}>{rowData.Time}</Text>
                                </View>
                            );
                        }}
                    />

 

 最張效果如圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM