CategorySelector.js 4.16 KB
'use strict';

import React, {Component} from 'react';
import {Dimensions, ListView, StyleSheet, Text, TouchableOpacity, View,} from 'react-native';
import Immutable from 'immutable';

export default class CategorySelector extends Component {


    constructor(props) {
        super(props);

        this.dataSource = new ListView.DataSource({
            rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
        });

        this.renderRow = this.renderRow.bind(this);
        this.scrollToCenter = this.scrollToCenter.bind(this);

        this.listView = null;
        this.scrollContentWidth = 0;
        this.rowPosition = {};

    }

    scrollToCenter(rowID) {
        if (!this.listView) {
            return;
        }

        let rowLayout = this.rowPosition[rowID];
        if (!rowLayout) {
            return;
        }

        let rowX = rowLayout.x;
        let rowWidth = rowLayout.width;

        if (this.scrollContentWidth < width) {
            return;
        }
        // 位于列表头,且x坐标 < 屏幕x中心距离
        if (rowX + rowWidth / 2 < width / 2) {
            this.listView && this.listView.scrollTo({x: 0, y: 0, animated: true});
            return;
        }

        // 位于列表尾,且(容器宽度-x坐标)< 屏幕x中心距离
        if ((this.scrollContentWidth - rowX - rowWidth / 2) < width / 2) {
            this.listView && this.listView.scrollTo({x: this.scrollContentWidth - width, y: 0, animated: true});
            return;
        }

        let scrollX = rowX + rowWidth / 2 - width / 2 + 5;

        this.listView && this.listView.scrollTo({x: scrollX, y: 0, animated: true});
    }

    renderRow(rowData, sectionID, rowID, highlightRow) {
        let marginLeft = (rowID == 0) ? 0 : 22;
        let color = rowID == this.props.selectedCategoryIndex ? '#444444' : '#b0b0b0';
        let fontWeight = rowID == this.props.selectedCategoryIndex ? 'bold' : 'normal';
        return (
            <TouchableOpacity
                key={'row' + rowID}
                activeOpacity={1}
                style={styles.rowContainer}
                onPress={() => {
                    this.scrollToCenter(rowID);
                    this.props.onPressCategory && this.props.onPressCategory(rowData, rowID);
                    this.props.changeCategorySelectorTitle && this.props.changeCategorySelectorTitle(rowData);
                }}
                onLayout={(event) => {
                    this.rowPosition[rowID] = event.nativeEvent.layout;
                }}
            >
                <View style={[styles.categoryContainer, {marginLeft}]}>
                    <Text style={[styles.categoryName, {color, fontWeight}]}>{rowData.get('sort_name')}</Text>
                </View>
            </TouchableOpacity>
        );
    }

    render() {
        let data = this.props.data;
        return (
            <View style={styles.container}>
                <ListView
                    ref={(c) => {
                        this.listView = c;
                    }}
                    enableEmptySections={true}
                    contentContainerStyle={styles.contentContainer}
                    dataSource={this.dataSource.cloneWithRows(data.toArray())}
                    renderRow={this.renderRow}
                    horizontal={true}
                    showsHorizontalScrollIndicator={false}
                    onContentSizeChange={(contentWidth, contentHeight) => {
                        this.scrollContentWidth = contentWidth;
                    }}
                />
                {data.size > 0 ? <View style={styles.line}/> : null}
            </View>
        );
    }
};

let {width} = Dimensions.get('window');

let styles = StyleSheet.create({
    container: {
        height: 44,
        backgroundColor: 'white',
        flexDirection: 'row',
    },
    contentContainer: {
        marginLeft: 15,
    },
    rowContainer: {
        justifyContent: 'center',
    },
    categoryContainer: {
        marginRight: 22
    },
    categoryName: {
        fontSize: 14,
        color: '#b0b0b0',
    },
    line: {
        position: 'absolute',
        width,
        height: 1,
        left: 0,
        bottom: 0,
        backgroundColor: '#e5e5e5',
    },
});