当前位置:

React Native 小记 - TouchableOpacity 单次点击无效

访客 2024-04-23 1395 0

一般是焦点问题,解决方法:即在ScrollView标签内,根据情况设置其keyboardShouldPersistTaps属性值为always或者handled。详细解决过程如下:

0x00描述

收到测试人员提交的Bug:帐号密码输入完毕按返回键关闭键盘后,点击登录没反应,再点一次才执行登录操作。网上类似的情况还有“当点击TouchableOpacity时,要点击两下才会触发onPress()”、“在ScrollView中TouchableOpacity需要在TextInput失去焦点后才能点击”等。

0x01问题查找

作为一个Android开发者,看到情况描述,联想到是焦点问题。类似于Android原生开发的『ListView的Item中包含EditTextButton时:EditText与Button如何获取焦点、无法点击、ListView不能滑动等』。

由于我遇到的是ScrollView使用时出现的问题,查看下scrollview的官方文档发现有个keyboardShouldPersistTaps的属性,用于处理此类情况。

此外,在stackoverflow上也搜索到相关的回答,说是ListView也有此属性,但我本地react-native-0.57.2ListView源码中并没有此属性。

0x02解决方案

再次看文档:(官方文档|中文文档)

scrollview@keyboardShouldPersistTaps

如果当前界面有软键盘,那么点击ScrollView后是否收起键盘,取决于本属性的设置。

  • 'never'(默认值),点击TextInput以外的子组件会使当前的软键盘收起。此时子元素不会收到点击事件。
  • 'always',键盘不会自动收起,ScrollView也不会捕捉点击事件,但子组件可以捕获。
  • 'handled',当点击事件被子组件捕获时,键盘不会自动收起。这样切换TextInput时键盘可以保持状态。多数带有TextInput的情况下你应该选择此项。
  • false,已过时,请使用'never'代替。
  • true,已过时,请使用'always'代替。

经测试,使用always或者handled均可解决发生的问题,由于我这里是ScrollView内部存在多个TextInput,故选择handled值。

示例代码:

<ScrollViewstyle={styles.mScrollView}keyboardShouldPersistTaps={'handled'}><Viewstyle={styles.root}><Viewstyle={styles.userRoot}><Textstyle={styles.userRootV1}>用户名:</Text><Viewstyle={{flex:1,borderBottomColor:'#f0f0f0',borderBottomWidth:1}}><LessBorderTextInputstyle={styles.userRootV2}multiline={false}placeholder={'请输入用户名'}placeholderTextColor={'#ccc'}autoFocus={false}onChangeText={(newText)=>this.updateUser(newText)}returnKeyType={'next'}onSubmitEditing={()=>{this._input.focus();}}/></View></View><Viewstyle={styles.userPwdRoot}><Textstyle={styles.userPwdRootV1}>密码:</Text><Viewstyle={{flexDirection:'row',flex:1,borderBottomColor:'#f0f0f0',borderBottomWidth:1,alignItems:'center',}}><LessBorderTextInputstyle={styles.userPwdRootV2}placeholder={'请输入密码'}multiline={false}placeholderTextColor={'#ccc'}secureTextEntry={!this.state.showPwd}onChangeText={(newText)=>this.updatePwd(newText)}returnKeyType={'done'}ref={(c)=>this._input=c}/><TouchableOpacityonPress={()=>this._showPwd(!this.state.showPwd)}><Imagesource={pwd_icon}style={styles.userPwdRootV3}/></TouchableOpacity></View></View><TouchableOpacityonPress={()=>_login()}><Textstyle={styles.userSignIn}>登录</Text></TouchableOpacity></ScrollView>

其中LessBorderTextInput是我参考官方文档封装后无边框(方便实现各种UI设计要求)的TextInput,并且增加了支持ref属性的功能,可用于多处需要填写内容时直接在键盘上点击下一项即自动进入下一项的输入。参见博客的相关文章。

0x03总结

发现问题,借助搜索工具能很快得到解决方案,我这里也特地把解决方法直接写到了文章的开头,至于如何解决问题,是给想了解原因的人准备的一个思路和说明。如果你有更好的见解,欢迎和我一起讨论。

如果有什么建议或者问题可以随时联系我,共同探讨学习:

  • Github:likfe
  • CSDN:他叫自己Mr.张
  • 掘金:cafeting
  • 微博:cafeting

发表评论

  • 评论列表
还没有人评论,快来抢沙发吧~