react native帶索引的城市列表組件的執行個體代碼,reactnative

來源:互聯網
上載者:User

react native帶索引的城市列表組件的執行個體代碼,reactnative

城市列表選擇是很多app共有的功能,比如典型的美圖app。那麼對於React Native怎麼實現呢?

要實現上面的效果,首先需要對介面的組成簡單分析,介面的資料主要由當前城市,曆史訪問城市和熱門城市組成,所以我們在提供Json資料的時候就需要將資料分為至少3部分。

const ALL_CITY_LIST = DATA_JSON.allCityList;const HOT_CITY_LIST = DATA_JSON.hotCityList;const LAST_VISIT_CITY_LIST = DATA_JSON.lastVisitCityList;

而要實現字母索引功能,我們需要自訂一個控制項,實現和資料的綁定關係,自訂群組件代碼如下:

CityIndexListView.js

'use strict';import React, {Component} from 'react';import {  StyleSheet,  View,  Text,  TouchableOpacity,  ListView,  Dimensions,} from 'react-native';import Toast, {DURATION} from './ToastUtil'const SECTIONHEIGHT = 30;const ROWHEIGHT = 40;const ROWHEIGHT_BOX = 40;var totalheight = []; //每個字母對應的城市和字母的總高度const {width, height} = Dimensions.get('window');var that;const key_now = '當前';const key_last_visit = '最近';const key_hot = '熱門';export default class CityIndexListView extends Component {  constructor(props) {    super(props);    var getSectionData = (dataBlob, sectionID) => {      return sectionID;    };    var getRowData = (dataBlob, sectionID, rowID) => {      return dataBlob[sectionID][rowID];    };    let ALL_CITY_LIST = this.props.allCityList;    let CURRENT_CITY_LIST = this.props.nowCityList;    let LAST_VISIT_CITY_LIST = this.props.lastVisitCityList;    let HOT_CITY_LIST = this.props.hotCityList;    let letterList = this._getSortLetters(ALL_CITY_LIST);    let dataBlob = {};    dataBlob[key_now] = CURRENT_CITY_LIST;    dataBlob[key_last_visit] = LAST_VISIT_CITY_LIST;    dataBlob[key_hot] = HOT_CITY_LIST;    ALL_CITY_LIST.map(cityJson => {      let key = cityJson.sortLetters.toUpperCase();      if (dataBlob[key]) {        let subList = dataBlob[key];        subList.push(cityJson);      } else {        let subList = [];        subList.push(cityJson);        dataBlob[key] = subList;      }    });    let sectionIDs = Object.keys(dataBlob);    let rowIDs = sectionIDs.map(sectionID => {      let thisRow = [];      let count = dataBlob[sectionID].length;      for (let ii = 0; ii < count; ii++) {        thisRow.push(ii);      }      let eachheight = SECTIONHEIGHT + ROWHEIGHT * thisRow.length;      if (sectionID === key_hot || sectionID === key_now || sectionID === key_last_visit) {        let rowNum = (thisRow.length % 3 === 0)          ? (thisRow.length / 3)          : parseInt(thisRow.length / 3) + 1;        console.log('sectionIDs===>' + sectionIDs + ", rowNum=====>" + rowNum);        eachheight = SECTIONHEIGHT + ROWHEIGHT_BOX * rowNum;      }      totalheight.push(eachheight);      return thisRow;    });    let ds = new ListView.DataSource({      getRowData: getRowData,      getSectionHeaderData: getSectionData,      rowHasChanged: (row1, row2) => row1 !== row2,      sectionHeaderHasChanged: (s1, s2) => s1 !== s2    });    this.state = {      dataSource: ds.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs),      letters: sectionIDs    };    that = this;  }  _getSortLetters(dataList) {    let list = [];    for (let j = 0; j < dataList.length; j++) {      let sortLetters = dataList[j].sortLetters.toUpperCase();      let exist = false;      for (let xx = 0; xx < list.length; xx++) {        if (list[xx] === sortLetters) {          exist = true;        }        if (exist) {          break;        }      }      if (!exist) {        list.push(sortLetters);      }    }    return list;  }  _cityNameClick(cityJson) {    // alert('選擇了城市====》' + cityJson.id + '#####' + cityJson.name);    this.props.onSelectCity(cityJson);  }  _scrollTo(index, letter) {    this.refs.toast.close();    let position = 0;    for (let i = 0; i < index; i++) {      position += totalheight[i]    }    this._listView.scrollTo({y: position});    this.refs.toast.show(letter, DURATION.LENGTH_SHORT);  }  _renderRightLetters(letter, index) {    return (      <TouchableOpacity key={'letter_idx_' + index} activeOpacity={0.6} onPress={() => {        this._scrollTo(index, letter)      }}>        <View style={styles.letter}>          <Text style={styles.letterText}>{letter}</Text>        </View>      </TouchableOpacity>    );  }  _renderListBox(cityJson, rowId) {    return (      <TouchableOpacity key={'list_item_' + cityJson.id} style={styles.rowViewBox} onPress={() => {        that._cityNameClick(cityJson)      }}>        <View style={styles.rowdataBox}>          <Text style={styles.rowDataTextBox}>{cityJson.name}</Text>        </View>      </TouchableOpacity>    );  }  _renderListRow(cityJson, rowId) {    console.log('rowId===>' + rowId + ", cityJson====>" + JSON.stringify(cityJson));    if (rowId === key_now || rowId === key_hot || rowId === key_last_visit) {      return that._renderListBox(cityJson, rowId);    }    return (      <TouchableOpacity key={'list_item_' + cityJson.id} style={styles.rowView} onPress={() => {        that._cityNameClick(cityJson)      }}>        <View style={styles.rowdata}>          <Text style={styles.rowdatatext}>{cityJson.name}</Text>        </View>      </TouchableOpacity>    )  }  _renderListSectionHeader(sectionData, sectionID) {    return (      <View style={styles.sectionView}>        <Text style={styles.sectionText}>          {sectionData}        </Text>      </View>    );  }  render() {    return (      <View style={styles.container}>        <View style={styles.listContainner}>          <ListView ref={listView => this._listView = listView}               contentContainerStyle={styles.contentContainer} dataSource={this.state.dataSource}               renderRow={this._renderListRow} renderSectionHeader={this._renderListSectionHeader}               enableEmptySections={true} initialListSize={500}/>          <View style={styles.letters}>            {this.state.letters.map((letter, index) => this._renderRightLetters(letter, index))}          </View>        </View>        <Toast ref="toast" position='top' positionValue={200} fadeInDuration={750} fadeOutDuration={1000}            opacity={0.8}/>      </View>    )  }}const styles = StyleSheet.create({  container: {    // paddingTop: 50,    flex: 1,    flexDirection: 'column',    backgroundColor: '#F4F4F4',  },  listContainner: {    height: Dimensions.get('window').height,    marginBottom: 10  },  contentContainer: {    flexDirection: 'row',    width: width,    backgroundColor: 'white',    justifyContent: 'flex-start',    flexWrap: 'wrap'  },  letters: {    position: 'absolute',    height: height,    top: 0,    bottom: 0,    right: 10,    backgroundColor: 'transparent',    // justifyContent: 'flex-start',    // alignItems: 'flex-start'    alignItems: 'center',    justifyContent: 'center'  },  letter: {    height: height * 4 / 100,    width: width * 4 / 50,    justifyContent: 'center',    alignItems: 'center'  },  letterText: {    textAlign: 'center',    fontSize: height * 1.1 / 50,    color: '#e75404'  },  sectionView: {    paddingTop: 5,    paddingBottom: 5,    height: 30,    paddingLeft: 10,    width: width,    backgroundColor: '#F4F4F4'  },  sectionText: {    color: '#e75404',    fontWeight: 'bold'  },  rowView: {    height: ROWHEIGHT,    paddingLeft: 10,    paddingRight: 10,    borderBottomColor: '#F4F4F4',    borderBottomWidth: 0.5  },  rowdata: {    paddingTop: 10,    paddingBottom: 2  },  rowdatatext: {    color: 'gray',    width: width  },  rowViewBox: {    height: ROWHEIGHT_BOX,    width: (width - 30) / 3,    flexDirection: 'row',    backgroundColor: '#ffffff'  },  rowdataBox: {    borderWidth: 1,    borderColor: '#DBDBDB',    marginTop: 5,    marginBottom: 5,    paddingBottom: 2,    marginLeft: 10,    marginRight: 10,    flex: 1,    justifyContent: 'center',    alignItems: 'center'  },  rowDataTextBox: {    marginTop: 5,    flex: 1,    height: 20  }}); 

