React Native开发移动开发技术前沿React Native实践

React-native 自定义键盘

2017-09-07  本文已影响1085人  饭后的甜点_

导语:

react-native 就不多介绍了详情见链接, 前些日子公司要做有关即时通讯的项目,需要自定义一个键盘, 所以我就写了一个,小弟才学疏浅有不对的地方希望大神指点.

react 2.jpg

需求:

  我们自定义聊天键盘时需要实现的功能有:    
  1.  调用原生的键盘(React已经帮我们实现了)
  2.  键盘的表情功能(类似于某宝的发送表情)
  3.  调用相机相册选择相片 
  4.  语音功能(我司没有要求..暂且放过它)

一. 自定义键盘JS文件

import {
    StyleSheet,
    View,
    Image,
    Text,
    Platform,
    StatusBar,
    TouchableOpacity,
    FlatList,
    TextInput,
    DeviceEventEmitter,
    ScrollView,
} from 'react-native'

这些控件集我们后面会用到,大家根据自己工程的情况选择添加吧~~~~
然后就是在js的 render 方法里自定义见面

render () {
        return(
            <View style={styles.container}>
                 {this._creatListView()}
                 {this._creatBottomTool()}
            </View>
        )
}

这个方法里是写主要界面的因为这次主要写键盘所以键盘工具栏上方用一个空View去代替,大体上如下图:

342D00B6-CC5B-4ED0-AA5A-02FF32317CAA.png

this._creatListView()方法里的代码如下:

_creatListView = () =>{
        return(
                <View style={{width:414,flex:1,backgroundColor:'white'}}/>
        )
}

这个就是键盘工具栏上方的view 我的宽度是写死的,正常是屏幕宽,可自定义一个全局的宽度等于屏幕宽,这里我就不处理了.下面就是我们要自定义的键盘环节了:

_creatBottomTool = () =>{
        var lenth = this.state.isGetFocus ? 300: 40
        return(
            <View style={{width:global.width,height:lenth,marginBottom:0,backgroundColor:'#F2F2F2'}}>
                <ScrollView keyboardShouldPersistTaps="always"
                            showsVerticalScrollIndicator={false}
                            scrollEnabled={false}>
                    <View style={{flexDirection:'row',width:global.width,height:39}}>
                        <TextInput ref = "textInput"
                                   style={{marginTop:5,marginLeft:15,width:240,height:30,backgroundColor:'white',padding:0,borderRadius:5}}
                                   onFocus={this._getFocus}
                                   onBlur={this._lostFocus}
                                   onSubmitEditing={this._getTure}
                                   onChangeText={(text) =>{
                                       this.setState({
                                           inputMsg:text,
                                       })}}
                                   blurOnSubmit={true}
                                   returnKeyType={'send'}
                                   value={this.state.inputMsg}/>
                        <TouchableOpacity style={{marginLeft:15,marginTop:5}}
                                          activeOpacity={1}
                                          onPress={this._getEmoji}>
                            <Image source={require('../../Res/emoji.png')}
                                   style={{width:30,height:30}}
                                   resizeMode={'contain'}/>
                        </TouchableOpacity>
                        <TouchableOpacity style={{marginLeft:15,marginTop:5}}
                                          activeOpacity={1}
                                          onPress={this._getPhotoSetting}>
                            <Image source={require('../../Res/addmoji.png')}
                                   style={{width:30,height:30}}
                                   resizeMode={'contain'}/>
                        </TouchableOpacity>
                    </View>
                    <View style={{width:global.width,height:1,backgroundColor:'#E6E6E6'}}/>
                </ScrollView>
                {this.isshowEmojiView()}
            </View>
        )
    }

忘记写constructor了 这个是JS最开始就会调用的方法 这里的属性发生变化的时候render的界面会被重新渲染 (这个就是React的优势之一)~~~~~

constructor(props){
        super(props)
        this.state = {
            messege:[],
            isGetFocus:false,
            inputMsg:'',
            isshowEmojiView:false,
            isshowPhotoSetting:false,
            emojidata:[],
        }
}

