1. 程式人生 > >React Native 省市區地址選擇器(仿京東)

React Native 省市區地址選擇器(仿京東)

產品經理:“你明白吧,這裡向右劃可以出選單,然後需要一個閃爍的動畫,還有,我想這個tab可以拉下來,你懂吧? 設計師:“別廢話,把你要抄的產品給我看下。”

接下來,我們仿一下別人家的地址挑選器
省市區資料格式的json檔案

這裡寫圖片描述

import React, { Component, PropTypes } from 'react';
import {
    ViewPropTypes,
    StyleSheet,
    View,
    TouchableOpacity,
    TouchableNativeFeedback,
    Platform,
    Animated,
    Text
} from 'react-native'
; export default class SelectCityTabBar extends Component { //屬性聲名 static propTypes = { goToPage: PropTypes.func, activeTab: PropTypes.number, tabs: PropTypes.array, backgroundColor: PropTypes.string, activeTextColor: PropTypes.string, inactiveTextColor
: PropTypes.string, textStyle: Text.propTypes.style, tabStyle: ViewPropTypes.style, renderTab: PropTypes.func, underlineStyle: ViewPropTypes.style, }; //預設屬性 static defaultProps = { activeTextColor: '#FA3D4F', inactiveTextColor: 'black', backgroundColor
: null, } renderTab(name, page, isTabActive, onPressHandler) { const { activeTextColor, inactiveTextColor, textStyle, } = this.props; const textColor = isTabActive ? activeTextColor : inactiveTextColor; const fontWeight = isTabActive ? 'bold' : 'normal'; const viewStyle = isTabActive ? [styles.tab, { borderBottomWidth: Constant.sizeDividerLarge, borderColor: Constant.colorPrimary }] : styles.tab; if (Platform.OS !== 'ios') { return <TouchableNativeFeedback delayPressIn={0} background={TouchableNativeFeedback.SelectableBackground()} key={name + page} accessible={true} accessibilityLabel={name} accessibilityTraits='button' onPress={() => onPressHandler(page)} > <View style={viewStyle}> <Text style={[{ color: textColor, fontWeight, }, textStyle,]}> {name} </Text> </View> </TouchableNativeFeedback> } return <TouchableOpacity key={name + page} accessible={true} accessibilityLabel={name} accessibilityTraits='button' onPress={() => onPressHandler(page)} > <View style={viewStyle}> <Text style={[{ color: textColor, fontWeight, }, textStyle,]}> {name} </Text> </View> </TouchableOpacity>; } render() { return ( <View style={{ flexDirection: 'row', borderBottomWidth: Constant.sizeDividerNormal, borderColor: Constant.colorDivider }}> {this.props.tabs.map((name, page) => { const isTabActive = this.props.activeTab === page; const renderTab = this.props.renderTab || this.renderTab; return this.renderTab(name, page, isTabActive, this.props.goToPage); })} </View> ); } } const styles = StyleSheet.create({ tab: { alignItems: 'center', justifyContent: 'center', paddingBottom: 10, marginLeft: 10, }, tabs: { height: 50, flexDirection: 'row', justifyContent: 'space-around', borderWidth: 1, borderTopWidth: 0, borderLeftWidth: 0, borderRightWidth: 0, borderColor: '#ccc', }, });

npm react-native-scrollable-tab-view 元件

import React, { Component } from 'react';
import {
    StyleSheet,
    View,
    ScrollView,
    Dimensions,
    TouchableOpacity,
    InteractionManager,
    Platform,
    UIManager,
    Text
} from 'react-native';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import SelectCityTabBar from './SelectCityTabBar'
import AREA_JSON from '../../util/area.json';
const { height, width } = Dimensions.get('window');

export default class AddressSelect extends Component {

    static defaultProps = {
        commitFun: function (value) {
            console.log(value);
        },
        dissmissFun: function () {

        },
        lastAddress: null,
    };

