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

相关推荐
masa01019 分钟前
JavaScript--JavaScript基础
开发语言·javascript
让开,我要吃人了2 小时前
HarmonyOS开发实战(5.0)实现二楼上划进入首页效果详解
前端·华为·程序员·移动开发·harmonyos·鸿蒙·鸿蒙系统
everyStudy3 小时前
前端五种排序
前端·算法·排序算法
甜兒.4 小时前
鸿蒙小技巧
前端·华为·typescript·harmonyos
她似晚风般温柔7897 小时前
Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
开发语言·javascript·uni-app
Jiaberrr8 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy8 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
城南云小白8 小时前
web基础+http协议+httpd详细配置
前端·网络协议·http
前端小趴菜、8 小时前
Web Worker 简单使用
前端
web_learning_3218 小时前
信息收集常用指令
前端·搜索引擎