React Native学习组件之TextInput

678 查看

Demo展示


RNTextInput.gif

搜索框自动提示。此demo分为两部分,第一是我们自定义输入框,RN默认的输入框不是很美观;第二个是自动列表提示。demo比较简单,我们快速的来实现它吧。

自定义输入框

在根目录上新建一个search.js文件

import React, {Component} from 'react';
import {
    StyleSheet,
    Text,
    TextInput,
    PixelRatio,
    View
} from 'react-native';

var onePT = 1 / PixelRatio.get();

class SearchComponent extends Component {

    render() {
        return (
            <View style={styles.flex}>
                <View style={[styles.inputHeight, styles.flexDirection]}>
                    <View style={[styles.flex, styles.input]}>
                        <TextInput
                            //这里表示输入自带的下划线颜色透明
                            underlineColorAndroid={'transparent'}
                        />
                    </View>
                    <View style={styles.btn }>

                        <Text >搜索</Text>
                    </View>
                </View>

            </View>
        );
    }

}

const styles = StyleSheet.create({

    flex: {
        flex: 1
    },

    flexDirection: {
        flexDirection: 'row'
    },
    input: {
        borderWidth: 1,
        marginLeft: 5,
        paddingLeft: 5,
        borderColor: '#ccc',
        justifyContent: 'center',
        borderRadius: 4
    },
    inputHeight: {
        height: 45
    },
    btn: {
        width: 55,
        marginLeft: -5,
        marginRight: 5,
        backgroundColor: '#23beff',
        justifyContent: 'center',
        alignItems: 'center',
        borderBottomRightRadius: 4,
        borderTopRightRadius: 4
    },
    result: {

        marginLeft: 5,
        marginRight: 5,
        height: 200,
        borderColor: '#ccc',
        borderBottomWidth: 1,
        borderRightWidth: 1,
        borderLeftWidth: 1
    },
    resultItem: {
        fontSize: 16,
        paddingLeft: 10,
        paddingTop: 10,
        paddingBottom: 10,
        borderWidth: onePT,
        borderColor: '#ddd'

    },

    resultItemBottomLine: {
        borderBottomWidth: onePT,
        borderColor: '#ddd',
    }
});
module.exports = SearchComponent;

我们在index.android.js文件里面使用它

import React, {Component} from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View
} from 'react-native';

var SearchComponent = require('./search');

class RNTextInput extends Component {
    render() {
        return (
            <View style={[styles.flex, styles.topStatus]}>

                <SearchComponent/>

            </View>
        );
    }
}

const styles = StyleSheet.create({
    flex: {
        flex: 1
    },
    topStatus: {
        marginTop: 25
    }
});

AppRegistry.registerComponent('RNTextInput', () => RNTextInput);

效果如下:


serach_1.png

自动提示列表

  • TextInput常用属性

    • returnKeyType

      因为这里的使用场景是搜索,所我们虚拟键盘的返回键是search

    • placeholder

      显示在输入前的占位符,如“请输入关键字”。有点像Android中EditText中的hint提示

    • value

      通过this.state.value修改TextInput的value的变化

    • onEndEditing

      用户结束编辑时触发该事件,会将this.state.value写入。这样,就能在搜索框中显示该值

    • onChangeText

      监听输入框值的变化,onChangeText获取的值作为字符串传入

  • 代码实现

在serach.js文件添加一些代码

...

var onePT = 1 / PixelRatio.get();

class SearchComponent extends Component {

    //我们可以在构造方法中进行初始化
    constructor(props) {
        super(props);
        this.state = {
            show: false,
        };
    }

    /**
     * 显示搜索结果
     * @param result
     */
    showResult(result) {
        var result = result;
        this.setState({
            show: true,
            value: result
        });
    }

    /**
     * 隐藏搜索结果
     * @param result
     */
    hideResult(result) {
        this.setState({
            show: false,
            value: result
        });
    }    
    render() {
        return (
            <View style={styles.flex}>
                <View style={[styles.inputHeight, styles.flexDirection]}>
                    <View style={[styles.flex, styles.input]}>
                        <TextInput
                            underlineColorAndroid={'transparent'}
                            returnKeyType="search"
                            placeholder="请输入关键字"
                            onChangeText={(text)=>this.showResult(text)}
                            value={this.state.value}
                            onEndEditing={(text)=>this.hideResult({text})}
                        />
                    </View>
                    <View style={styles.btn }>

                        <Text onPress={()=>this.hideResult(this.state.value)}>搜索</Text>
                    </View>
                </View>

                { this.state.show ?
                    <View style={styles.result}>
                        <View style={[styles.resultItemBottomLine, styles.flex]}>
                            <Text style={[styles.resultItem]}
                                  numberOfLines={1}
                                  onPress={this.hideResult.bind(this, this.state.value + '超市')}>
                                {this.state.value}超市
                            </Text>
                        </View>

                        <View style={[styles.resultItemBottomLine, styles.flex]}>
                            <Text style={styles.resultItem}
                                  numberOfLines={1}
                                  onPress={this.hideResult.bind(this, this.state.value + '道路')}>
                                {this.state.value}道路
                            </Text>
                        </View>

                        <View style={[styles.resultItemBottomLine, styles.flex]}>
                            <Text style={[styles.resultItem]}
                                  numberOfLines={1}
                                  onPress={this.hideResult.bind(this, this.state.value + '综合商店')}>
                                {this.state.value}综合商店
                            </Text>
                        </View>

                        <View style={[styles.resultItemBottomLine, styles.flex]}>
                            <Text style={[styles.resultItem]}
                                  numberOfLines={1}
                                  onPress={this.hideResult.bind(this, this.state.value + '医院')}>
                                {this.state.value}医院
                            </Text>
                        </View>

                        <View style={[styles.flex]}>
                            <Text style={[styles.resultItem]}
                                  numberOfLines={1}
                                  onPress={this.hideResult.bind(this, this.state.value + '美容院')}>
                                {this.state.value}美容院
                            </Text>
                        </View>
                    </View>
                    : null
                }
            </View>
        );
    }

}

...

运行效果如下:


search_2.png

总结

我们通过判断this.state.show来确定是否显示结果列表。如果this.state.show是true,则显示。如果是false,则隐藏(null对象不显示)。

结果列表的规则是:输入关键字+预设关键字。这是我们模拟服务端传过来的数据。同时,点击结果列表中的某一项,应该隐藏列表并且将结果显示在输入框中。onPress={this.hideResult.bind(this, this.state.value + '超市')}就是当用户点击时,将字符传结果输入的到hide方法中。在js中,调用有参数的方法,我们可以使用bind方法来传参。

hide方法很简单,就是将this.state.show设置为false,这样会将结果列表隐藏起来了。因为状态的改变引起了视图的重新渲染,遇到this.state.show为false,就不渲染结果列表了。

好了,我们的TextInput组件就学习完了,若有不对之处,还请告知。谢谢!