8

RN TouchableOpacity点击事件不响应原因详解

 2 years ago
source link: https://segmentfault.com/a/1190000041145661
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

首先是整个页面布局如上:

在实际开发中发现 如下红框中的所有区域点击事件均没有效果,不会触发

RN基本触摸组件尝试

TouchableHighlight、TouchableNativeFeedback、 TouchableOpacity 、 TouchableWithoutFeedback

  • onPressIn:点击开始;
  • onPressOut:点击结束或者离开;
  • onPress:单击事件回调;
  • onLongPress:长按事件回调。

以上触摸事件无论怎么尝试在红框区域内都是无效事件

Pressable

Pressable 是一个核心组件的封装,它可以检测到任意子组件的不同阶段的按压交互情况

这个点击也是无效操作,到时官方文档里面的一句提示:触控区域不会超出绑定的父级 view,在按压到重叠的兄弟视图时,z-index 更高的那个视图会更优先

受到启发做一下尝试:

定位布局&解决方案

首先真机上打开Android调试工具的布局边框,展示如下前端的布局效果

  • 首先是顶部带背景banner区域的
  • 然后是签到卡片
  • 从布局上可以明显看到banner和签到卡片是有区域交叉重叠的
  • 从代码定位来一步步排查

    const styles = StyleSheet.create({
      banner: {
            height: 170,
            width: width,
            paddingTop: 25,
            paddingLeft: 15,
            backgroundColor: Colors.F4F5F7,
        },
    })
    <ImageBackground
          style={styles.banner}
          source={imageBanner}
          resizeMode="contain"
      >
          <Text style={styles.bannerTitle}>当前可用积分</Text>
          <View style={styles.bannerLeft}>
              <Text style={styles.bannerLeftCount}>
                  {taskInfo?.totalPoints}
              </Text>
              <TouchableOpacity
                  onPress={() => {
                      jumpToNewTask();
                  }}
              >
                  <ImageBackground
                      style={styles.newTaskBtn}
                      source={NewTaskBtn}
                  >
                      <Image
                          style={styles.bannerLeftImage}
                          source={MoneyImage}
                      />
                      <Text style={styles.newTaskText}>新手任务</Text>
                      <Image
                          style={styles.triangle}
                          source={TriangleRight}
                      />
                  </ImageBackground>
              </TouchableOpacity>
          </View>
          <TouchableOpacity
              style={styles.redeemBtnContent}
              onPress={() => {
                  jumpToRedeem();
              }}
          >
              <ImageBackground
                  style={styles.redeemBtn}
                  source={RedeemBtn}
              >
                  <Text style={styles.redeemBtnText}>积分兑换</Text>
              </ImageBackground>
          </TouchableOpacity>
              {/* 七天签到区域 */}
          <SignList
              data={taskDaily}
              info={taskInfo}
              signCallback={() => {
                  getTaskInfo();
                  getSignListInit();
              }}
          />
      </ImageBackground>
  • 从代码中可以明显看到签到卡片被包裹到banner的ImageBackground内部了 而banner的高度只有170px
  • 这样的话根据官方说的触控区域不会超过父级容器区域,那可实际可点击区域只有banner高度170内是可触控区域了
    image-20211218150116687
  • 那么到这问题就已经很清晰了 ,需要修改页面整体布局,具体如下

    const styles = StyleSheet.create({
      banner: {
            height: 170,
            width: width,
            paddingTop: 25,
            paddingLeft: 15,
            backgroundColor: Colors.F4F5F7,
        },
      signListContent: {
            borderRadius: 8,
            backgroundColor: Colors.FFFFFF,
            width: width - 30,
            marginTop: 25,
            paddingVertical: 20,
            position: 'absolute',
            top: 80,
            left: 15,
        }
    })
    <ImageBackground
          style={styles.banner}
          source={imageBanner}
          resizeMode="contain"
      >
          <Text style={styles.bannerTitle}>当前可用积分</Text>
          <View style={styles.bannerLeft}>
             ...
          </View>
          ...
      </ImageBackground>
      {/* 七天签到区域 */}
      <SignList
          data={taskDaily}
          info={taskInfo}
          signCallback={() => {
              getTaskInfo();
              getSignListInit();
          }}
      />
  • 签到卡片直接拿出来和banner平级,然后使用定位absolute来把卡片叠加到banner区域,这样他的父容器就是最外层的body文档流了,这样卡片内部都是可触控区域了,完美解决问题

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK