小程序办理 iOS 边界滚动橡皮筋效果问题记录

打印 上一主题 下一主题

主题 1016|帖子 1016|积分 3048

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目标功能

在开发微信小程序时,我必要实现以下功能:


  • 当用户向上滚动屏幕时,底部地区 bottom-area 要显示。
  • 当用户向下滚动屏幕时,底部地区 bottom-area 要隐蔽。
最初的实现方法

最初,我通过监听滚动事件来实现隐蔽功能。当检测到用户向下滚动时,隐蔽 bottom-area,否则显示 bottom-area。代码如下:
  1. const scrollNew = ref<number>(0);
  2. const scrollOld = ref<number>(0);
  3. const isScrollDown = computed(() => scrollNew.value > scrollOld.value);
  4. const isHidden = computed(() => isScrollDown.value);
  5. onPageScroll((e) => {
  6.   scrollOld.value = scrollNew.value;
  7.   scrollNew.value = e.scrollTop;
  8. });
复制代码
碰到的问题

在 iOS 装备上,当用户滚动到页面底部并继承下拉时,会触发边界滚动橡皮筋效果,导致页面回弹。这种回弹会改变滚动状态 (回弹时向上滚动),使得 bottom-area 再次显示,违反了我们的初衷。
具体问题如下:


  • 当用户滚动到底部而且继承下拉时,页面会回弹,导致 isScrollDown 状态改变。
  • 这种状态改变使得 bottom-area 不测显示。
办理方案: 对底部地区举行特殊判断


  • 获取装备窗口高度
    使用 uni.getSystemInfoSync 获取窗口高度,存储在变量 viewportHeight 中。
  • 实现滚动事件处理函数
    在滚动事件处理函数中,使用 uni.createSelectorQuery 获取滚动位置信息,并判断是否滚动到底部。如果到达底部,隐蔽 bottom-area;否则,根据滚动方向决定是否隐蔽。
详细步骤

步骤一:获取窗口高度

使用 uni.getSystemInfoSync 获取装备的系统信息,包括窗口高度:
  1. const systemInfo = uni.getSystemInfoSync();
  2. const viewportHeight = systemInfo.windowHeight;
复制代码
步骤二:实现滚动事件处理函数

在滚动事件处理函数中,使用 uni.createSelectorQuery 获取滚动位置信息,并判断是否滚动到底部:
  1. const handlePageScroll = debounce((e: any) => {
  2.   scrollOld.value = scrollNew.value;
  3.   scrollNew.value = e.scrollTop;
  4.   uni.createSelectorQuery().selectViewport().scrollOffset((res) => {
  5.     if (res.scrollTop + viewportHeight >= res.scrollHeight) {
  6.       isHidden.value = true;
  7.     } else {
  8.       isHidden.value = isScrollDown.value;
  9.     }
  10.   }).exec();
  11. }, 50);
复制代码
  debounce() 是消抖函数
  完备代码示例

  1. <template>  <view class="forumdetailLayout">    <!-- 底部地区: 评论 点赞 上下页切换 -->    <view class="bottom-area" :class="{ hidden: isHidden }">      <wd-icon name="arrow-left" size="40rpx"></wd-icon>      <view class="edit">我有话要说...</view>      <view class="like">        <wd-icon name="thumb-up" size="40rpx"></wd-icon>        <view class="like-count">{{ forumDetail.likeCount }}</view>      </view>      <wd-icon name="arrow-right" size="40rpx"></wd-icon>    </view>  </view></template><script lang="ts" setup>import { debounce } from "lodash-es"; // 引入 lodash 的 debounce 函数const scrollNew = ref<number>(0);const scrollOld = ref<number>(0);const isHidden = ref<boolean>(false);const isScrollDown = computed(() => scrollNew.value > scrollOld.value);// 获取视口高度const systemInfo = uni.getSystemInfoSync();
  2. const viewportHeight = systemInfo.windowHeight;
  3. // 添加debounced处理函数const handlePageScroll = debounce((e: any) => {  scrollOld.value = scrollNew.value;  scrollNew.value = e.scrollTop;  uni    .createSelectorQuery()    .selectViewport()    .scrollOffset((res: any) => {      if (res.scrollTop + viewportHeight >= res.scrollHeight) {        isHidden.value = true;      } else {        isHidden.value = isScrollDown.value;      }    })    .exec();}, 20);onPageScroll(handlePageScroll);onReachBottom(() => {  isHidden.value = true;});</script><style lang="scss" scoped>.forumdetailLayout {  .bottom-area {    position: fixed;    bottom: 0;    z-index: 100;    box-sizing: border-box;    display: flex;    align-items: center; /* 中心对齐 */    justify-content: center; /* 在子元素之间匀称分布 */    width: 100%;    padding: 17rpx 30rpx env(safe-area-inset-bottom) 30rpx;    background-color: $background-color;    transition: transform 0.3s;    .edit {      flex: 1; /* 占据剩余空间 */      padding: 17rpx;      margin-right: 10rpx; /* 右边距 */      color: $text-color-grey;      background-color: white;      border-radius: 24rpx;    }    .like {      display: flex;      flex-direction: column;      align-items: center; /* 内部中心对齐 */      margin-right: 10rpx; /* 右边距 */    }  }  .bottom-area.hidden {    transform: translateY(100%);  }}</style>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

知者何南

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表