• 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>
                                );
                            }}
                        />

     最张效果如图:

  • 相关阅读:
    取得元素节点的默认display值
    mass Framework emitter模块 v2
    memset函数详细说明
    八大排序算法总结
    电脑很卡,怎么办?这里帮你解决
    Android APK反编译详解(附图)
    java环境变量配置
    如何使用U盘安装操作系统 安装GHOST XP, xp纯净版
    c# WinForm开发 DataGridView控件的各种操作总结(单元格操作,属性设置)
    Js apply 方法 详解
  • 原文地址:https://www.cnblogs.com/efenghuo/p/7069821.html
Copyright © 2020-2023  润新知