博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React-native键盘遮挡输入框问题的解决
阅读量:4086 次
发布时间:2019-05-25

本文共 5367 字,大约阅读时间需要 17 分钟。

  现在有一个更准确一点的做法是用一个View包裹住TextInput,然后通过该View的onLayout方法获取该输入框的y轴位置,再减去一个适当的高度去处理scrollview的滚动,如下所示:

this.setState({downloadUrl:text})} />
然后实现_downloadLayout方法: _downloadLayout(e){
this.setState({
downloadY:e.nativeEvent.layout.y, }); } 之后再实现TextInput的onFocus方法,对包裹的整个scrollview页面进行滚动:
_downLoadFocus(){
let scroller = this.refs.scroller; iOS&& setTimeout(()=>{
let y = this.state.downloadY - 1/3*Dev_height;//Dev_height为屏幕的高度 scroller&&scroller.scrollTo({x:0, y:y, animated:true}); },50); }
这样的处理适合大多数的情况。 评论里有小伙伴说React.findNodeHandle已经不可以使用了,应该是使用了rn更新的版本,所以我们在使用的时也需要根据版本的不同去选择合适的方法, 感谢他的提醒,新版本可以使用下面这个方法 import ReactNative from 'react-native'; ... ReactNative.findNodeHandle(...)

     

 

RN中要解决键盘遮挡输入框的问题其实有挺多方式,在这里只是记录其中的一些个人实际开发中使用到的。

     方式一、使用scrollTo方法,这也是最简单最粗暴的,只是需要计算scrollview滚动的距离,并且处理一些体验的bug问题。大致思路是:组件render方法中使用scrollview,并且设置scrollview的keyboardShouldPersistTaps={true}(此步一定不能少,如果缺少该属性,接下来的一步将会不起作用),然后在scrollview中用一个view作为container包裹所有剩余的子视图,比如Text,TouchableHighlight之类的,并且用onStartShouldSetResponderCapture截取该view的事件,用以解决当点击页面上的按钮时,第一次点击只会收起键盘,第二次点击才会响应按钮方法的bug。然后在TextInput的onFocus方法中滚动scrollview,在onEndEditing中恢复scrollview的滚动。以下是在具体实现中的代码。

render方法的实现:

render:function() {

  return(
    <View style={styles.container}>
    <NavigationBar title={'绑定手机号'} onBackPress={this.onBackPress}/>
    <ScrollView ref='scroll' keyboardShouldPersistTaps={true} >
      <View style={styles.content} onStartShouldSetResponderCapture={(e) => {


        const target = e.nativeEvent.target;
        if (target !== React.findNodeHandle(this.refs.phoneInput) && target !== React.findNodeHandle(this.refs.codeInput)) {

          this.refs.phoneInput.blur();
          this.refs.codeInput.blur();
        }}}>

        <TextInput
          style = {styles.cardNumText}
          ref = 'phoneInput'
          onFocus={this.scrollViewTo.bind(this)}
          onEndEditing={()=>{this.refs.scroll.scrollTo(0)}}
          onChange = {this.cardNumberTextChanged.bind(this)}
          placeholder = '请输入预留手机号'
          placeholderTextColor = '#481A5C'
          keyboardType = 'numeric'
        />

        <View style = {styles.lineView}></View>

          <TouchableHighlight style = {styles.topButton} underlayColor='#9B9B9B' onPress = {this.jumpToNextPage.bind(this)}>
            <Text style = {styles.buttonText}>发送验证码</Text>
          </TouchableHighlight>
        <TextInput
          style = {styles.cardNumText}
          ref = 'codeInput'
          onFocus={this.scrollViewTo.bind(this)}
          onEndEditing={()=>{this.refs.scroll.scrollTo(0)}}
          placeholder = '输入验证码'
          placeholderTextColor = '#999'
          onChange = {this.cardNumberTextChanged}
          keyboardType = 'number-pad'
        />
        <View style = {styles.lineView}></View>

        <Text style = {styles.protectText}>
           XXXXXXXXXXXXXXXXXXX
        </Text>

        <TouchableHighlight style = {styles.downButton} underlayColor='#481A5C' onPress = {this.jumpToNextPage.bind(this)}>
          <Text style = {styles.buttonText}>下一步</Text>
        </TouchableHighlight>
      </View>
    </ScrollView>
  </View>);
}

  onFocus时调用的scrollViewTo方法的实现:

  scrollViewTo:function(e){


    let target = e.nativeEvent.target;
    let scrollLength = 100;
    if (target=== React.findNodeHandle(this.refs.codeInput)) {

      scrollLength = 160;
    }
    this.refs.scroll.scrollTo(scrollLength);
  },

 

  方式二、使用View包裹时,通过设置View的marginTop属性并且结合动画来实现:初始化一个state对象的值viewMarginTop用于设置Animated.View的marginTop,在textInput的onfocus时改变viewMarginTop的值,在onEndediting时恢复或者设置新的marginTop。具体为首先引入Animated,并且初始化state方法。(state内值的变化会触发界面上相关元素的再次熏染,具有reactivecocoa的相同的作用)

  getInitialState: function () {


    return {

      viewMarginTop: new Animated.Value(0),
    };
  },

在需要上升的视图中使用Animated.View,设置其mairginTop为viewMarginTop

  <Animated.View style={

{marginTop:this.state.viewMarginTop}}>

    //当然不建议将样式写在这里,这样会导致每次熏染都创建一次样式,你应该将样式定义到StyleSheet中

    //your Views and component

  </Animated.View>

然后在onFucos的方法中用动画改变viewMarginTop的值,如下

  Animated.timing(
    this.state.viewMarginTop,
    {


      toValue: 160,
      duration: 250,
    }
  ).start();

要恢复只需要在onEndediting中用同样的原理恢复viewMarginTop的值即可.

 

方式三、通过监听scrollview上键盘的出现和消失,在出现和消失方法中设置某个state值的变化,来设置scrollview的contentInset,该方法只是在github上看过,具体本人并没有用过即:

 

1.在页面熏染完时添加监听

componentDidMount: function () {


  // Keyboard events监听
  DeviceEventEmitter.addListener('keyboardWillShow', this.updateKeyboardSpace)
  DeviceEventEmitter.addListener('keyboardWillHide', this.resetKeyboardSpace)
},

componentWillUnmount: function () {


  // TODO: figure out if removeAllListeners is the right thing to do
  DeviceEventEmitter.removeAllListeners('keyboardWillShow')
  DeviceEventEmitter.removeAllListeners('keyboardWillHide')
},

 

getInitialState: function (props) {//初始化变量
  this.viewIsInsideTabBar = false
  return {


    keyboardSpace: 0,
  }
},

// Keyboard actions
updateKeyboardSpace: function (frames) {


  const keyboardSpace =  frames.endCoordinates.height//获取键盘高度
  this.setState({

    keyboardSpace: keyboardSpace,
  })
},

resetKeyboardSpace: function () {


  this.setState({

    keyboardSpace: 0,
  })
},

//设置scrollview的contentInset

<ScrollView
  ref='keyboardView'
  keyboardDismissMode='interactive'
  contentInset={

{bottom: this.state.keyboardSpace}}
  showsVerticalScrollIndicator={true}
</ScrollView>

转载地址:http://ckeni.baihongyu.com/

你可能感兴趣的文章
FMDB的使用
查看>>
UIImage存为本地文件与UIImage转换为NSData
查看>>
[转]打印质数的各种算法
查看>>
[转]javascript with延伸的作用域是只读的吗?
查看>>
php的autoload与global
查看>>
IE不支持option的display:none属性
查看>>
[分享]mysql内置用于字符串型ip地址和整数型ip地址转换函数
查看>>
TableDnd(JQuery表格拖拽控件)应用进阶
查看>>
[转]开源中最好的Web开发的资源
查看>>
java接口不能实例化原因浅谈
查看>>
Https加密及攻防
查看>>
Java生成随机不重复推广码邀请码
查看>>
Java8 Lambda表达式介绍
查看>>
【JAVA数据结构】双向链表
查看>>
【JAVA数据结构】先进先出队列
查看>>
String类的intern方法随笔
查看>>
【泛型】一个简易的对象间转换的工具类(DO转VO)
查看>>
1.随机函数,计算机运行的基石
查看>>
MouseEvent的e.stageX是Number型,可见as3作者的考虑
查看>>
在mc中直接加aswing组件,该组件还需最后用validate()方法
查看>>