    constructor(props) {
        super(props);
        if (Platform.OS === 'android') {
            UIManager.setLayoutAnimationEnabledExperimental(true)
        }
        const { lastAddress } = props;
        let selectAddress = this.initAddress(lastAddress);
        this.state = {
            selectAddress
        }
    }

    initAddress(lastAddress) {
        let selectAddress = [
            {
                value: null,
                label: null,
                children: AREA_JSON,
            }, {
                value: null,
                label: null,
                children: null,
            }, {
                value: null,
                label: null,
                children: null,
            }];
        let array = null;

        function fun(array, value) {
            for (let item of array) {
                if (item.value + '' === value + '') {
                    return item;
                }
            }
        }
        try {
            selectAddress = selectAddress.map((item, index) => {
                let result = fun(array ? array : AREA_JSON, lastAddress[index].value);
                if (result.children) {
                    array = result.children;
                }
                return result;
            });
        } catch (e) {
            console.log('-----e-', e);
        }
        return selectAddress
    }


    /**
     * 列表行
     * @param item
     * @param i
     * @returns {XML}
     */
    renderListItem(item, i) {
        let itemStyle = styles.itemStyle;
        let textStyle = styles.itemText;
        let { selectAddress } = this.state;
        if (item.label === selectAddress[i].label) {
            itemStyle = [itemStyle];
            textStyle = [textStyle, { color: 'red' }]
        }
        return (
            <TouchableOpacity
                style={itemStyle}
                key={i + item.label}
                onPress={() => {
                    this.pressItem(item, i)
                }}
            >
                <Text style={textStyle}>{item.label}</Text>
            </TouchableOpacity>
        )
    }

    /**
     * 點選列表事件
     * @param item 選中資料
     * @param i 選中行數
     */
    pressItem(item, i) {
        let { selectAddress } = this.state;
        const initObj = {
            value: null,
            label: null,
            children: null,
        }
        let tempIndex = 0;
        if (i === 0) {
            selectAddress[0] = item;
            selectAddress[1] = initObj;
            selectAddress[2] = initObj;
            tempIndex = 1
        } else if (i === 1) {
            selectAddress[1] = item;
            selectAddress[2] = initObj;
            tempIndex = 2
        } else {
            selectAddress[2].value = item.value;
            selectAddress[2].label = item.label;
            tempIndex = 2
            let address = [
                {
                    label: selectAddress[0].label,
                    value: selectAddress[0].value
                },
                {
                    label: selectAddress[1].label,
                    value: selectAddress[1].value
                },
                {
                    label: selectAddress[2].label,
                    value: selectAddress[2].value
                }
            ]
            this.props.commitFun && this.props.commitFun(address);
            this.props.dissmissFun && this.props.dissmissFun();
            return null;

        }
        this.setState({ selectAddress });
        InteractionManager.runAfterInteractions(() => {
            this.tabView.goToPage(tempIndex)
        })

    }