然後在頭部還需要實現一個搜尋方塊。

SearchBox.js

'use strict';import React, {Component} from 'react';import {  View,  TextInput,  StyleSheet,  Platform,} from 'react-native';export default class SearchBox extends Component {  constructor(props) {    super(props);    this.state = {      value: ''    };  }  onEndEditingKeyword(vv) {    console.log(vv);  }  onChanegeTextKeyword(vv) {    console.log('onChanegeTextKeyword', vv);    this.setState({value: vv});    this.props.onChanegeTextKeyword(vv);  }  render() {    return (      <View style={styles.container}>        <View style={styles.inputBox}>          <View style={styles.inputIcon}>          </View>          <TextInput ref="keyword" autoCapitalize="none" value={this.props.keyword}                onChangeText={this.onChanegeTextKeyword.bind(this)} returnKeyType="search" maxLength={20}                style={styles.inputText} underlineColorAndroid="transparent"                placeholder={'輸入城市名或拼音查詢'}/>        </View>      </View>    )  }}const styles = StyleSheet.create({  container: {    marginTop: 5,    marginBottom: 5,    backgroundColor: '#ffffff',    flexDirection: 'row',    height: Platform.OS === 'ios'      ? 35      : 45,    borderBottomWidth: StyleSheet.hairlineWidth,    borderBottomColor: '#cdcdcd',    paddingBottom: 5  },  inputBox: {    height: Platform.OS === 'ios'      ? 30      : 40,    marginLeft: 5,    marginRight: 5,    flex: 1,    flexDirection: 'row',    backgroundColor: '#E6E7E8'  },  inputIcon: {    margin: Platform.OS === 'ios'      ? 5      : 10  },  inputText: {    alignSelf: 'flex-end',    marginTop: Platform.OS === 'ios'      ? 0      : 0,    flex: 1,    height: Platform.OS === 'ios'      ? 30      : 40,    marginLeft: 2,    marginRight: 5,    fontSize: 12,    lineHeight: 30,    textAlignVertical: 'bottom',    textDecorationLine: 'none'  }});

最終效果:

 

 

最後是介面的繪製,這裡就不多說了,大家可以下載源碼自行查看。源碼地址:react-native-city_jb51.rar

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援幫客之家。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.