上面的global.width是我自定义的数值,你可以自己更改,我会在textInput里包一层scrollerview是因为textInput 焦点存在的时候 你点击其他按钮是需要2遍的 因为React机制的原因,它需要让textInput先失去焦点之后你才能选中按钮,如果你在后面添加了scrollerView并把keyboardShouldPersistTaps设置为always就不会出现上述问题,

接下来就是关于textInput的几个方法了:

  _getFocus = () =>{
        this.setState({
            isGetFocus:true,
            isshowEmojiView:false,
            isshowPhotoSetting:false,
        })
    }

    _lostFocus = () =>{
        if (this.state.isshowEmojiView || this.state.isshowPhotoSetting){
            this.setState({
                isGetFocus:true,
            })
        }else {
            this.setState({
                isGetFocus:false,
            })
        }
    }
   _getTure = () =>{
        this.refs.textInput.clear()
        this.refs.textInput.isFocused(false)
        temp.push({type:'my',msg:this.state.inputMsg})
        this.setState({
            messege:temp,
            inputMsg:'',
        })
    }
    _getEmoji = () =>{
        this.setState({
            isGetFocus:true,
            isshowEmojiView:true,
            isshowPhotoSetting:false,
        })
        this.refs.textInput.blur()
    }

接下来是选择emoji和选择图片的界面:

isshowEmojiView = () =>{
        if (this.state.isshowEmojiView) {
            return(
                <View style={{height:260,width:global.width,alignItems:'center',marginLeft:0,marginTop:0}}>
                    <FlatList horizontal={false}
                              keyExtractor={this._uiniqueid}
                              numColumns={8}
                              renderItem={this._renderemojiItem}
                              data={this.state.emojidata}/>
                    <View style={{width:global.width,height:35,flexDirection:'row'}}>
                        <View style={{height:35,flex:1}}/>
                        <TouchableOpacity activeOpacity={1} style={{width:60,height:35,alignItems:'center',justifyContent:'center',borderWidth:1,borderColor:'#E6E6E6'}}>
                            <Image source={require('../../Res/deletes.png')}
                                   style={{width:30,height:30}}
                                   resizeMode={'contain'}/>
                        </TouchableOpacity>
                        <TouchableOpacity activeOpacity={1} style={{width:60,height:35,marginRight:0,alignItems:'center',justifyContent:'center',borderWidth:1,borderColor:'#E6E6E6'}}>
                            <Text style={{color:'#696969'}}>发送</Text>
                        </TouchableOpacity>
                    </View>
                </View>
            )
        }
        if (this.state.isshowPhotoSetting){
            return(
                <View style={{height:260,width:global.width,flexDirection:'row'}}>
                    <View style={{width:60,height:60,borderWidth:1,borderColor:'#E6E6E6',marginTop:20,marginLeft:20,borderRadius:5,alignItems:'center',justifyContent:'center'}}>
                        <Image style={{width:30,height:30}}
                               resizeMode={'contain'}
                               source={require('../../Res/photos.png')}/>
                    </View>
                    <View style={{width:60,height:60,borderWidth:1,borderColor:'#E6E6E6',marginTop:20,marginLeft:15,borderRadius:5,alignItems:'center',justifyContent:'center'}}>
                        <Image style={{width:30,height:30}}
                               resizeMode={'contain'}
                               source={require('../../Res/cameras.png')}/>
                    </View>
                </View>
            )
        }
    }

上面用到的图片你可以自行更改路径图片不然会报错

 _uiniqueid = (item, index) => index

_renderemojiItem = (item) =>{
        return(
            <View style={{width:30,height:30,marginTop:15,marginLeft:5,marginRight:5}}>
                <TouchableOpacity activeOpacity={1}
                                  onPress={this._clickEmoji.bind(this,item)}>
                    <Image source={(this.state.emojidata[item.index])}
                           resizeMode={'contain'}
                           style={{width:30,height:30}}/>
                </TouchableOpacity>
            </View>
        )
    }

emojidata这个state属性 是你自己添加本地图片的数组,个数是自己定义的你可以简单放几张,文中并未添加是空数组 ,上文中的图片你都要替换成自己的图片~~~!!!!

上一篇下一篇

猜你喜欢

热点阅读