微信小程序仿支付宝应用列表功能,横纵项列表滚动定位

简介

最近接手一个小程序的项目,由于自己是Android开发,对前端了解程度不是太深,所以刚开始这个项目确实走了不少弯路。在此分享一个微信小程序仿支付宝应用列表,列表滚动顶部导航栏跟随滚动,点击顶部导航栏列表定位到相应的位置;这个需要我在网上怎么找都没有找到实现的方式,逼的我不得不动手亲自实现一番。


simple.jpg

思路

这个需求的页面结构首先是一个横向滚动的导航列表,然后是一个纵向滚动的详细列表,因为横向和纵向都有滚动需求,而且横向列表要求点击其中某一项要滚动到指定位置,scrollview的scroll-into-view的属性微信官方API中有详细的介绍,正好满足我们这一需求。
有了scroll-into-view这一属性,我们先分析横向滚动,点击某一项就滚动到对应的项,该属性需要传入对应项的id,我们就要给每一项指定对应的id,注意微信api特别指出id不能以数字开头,在每一个项里设置点击事件,把当前选中的id赋值给scoll-into-view属性,然后就能实现点击跳转功能,页面代码如下:

  <scroll-view class="zt_head" scroll-x="true" scroll-with-animation="true" scroll-into-view="{{head_scroll_to_position}}">
    <block wx:for="{{data_list}}" wx:for-index="inx" wx:key="index" wx:for-item="item">
      <view id="{{'head'+inx}}" bindtap="selectTab" data-selectedtab="{{inx}}" class="word {{ativity_tab==inx?'on':''}}" style="background-image: url({{ativity_tab==inx?'/images/director.png':''}})">{{item.theme.channelName}}</view>
    </block>
  </scroll-view>

js代码如下

  selectTab: function(e) {
    var that = this;
    var index = e.currentTarget.dataset.selectedtab;
    that.setData({
      ativity_tab: index,
      arrive_position: 'sub' + index  //到达纵向滚动的区域
    });
  }

纵向滚动要求滚动到标签的某一区域,在此区域经过时,导航栏的标签不切换,直到滚动到下一标签区域时,导航栏滚动到指定的标签。这一需求就需要我们计算详细列表的每一项区域的高度,在此区域经过时,保证选中的导航栏标签不切换,计算每一项区域高度的代码如下:

  /**
   * 计算每个item的高度
   */
  getItemsHeight: function(){
    var that = this;
    var listsize = that.data.data_list.length;
    var distance = that.data.destince_top;
    var arr = [];
    for (var i = 0; i < listsize; i++) {
      wx.createSelectorQuery().select('#sub' + i).boundingClientRect(function (rect) {
        arr.push(rect.bottom - rect.top);

      }).exec()
    }
    that.data.item_height = arr
  }

计算完每一区域的高度,然后存放在一个高度数组里,在我们纵向列表滚动时计算经过区域的时候使用。在纵向滚动的列表中我们使用bindscroll方法来监听列表滚动的距离,其中监听方法的返回值中有scrollTop就是列表滚动的距离,由此我们计算方法如下:

  listScroll: function(e) {
    var that = this;
    var distance = e.detail.scrollTop;
    var listsize = that.data.item_height.length;
    for (var i = 0; i < listsize; i++) {
      if (i == 0) {
        if (distance < that.data.item_height[0]) {
          //防止列表滚动时反复的setData,提高列表的渲染性能
          if (that.data.head_scroll_to_position != null && that.data.head_scroll_to_position == "head0") {
            break;
          }
          that.setData({
            ativity_tab: 0,
            head_scroll_to_position: 'head0'
          });
          break;
        }
      } else {
        if (distance > that.sumItemHeight(i - 1) && (distance < that.sumItemHeight(i))) {
          //防止列表滚动时反复的setData,提高列表的渲染性能
          if (that.data.head_scroll_to_position != null && that.data.head_scroll_to_position == ("head" + i)) {
            break;
          }
          that.setData({
            ativity_tab: i,
            head_scroll_to_position: 'head' + i
          });
          break;
        }
      }
    }
  },
  /**
   * 计算某一项区域距离列表顶部的高度
   */
  sumItemHeight: function(e) {

    var that = this;
    if (e == 0) {
      return that.data.item_height[0];
    }
    return that.data.item_height[e] + that.sumItemHeight(e - 1);
  }

得到当前列表经过得区域,然后将当前横向标签的id通过setdata赋值,就实现了列表纵向滚动到某一区域,导航标签就滑动到指定的标签,下面给出横向列表的页面代码:

  <scroll-view class="scoll_list" style='height:{{scroll_list_height}}rpx;' scroll-y="true" scroll-with-animation="true" scroll-into-view="{{arrive_position}}" bindscroll="listScroll" >
    <block wx:for="{{data_list}}" wx:for-index="ids" wx:key="indexi" wx:for-item="fitem">
      <view id="{{'sub'+ids}}" class="zt_menu " style="{{ids==ztfw_list.length-1?'padding-bottom:'+window_heigh+'rpx !important':'padding-bottom:20rpx !important'}}">
        <view class="zt_title ">{{fitem.theme.channelName}}</view>
        <block wx:for="{{fitem.service}}" wx:key="indexj" wx:for-item="sitem">
          <view bindtap="gotoZTFind" data-ztbean='{{sitem}}' class="zt_nav ">
            <view class="zt_sub " style="background-image: url('{{sitem.picUrl}}');">
              <view class="box ">{{sitem.title}}</view>
            </view>
          </view>
        </block>
      </view>
    </block>
  </scroll-view>

总结

以上就是实现类似支付宝应用列表功能的思路以及代码,需要注意的是横向scrollview需要设置宽度,我这里设置成屏幕的宽度,纵向的srollview需要设置高度,我这里设置的高度是窗口的高度减去横向导航栏的高度,横向导航栏css样式设置是浮动,设置高度代码如下:

    wx.getSystemInfo({
      success: function(res) {
        //屏幕比率
        let ratio = 750 / res.windowWidth;
        that.setData({
          scroll_list_height: res.windowHeight * ratio - 96,
          scroll_head_width: res.windowWidth * ratio,
          window_heigh: res.windowHeight * ratio - 400
        })
      },
    });

特别说明下,为了满足点击最后一个标签,纵向列表的最后一个区域能顶到最上部,我这边给一个纵向列表的最后一项一个填充高度,但是这个高度计算不是很精确,大家可以自己动手稍微修改一下。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。