PrismJS

2018年6月7日 星期四

react-native-autocomplete-input(4)關於style

前一回react-native-autocomplete-input(3)參考重構筆記的範例,可以看到還是有一點不完整的地方是在Autocomplete本身的style上面(59及100行),沒有用props傳入,組件化就不太完整,因此這篇簡單補上,完整的組件程式碼如下:




import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { 
  StyleSheet,
  Platform,
  Text,
  TextInput,
  View,
  FlatList,
  TouchableOpacity,
  ViewPropTypes as RNViewPropTypes
} from 'react-native';
const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();

const ViewPropTypes = RNViewPropTypes || View.propTypes;

export default class Autocomplete extends Component {
  _keyExtractor = (item, index) => item.content;
  static propTypes = {
    array: PropTypes.array,
    placeholder: PropTypes.string,
    keyboardShouldPersistTaps: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.bool
    ]),
    returnKeyType: PropTypes.string,
    keyboardType: PropTypes.string,
    AutocompleteStyle: ViewPropTypes.style,
    AutocompleteFontStyle: Text.propTypes.style,
  };
  static defaultProps = {
    array: [],
    placeholder: '',
    keyboardShouldPersistTaps: 'handled',
    returnKeyType: 'done',
    keyboardType: 'default',
  };
    
  constructor(props) {
    super(props);
    this.state = {
      text: '',
      flagFocus: false,
    };
  };
  /**
   *  從輸入找出陣列符合
   */
  findArray(text) {
    if (text === '') {
        return [];
    }    
    const { array } = this.props;
    const regex = new RegExp(`${text.trim()}`, 'i');
    return array.filter(array => array.content.search(regex) >= 0);
  }
  /**
   *  回傳提示框
   */
  renderItem = (item) => {
    const {
      AutocompleteFontStyle,
    } = this.props;
    return (
      <TouchableOpacity 
        activeOpacity={0} 
        style={{padding:10}} 
        onPress= {() => this.setState({ text: item.content })}
      >
        <Text style={[styles.item,AutocompleteFontStyle]}>
          {item.content}
        </Text>
      </TouchableOpacity>
    );
  };
  
  onFocus() {
    this.setState({ flagFocus: true })
  };
  
  onBlur() {
    this.setState({ flagFocus: false })
  };

  render() {
    const {
      keyboardShouldPersistTaps,
      returnKeyType,
      keyboardType,
      placeholder,
      AutocompleteStyle,
      AutocompleteFontStyle,
    } = this.props;
    const { text, flagFocus } = this.state;
    const array = this.findArray(text);
    const showResults = (array.length === 0||(array.length === 1 && comp(text, array[0].content)))?false:true;
    
    /**
     * console.log(array.length)
     */
    return (
      <View style={styles.container}>
        <TextInput 
          ref='Account'
          autoCapitalize='none'
          autoCorrect={false}
          maxLength={10}
          underlineColorAndroid='transparent'
          keyboardType={keyboardType}
          returnKeyType={returnKeyType}
          defaultValue={text}
          style={[
            AutocompleteStyle,
            AutocompleteFontStyle,
          ]}
          onFocus={() => this.onFocus()}
          onBlur={() => this.onBlur()}
          onChangeText={text => this.setState({ text: text })}
          placeholder={placeholder}
        />
        { showResults && flagFocus && 
          (<FlatList
            style={[
              styles.flatlist,
              {top:AutocompleteFontStyle,},
            ]}
            bounces={false}
            keyExtractor={this._keyExtractor}
            keyboardShouldPersistTaps={keyboardShouldPersistTaps}
            numColumns ={1}
            data={array.length === 1 && comp(text, array[0].content) ? [] : array}
            renderItem={({item}) => this.renderItem(item)}     
          />)}
      </View>
    );
  };
}

const androidStyles = {
  container: {
  },
};
const iosStyles = {
  container: {
    zIndex: 1
  },
};

const styles = StyleSheet.create({
  ...Platform.select({
    android: { ...androidStyles },
    ios: { ...iosStyles }
  }),
  flatlist: {
    flex:1,
    maxHeight:120,
    position: 'absolute',
    left: 0,
    right: 0,
    borderColor: '#b9b9b9',
    borderRadius: 1,
    borderWidth: 1,
    backgroundColor: 'white',
    borderTopWidth: 0,
    zIndex: 2,
    elevation: 20,
  },
  item: {
    textAlign:'center',
    zIndex: 2,
    elevation: 20,
  },
  
});
上述範例可以看到在28、29行的地方多了兩個props,分別為AutocompleteStyle、AutocompleteFontStyle,分成兩個的原因目前是因為如果在AutocompleteStyle裡面撰寫到fontSize的屬性,會出現Invalid props.style key `fontSize` supplied to `Autocomplete`的warning,因此查了一些資料目前是將跟Text有關的屬性額外分了一個AutocompleteFontStyle出來,或者是可以採用下列的方法:
static propTypes = {
    ...View.propTypes,
    ...TextInput.propTypes,
    array: PropTypes.array,
    placeholder: PropTypes.string,
    returnKeyType: PropTypes.string,
    keyboardType: PropTypes.string,
  };
這個方法在傳入porps時就可以直接全部寫在style這個屬性內了,最後附上原先採用AutocompleteStyle、AutocompleteFontStyle這個的呼叫範例:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
    Platform,
    StyleSheet,
    Text,
    View,
    Image,
    ImageBackground,
    PixelRatio,
    TextInput,
    TouchableOpacity,
    AlertIOS,
    ScrollView,
} from 'react-native';
import Autocomplete from './Autocomplete'

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
    };
  }
  render() {
    return (
      <View  style={styles.container}>
        <Autocomplete 
          ref='Account'
          placeholder = {'test'}
          AutocompleteFontStyle = {{fontSize: 18}}
          AutocompleteStyle = {[
            styles.textinput,
          ]}        
          array= {[
            {content:'001'},
            {content:'002'},
          ]}
/>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  textinput: {
    flex:1,
    padding:0,
    marginTop: 10,
    minWidth:180,
    maxWidth:280,
  },
});

沒有留言:

張貼留言