RN子容器超出父容器部分点击事件(android)

场景

当出现下面这种布局:绿色元素的高度是由红色元素高度撑开,红色元素又需要超出绿色元素一部分(这里是以超出100像素为例子),并且给红色元素添加了点击事件。

我们一般会把红色元素放到绿色元素里面,形成父子关系,然后对红色元素设置偏移量 top:-100(或者marginTop:-100)。

less 复制代码
  <View style={styles.greenView}>
      <TouchableWithoutFeedback onPress={onPress}> 
         <View style={styles.redView}></View>
      </TouchableWithoutFeedback>
  </View>

  greenView: {
    width: '100%',
    alignItems:'center',
    backgroundColor: 'green',
  },
  redView: {
    width: 180,
    height:300,
    backgroundColor: 'red',   
    top:-100,
    // marginTop:-100,
  },

问题

上面这种父子关系在 安卓 中会出现红色元素超出绿色元素的部分(那100像素)的点击事件是无法生效的,ios是正常的。

原因就是: 安卓对于超出父容器的子容器的view不给予事件分发

所以我们就要避免将红色元素包裹在绿色元素里面从而出现父子关系这种写法。

解决方案

下面给出2中解决方案

方案1(最佳方案)
    • 步骤1:让红色容器和绿色容器并列,避免出现子父关系。
    • 步骤2: 然后给绿色容器设置paddingTop:300(这里300是红色元素的高度),或者在绿色容器里面放置一个高度等于红色元素高度的view元素,目的就是给红色元素占位,撑开绿色元素的高度。

【注意:一定要让红色元素的层级比绿色元素高,不然红色元素显示不出来】

    • 步骤3: 然后给红色元素设置marginBottom【不建议使用bottom】等于负的自身的高度(这里是-300像素)。这样红色容器在视觉上就显示在绿色容器里面,在此基础上再给红色元素的marginBottom加上红色元素需要超出绿色元素的高度就行(这里是加100) 。

步骤1图 步骤2图 步骤3图

less 复制代码
  <TouchableWithoutFeedback onPress={onPress}> 
         <View style={styles.redView}></View>
   </TouchableWithoutFeedback>
  <View style={styles.greenView}></View>

  greenView: {
    width: '100%',
    height: 300,
    alignItems:'center',
    backgroundColor: 'green',
    paddingTop:300, // 值为红色元素的高度300
  },
  redView: {
    width: 180,
    height:300,
    backgroundColor: 'red',   
    marginBottom:-300 + 100, // 值为负的自身的高度再加上需要超出的高度
    zIndex:1, // 注意红色元素的层级要比绿色元素高,不然显示不出来
  },

为什么说不建议用bottom来设置红色元素的偏移位置,它和marginBottom都可以达到这种果。因为如果用bottom的话,会影响其它元素的布局。

我们在绿色元素的同级增加一个蓝色元素,就可以看到明显区别。设置MarginBottom的样式 往往是我们所期待的,蓝色元素紧挨着红色元素。而设置bottom会使的红色元素的起始位置的地方无法被其它元素占用。蓝色元素与红色元素之间间隔了200像素

less 复制代码
  <View style={styles.othersView}></View>  
  <TouchableWithoutFeedback onPress={onPress}> 
         <View style={styles.redView}></View>
  </TouchableWithoutFeedback>
  <View style={styles.greenView}></View>

  othersView:{
   flex:1,
   width:'100%',
   backgroundColor:'blue'
  },
  greenView: {
    width: '100%',
    height: 300,
    alignItems:'center',
    backgroundColor: 'green',
    paddingTop:300,
  },
  redView: {
    width: 180,
    height:300,
    backgroundColor: 'red',   
    zIndex:1,
    marginBottom: -300 + 100, // 左图样式
    bottom:-300 + 100,  // 右图样式
  },
方案2: (局限性)

如果你就是想设计成父子关系的话,也可以实现这种效果。但是只适合安卓端。

    • 可以给父容器设置boderTopWidth,为红色容器需要超出的部分(这里是100像素),然后把再把绿色元素的border颜色设置为透明色就行。只要子容器没有超出父容器,点击事件就是正常的。【但是这里必须要设置一下borderRadius不为0即可】

左图安卓,右图iios,都给绿色元素设置了borderTopWidth: 100,borderColor: 'transparent',

borderRadius:1。

安卓端的border默认为黑色,设置borderColor: 'transparent' 后再变成透明色。

ios端的border默认为背景颜色(绿色),设置borderColor: 'transparent'还是为背景色(绿色)

【注意:如果borderRadius没值的话,双端border的颜色都是默认为黑色,再把border设置为透明色就都是显示出背景的颜色】

安卓端图 ios端图

less 复制代码
  <View style={styles.othersView}></View>
  <View style={styles.greenView}>
       <TouchableWithoutFeedback onPress={onPress}> 
            <View style={styles.redView} ></View>
       </TouchableWithoutFeedback>
  </View>


  othersView:{
  flex:1,
  width:'100%',
  backgroundColor:'blue'
  },
  greenView: {
    width: '100%',
    alignItems:'center',
    backgroundColor: 'green',
    borderTopWidth: 100,
    borderRadius: 1, // 不为0即可
    borderColor:'transparent',
  },
  redView: {
    width: 180,
    height:300,
    backgroundColor: 'red',
    top: -100,
  },

总结

安卓端会出现子容器超出父容器部分的点击事件不生效,是因为安卓对于超出父容器的子容器的view不给予事件分发,因此在开发中,如果有类似场景需求,要避免这种父子关系的出现。上面我是以超出部分在绿色元素的上方为例子,如果红色元素要超出的部分在绿色元素的左边、右边或者下边,方法是类似的。整体思路就是让所谓的子元素(红色元素)在父元素(绿色元素)外面,变成兄弟关系,然后再想办法让子元素(红色元素)再偏移回父元素(绿色元素)里面。最后在视觉上就形成了父子关系的效果。

相关推荐
L耀早睡1 分钟前
mapreduce打包运行
大数据·前端·spark·mapreduce
咖啡の猫3 分钟前
JavaScript基础-创建对象的三种方式
开发语言·javascript·ecmascript
HouGISer15 分钟前
副业小程序YUERGS,从开发到变现
前端·小程序
outstanding木槿20 分钟前
react中安装依赖时的问题 【集合】
前端·javascript·react.js·node.js
小吕学编程1 小时前
Jackson使用详解
java·javascript·数据库·json
霸王蟹1 小时前
React中useState中更新是同步的还是异步的?
前端·javascript·笔记·学习·react.js·前端框架
霸王蟹1 小时前
React Hooks 必须在组件最顶层调用的原因解析
前端·javascript·笔记·学习·react.js
专注VB编程开发20年1 小时前
asp.net IHttpHandler 对分块传输编码的支持,IIs web服务器后端技术
服务器·前端·asp.net
爱分享的程序员2 小时前
全栈项目搭建指南:Nuxt.js + Node.js + MongoDB
前端
听吉米讲故事2 小时前
Slidev集成Chart.js:专业数据可视化演示文稿优化指南
javascript·信息可视化·数据分析