小程序开发踩坑记录(五)——模拟实现底部tabbar和下拉刷新功能(解决安卓端打开下拉刷新功能后fixed元素失效问题)

①问题描述

因为上一篇文章提到的问题,小程序目前(2019年4月29日)暂时无法实现在打开下拉刷新功能的前提下,自己使用position:fixed制作底部tabbar标签导航栏,在下拉刷新时,页面上所有的fixed元素也都会失去fixed效果,会跟随页面一起下拉。
为解决这个问题,笔者使用scroll-view组件自制下拉刷新功能,使用position:fixed自制底部tabbar,基本解决(或者说避开)了这个问题。

②实现情况

小程序开发踩坑记录(五)——模拟实现底部tabbar和下拉刷新功能(解决安卓端打开下拉刷新功能后fixed元素失效问题)_第1张图片

小程序开发踩坑记录(五)——模拟实现底部tabbar和下拉刷新功能(解决安卓端打开下拉刷新功能后fixed元素失效问题)_第2张图片

③实现方式

主要思路:

tabbar部分:

以tabbar有三项为例,这三个页面并非通过路由跳转,而是一个index页面内的三个不同的自定义组件,通过 wx:if 控制显示隐藏来实现(看起来像的)“页面跳转”,底部的 footer 通过 { position : fixed } 固定定位在 { bottom:0 } 处。点击tabbar上的三个选项改变的只是 activeItem 的值而非页面路由。

index页面结构:











下拉刷新部分:

基础结构:


	
		
			
			
		
	

其中,refreshBox 为下拉刷新时才能看到的内容,即前文图中的箭头图片,正在刷新、最后更新时间等内容。content 内部放入需要正常显示的正文内容。
在此结构的基础上,给scroll-view设置 scroll-top="{{scrolltop}}" 属性,其中 scrolltop 的初始值设置为 refreshBox 的高度(假设为75px,此处最好用px单位),即可在进入页面时,滚动条自动滚动至75px,就能达到隐藏起来refreshBox 的效果 。
而后,再给 scroll-view 绑定 bindtouchend=“touchend” 事件,检测当手指离开屏幕时,如果 scrollheight (滚动条当前的位置,可通过onscroll事件获取)小于75,则 setData({ scrolltop:75px }),即当检测到松手时 refreshbox 是可见状态时,就自动滚动至可以将其完全隐藏的位置,视觉上与原生的刷新还是十分相似的。

④几个重点

基本思路就如上所述,而落实到具体代码上时还有这么几个坑需要注意:

  1. 最重要的:一定不要在 app.json 和 index.json 中开启 enablePullDownRefresh !!!

  2. scroll-view外层的view要设置height:100%,该组件的wxss要设置 page{ height:100% } ,scroll-view内的view要设置 { min-height: 120%; },因为如果不将scroll-view填满屏幕并使内部高度溢出,就不会出现滚动条,scroll-top也就不起作用,refreshBox 会直接可见。

  3. < scroll-view >中设置的 bindtouchend =“touchend” 函数 和 onscroll = “scroll” 函数有几个点需要注意,写在相应注释中了:

    touchend() {
      var that = this;
      //松开手指时如果scrollheight小于75,说明此时refreshbox是可见的,需要滚动将其隐藏
      if (this.data.scrollheight < 75) {
        this.setData({
          scrolltop: '75px'
        })
      }
      
      //记录松开手指时滚动条的高度和标记手指已经离开,以便在scroll中判断出页面是靠惯性滚动至顶的,此时要手动停止滚动,防止refreshbox漏出
      this.setData({
        topWhenTouchEnd: this.data.scrollheight,
        istouching: false
      })
      //一定延迟后,refreshbox一定已经处于隐藏状态了,此时将字样和图片改回
      setTimeout(function() {
        that.setData({
          refreshText: '下拉刷新...',
          refreshIcon: "/image/arrow_down.png",
        });
        //如果shouldRefresh标记为true,代表需要刷新(在scroll中控制)
        if (that.data.shouldRefresh == true) {
          //获取页面所有数据的函数
          that.getData('ref');
          //将shouldRefresh重置便于下次使用
          that.setData({
            shouldRefresh: false
          })
        }
      }, 500)
    },
    scroll(e) {
      this.setData({
        scrollheight: e.detail.scrollTop,
      })
      //如果e.detail.scrollTop < 10 ,说明已经拉到底了,即代表用户确实在使用下拉刷新功能,此时改变文字,并将shouldRefresh标记设为true以在touchend中刷新数据
      if (e.detail.scrollTop < 10) {
        //此处进行刷新函数
        this.setData({
          refreshText: '松开刷新...',
          refreshIcon: "/image/arrow_up.png",
          shouldRefresh: true
        })
      }
      //判断如果页面是靠惯性滚动至顶的,则要手动停止其继续滚动,防止refreshbox漏出
      if (this.data.topWhenTouchEnd > 75 && this.data.istouching == false) {
        if (e.detail.scrollTop < 76) {
          this.setData({
            scrolltop: '150rpx',
            topWhenTouchEnd: 0
          })
        }
      }
    },
    
  4. 在 index.wxss 中设置:::-webkit-scrollbar{ width:0; height:0; color:transparent; }
    将滚动条隐藏,因为此时滚动条与视觉效果不一致(因为当视觉看起来页面到顶时,滚动条并不在顶部,只有将 refreshbox 都拉到底时滚动条才在顶部,影响页面效果)

⑤小结

试了相当多的办法,这个算是最终效果比较好的一种了,暂时没发现什么太大的不足(写起来费劲不算,实现效果最重要),更重要的是在苹果和安卓端都能较好地实现,且刷新框和底部栏都可完全自定义,不必再拘泥于原生刷新和原生tabbar的那几条属性,从而可以放飞自我,实现ui同学设计的各种酷炫的效果,防止前端和UI刀兵相见,大大促进办公室和谐。XD

p.s.文中只是介绍了实现的大概思路,目的在给也遇到这个问题、还没有前进方向的童鞋指个路,并没有放很多代码,因为我的代码里有很多业务逻辑,与本文没太大关系,都贴上来更乱,笔者也懒得整理了,有迫切需要或者有问题的话请留言。

你可能感兴趣的:(小程序)