    render() {
        const { selectAddress } = this.state;
        return (
            <View style={styles.container}>
                <View style={{ width: width, height: 40, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }}>
                    <Text>所在地區</Text>
                </View>
                <ScrollableTabView
                    ref={(tabView) => {
                        this.tabView = tabView;
                    }}
                    renderTabBar={() => <SelectCityTabBar />}
                >
                    {selectAddress.map((obj, i) => {
                        let array = (i === 0) ? AREA_JSON : selectAddress[i - 1].children;
                        if (array) {
                            return (
                                <ScrollView
                                    key={i}
                                    tabLabel={obj.label || '請選擇'}
                                    style={styles.scrollStyleList}
                                >
                                    {array && array.map((obj2, j) => {
                                        return this.renderListItem(obj2, i)
                                    })}
                                </ScrollView>
                            )
                        }
                    })}
                </ScrollableTabView>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        height: height * 0.6,
        backgroundColor: '#F5FCFF',
    },
    scrollStyleList: {
        width: width,
        marginBottom: Constant.sizeMarginDefault,
        marginTop: Constant.sizeMarginDefault,
    },
    itemStyle: {
        marginTop: 5,
        width: width,
        height: 35,
        marginLeft: Constant.sizeMarginDefault,
        justifyContent: 'center'
    },
    itemText: {
        fontSize: 15,
        color: '#333333'
    },

使用方法:

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

import {ReactNavComponent, Widget} from 'rn-yunxi';
import AddressSelect from '../../app-widget/address-select/index'

export default class extends React.Component {

    render() {
        return (
            <TouchableOpacity style={{flex:1, justifyContent:'center', alignItems:'center'}} onPress={() => this.openAddressSelect()}>
                <Text >地址選擇</Text>
            </TouchableOpacity>
        );

    }

    openAddressSelect() {

        Widget.Popup.show( // 這邊使用自己封裝的modal巢狀地址選擇器
            <AddressSelect
                commitFun={(area) => this.onSelectArea(area)}
                dissmissFun={() => Widget.Popup.hide()}
            />,
            {
                animationType: 'slide-up', backgroundColor: '#00000000', onMaskClose: () => {
                Widget.Popup.hide()
            }
            })
    }

    onSelectArea = (area) => {
        Log(area)
    }
};

資料型別格式

[
    {
        "value": "110000000000",
        "children": [
            {
                "value": "110100000000",
                "children": [
                    {
                        "value": "110101000000",
                        "label": "東城區"
                    },
                    {
                        "value": "110102000000",
                        "label": "西城區"
                    },
                    {
                        "value": "110105000000",
                        "label": "朝陽區"
                    },
                    {
                        "value": "110106000000",
                        "label": "豐臺區"
                    },
                    {
                        "value": "110107000000",
                        "label": "石景山區"
                    },
                    {
                        "value": "110108000000",
                        "label": "海淀區"
                    },
                    {
                        "value": "110109000000",
                        "label": "門頭溝區"
                    },
                    {
                        "value": "110111000000",
                        "label": "房山區"
                    },
                    {
                        "value": "110112000000",
                        "label": "通州區"
                    },
                    {
                        "value": "110113000000",
                        "label": "順義區"
                    },
                    {
                        "value": "110114000000",
                        "label": "昌平區"
                    },
                    {
                        "value": "110115000000",
                        "label": "大興區"
                    },
                    {
                        "value": "110116000000",
                        "label": "懷柔區"
                    },
                    {
                        "value": "110117000000",
                        "label": "平谷區"
                    },
                    {
                        "value": "110118000000",
                        "label": "密雲區"
                    },
                    {
                        "value": "110119000000",
                        "label": "延慶區"
                    }
                ],
                "label": "北京市"
            }
        ],
        "label": "北京市"
    }
]

相關推薦

React Native 省市區地址選擇仿京東

產品經理:“你明白吧,這裡向右劃可以出選單,然後需要一個閃爍的動畫,還有,我想這個tab可以拉下來,你懂吧? 設計師:“別廢話,把你要抄的產品給我看下。” … 接下來,我們仿一下別人家的地址挑選器 省市區資料格式的json檔案 import Re

js實現移動端省市區三級聯動選擇附原始碼

效果圖:  核心程式碼: <script> var nameEl = document.getElementById('sel_city'); var first = []; /* 省,直轄市 */ var second = []

聯級選擇仿element-ui,不過我用的是jq寫的!

在做元件之前,一般我都是把HTML結構先寫出來的,最終我們需要變成這樣的結構    <div class="cascader-menus"> <ul class="menus"> <li>文字<

Citypicker省市區地址選擇3.0.0版本釋出,重大更新!!!

CityPicker 城市選擇器 說明 本次更新為3.0.0版本,重大更新,強烈建議升級為最新版本,該版本徹底解決載入慢的問題,採用預先載入本地城市資料的方法。同時支援自定義省市區item佈局的屬性,更開放的使用方式,完全符合你自身的需要。還不趕緊升級使

CSS選擇之偽類選擇偽元素

寫法 cor outline p標簽 而不是 edit 實現 after tab selection [CSS4]應用於文檔中被用戶高亮的部分(比如使用鼠標或其他選擇設備選中的部分)。(IE8及以下不支持)(火狐-moz-selection)

css-css的基本選擇三種

  ** 要對哪個標籤裡面的資料進行操作   (1)標籤選擇器 div { background-color:red; color:blue; }   (2)class選擇器     * 每個HTML標籤中都有一個屬性 class <div class="h

CCF認證 2018-09-3 元素選擇50分模擬+dfs

水了一個50分再說。 CCF認證 2018-09-3 元素選擇器 題意:給你html的一些結構,讓你找出給定標籤元素的個數以及位置。 思路:看資料範圍可以看出,可以水一個50分,有50個測試點只需要簡單記錄標籤和後代,然後順序找一邊就可以拿到50,但是要全拿的話,後面的處理

> 子元素選擇Child selector

如果您不希望選擇任意的後代元素,而是希望縮小範圍,只選擇某個元素的子元素,請使用子元素選擇器(Child selector)。 例如,如果您希望選擇只作為 <div>元素子元素的 strong 元素,可以這樣寫: div > strong {color

jquery not選擇多條件

$(".basicList input").not(".stuid, .stuname").removeAttr("checked"); 如以上為將複選框中類不名為stuid和stuname的取消選擇狀態

js:選擇常用總結

<ul><li id="foo">foo</li> <li id="bar">bar</li> <li id="baz">baz</li> </ul> $('li').index

CSS一個元素同時使用多個類選擇class selector

一個元素同時使用多個類選擇器 CSS中類選擇器用點號表示。實際專案中一個div元素為了能被多個樣式表匹配到(樣式複用),通常div的class中由好幾段組成,如<div class="user login">能被.user和.login兩個選擇器選中。如果這兩個

3選擇元素——4css選擇CSS selectors

The jQuery library supports nearly all of the selectors included in CSS specifications 1 through 3, as outlined on the World Wide Web Con

java 日期選擇帶時間

import java.awt.BorderLayout; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FlowLayo

jQuery中選擇包含例項

因為我查了一下,發現網上別人總結的確實也都不錯了,所以我下面主要是對選擇器的使用(其實主要還是為了督促自己多練習使用啦)jQuery中的選擇器,主要也就分為:基本選擇器、屬性選擇器、內容選擇器、過濾選擇器、子元素選擇器、表單元素選擇器等基本選擇器,也是我們用的最多的,我就不再

React Native入門學習筆記三JSX語法

demo1 javascript/babel 很簡單,react的jsx語法 與js不同,引用的script標籤要這樣寫: <script type="text/babel"></script> <!DOCTY

React Native 之搭建開發環境MacOS使用者

必需軟體 Homebrew Homebrew, Mac系統的包管理器,用於安裝NodeJS和一些其他必需的工具軟體。 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/

Android 圖片選擇第二種

 ImageConfig imageConfig         = new ImageConfig.Builder(new GlideLoader())         .steepToolBarColor(getResources().getColor(R.color.blue))         .ti

使用pickerview實現省市區地址選擇的三級聯動

此三級聯動的實現基於pickerview,附上github地址:Android-PickerView 這是一款仿iOS的PickerView控制元件,有時間選擇和選項選擇,並支援一二三級聯動,支援自定義樣式。 首先下載pickerview,將其作為Module新增進你的

Android 地址選擇,實現省市區三級聯動

最近專案裡面用到了一個地址選擇器,實現現在主流的WheelView滑動選擇,整理了下,做了個Demo.廢話不多說,直接上程式碼: 主佈局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xml

Android:仿QQ照片選擇按相簿分類顯示,多選新增

本例的目的是實現類似於QQ的照片選擇功能。選擇照片之後,使用類似於新浪微博 發微博 頁面進行展示。 先上效果圖:        本例中使用的主要技術: 1.使用ContentProvider讀取SD卡所有圖片資訊。 2.對1中獲取的圖片,以圖片所屬的父資料夾進