微信小程序开发--列表滚动上下联动效果

简介: 列表滚动

当点击tab栏的时候,列表数据也跟随联动。

下面是实现的一个效果图:

网络异常,图片无法展示
|

顶部的头部区域不跟随列表滚动; 头部区域以下属于滚动区域。

2、实现

2.1 原理介绍

这个地方的实现主要借助了微信小程序原生的scroll-view组件。

使用它的 scroll-into-view 属性,可以实现点击顶部的tab栏,将页面滚动到指定的列表位置;

使用 bindscroll 事件,可以知道当前页面滚动的距离,根据滚动的距离做tab栏的切换操作;

2.1 页面布局代码

先说下界面的整体布局,主要分为两部分,头部固定区域 + 可滚动列表区域。

可滚动的列表区域的标题栏当滚动一定的距离后,它也要固定在顶部。

代码实现:

<!--index.wxml--><viewclass="list"><!--顶部固定区域--><viewstyle="height: 88rpx;width: 100%;background-color: burlywood;text-align: center;">头部区域</view><!--可滚动区域--><scroll-viewscroll-y="true"style="width: 100%; height: {{scrollAreaHeight}}px;"bindscroll="scroll"scroll-into-view="{{scrollToItem}}"scroll-with-animation="true"scroll-top="{{scrollTop}}"><!--水平滚动的tab栏--><scroll-viewscroll-x="true"style="height: 88rpx;width: 100%;"><viewclass="head-area {{float ? 'head-float' : ''}}"><viewclass="head-area-item {{curSelectTab === index ? 'head-area-item-select' : ''}}"wx:for="{{appGroupList}}"bindtap="tabClick"data-index="{{index}}">    {{item.name}}
</view></view></scroll-view><!--数据列表--><viewclass="list-group"style="height: {{listGroupHeight}}px;"><viewclass="list-group-item"id="v_{{index}}"wx:for="{{appGroupList}}"data-index="{{index}}"><viewclass="group-name">      {{item.name}}
</view><viewclass="group-children"><viewwx:for="{{item.children}}"class="group-children-item"style="width: {{itemWidth}}px;"><imagesrc="{{item.url}}"></image><view>{{item.name}}</view></view></view></view></view></scroll-view></view>

1、scrollAreaHeight 滚动区域的高度计算。 --- 通过获取当前设备的窗口高度减去顶部固定区域的高度

2、水平tab栏是否置顶。 --- 根据页面的滚动距离来判断,如果滚动距离 大于或者等于 水平tab栏的高度,则置顶;

3、设置数据列表的id="v_{{index}}" id,后续点击tab栏滚动到指定的位置就是根据这个id去实现的。

/**index.wxss**/
.list{
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}
.head-area{
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  height: 88rpx;
  width: 100%;
  padding: 0 10;
}
.head-area-item{
  display: flex;
  height: 88rpx;
  text-align: center;
  width: 150rpx;
  align-items: center;
  justify-content: center;
}
.head-area-item-select{
  color: #09bb07;
}
image{
  width: 88rpx;
  height: 88rpx;
}
.list-group{
  display: flex;
  width: 100%;
  height: 1000%;
  flex-direction: column;
}
.list-group-item{
  display: flex;
  width: 100%;
  background-color: #aaa;
  flex-direction: column;
}
.group-name{
  height: 88rpx;
  display: flex;
  text-align: center;
  align-items: center;
  margin-left: 20rpx;
}
.group-children{
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  width: 100%;
}
.group-children-item{
  height: 160rpx;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.head-float{
  position: fixed;
  top: 88rpx;
  background-color: #ffffff;
}

js逻辑层

// index.js
Page({
  heightArr: [],
  //记录scroll-view滚动过程中距离顶部的高度
  distance: 0,
  data: {
    appGroupList:[
      {name:"分组01",children:[{"name":"测试0","url":"/images/bluetooth.png"},
      {"name":"测试1","url":"/images/bluetooth.png"},
      {"name":"测试2","url":"/images/bluetooth.png"},
      {"name":"测试3","url":"/images/bluetooth.png"},
      {"name":"测试4","url":"/images/bluetooth.png"},
      {"name":"测试5","url":"/images/bluetooth.png"},
      {"name":"测试6","url":"/images/bluetooth.png"},
      {"name":"测试7","url":"/images/bluetooth.png"}]},
      {name:"分组02",children:[{"name":"测试0","url":"/images/bluetooth.png"},
      {"name":"测试1","url":"/images/bluetooth.png"},
      {"name":"测试2","url":"/images/bluetooth.png"},
      {"name":"测试3","url":"/images/bluetooth.png"},
      {"name":"测试4","url":"/images/bluetooth.png"},
      {"name":"测试5","url":"/images/bluetooth.png"},
      {"name":"测试6","url":"/images/bluetooth.png"},
      {"name":"测试7","url":"/images/bluetooth.png"}]},
      {name:"分组03",children:[{"name":"测试0","url":"/images/bluetooth.png"},
      {"name":"测试1","url":"/images/bluetooth.png"},
      {"name":"测试2","url":"/images/bluetooth.png"},
      {"name":"测试3","url":"/images/bluetooth.png"},
      {"name":"测试4","url":"/images/bluetooth.png"},
      {"name":"测试5","url":"/images/bluetooth.png"},
      {"name":"测试6","url":"/images/bluetooth.png"},
      {"name":"测试7","url":"/images/bluetooth.png"}]},
      {name:"分组04",children:[{"name":"测试0","url":"/images/bluetooth.png"},
      {"name":"测试1","url":"/images/bluetooth.png"},
      {"name":"测试2","url":"/images/bluetooth.png"},
      {"name":"测试3","url":"/images/bluetooth.png"},
      {"name":"测试4","url":"/images/bluetooth.png"},
      {"name":"测试5","url":"/images/bluetooth.png"},
      {"name":"测试6","url":"/images/bluetooth.png"},
      {"name":"测试7","url":"/images/bluetooth.png"}]},
      {name:"分组05",children:[{"name":"测试0","url":"/images/bluetooth.png"},
      {"name":"测试1","url":"/images/bluetooth.png"},
      {"name":"测试2","url":"/images/bluetooth.png"},
      {"name":"测试3","url":"/images/bluetooth.png"},
      {"name":"测试4","url":"/images/bluetooth.png"},
      {"name":"测试5","url":"/images/bluetooth.png"},
      {"name":"测试6","url":"/images/bluetooth.png"},
      {"name":"测试7","url":"/images/bluetooth.png"}]},
    ],
    itemWidth: wx.getSystemInfoSync().windowWidth / 4,
    scrollAreaHeight:wx.getSystemInfoSync().windowHeight - 44,
    float:false,
    curSelectTab:0,
    scrollToItem:null,
    scrollTop: 0, //到顶部的距离
    listGroupHeight:0,
  },
  onReady: function () {
    this.cacluItemHeight();
  },
  scroll:function(e){
    console.log("scroll:",e);
    if(e.detail.scrollTop>=44){
      this.setData({
        float : true
      })
    } else if(e.detail.scrollTop<44){this.setData({float:false})}letscrollTop = e.detail.scrollTop;letcurrent = this.data.curSelectTab;if(scrollTop>= this.distance) {
      //页面向上滑动
      //列表当前可视区域最底部到顶部的距离 超过 当前列表选中项距顶部的高度(且没有下标越界),则更新tab栏
      if (current + 1 <this.heightArr.length&&scrollTop>= this.heightArr[current]) {
        this.setData({
          curSelectTab: current + 1
        })
      }
    } else { 
      //页面向下滑动
      //如果列表当前可视区域最顶部到顶部的距离 小于 当前列表选中的项距顶部的高度,则切换tab栏的选中项
      if (current - 1 >= 0 && scrollTop <this.heightArr[current-1]){this.setData({curSelectTab:current-1})}}//更新到顶部的距离this.distance = scrollTop;},tabClick(e){this.setData({curSelectTab:e.currentTarget.dataset.index,scrollToItem:"v_"+e.currentTarget.dataset.index})},//计算每一个item高度cacluItemHeight(){letthat = this;this.heightArr = [];leth = 0;constquery = wx.createSelectorQuery();query.selectAll('.list-group-item').boundingClientRect()query.exec(function(res){res[0].forEach((item) => {
        h += item.height;
        that.heightArr.push(h);
      })
      console.log(that.heightArr);
      that.setData({
        listGroupHeight: that.heightArr[that.heightArr.length - 1 ]
      })
    })
  },
})

以上内容仅供参考

相关文章
|
5月前
|
人工智能 小程序 前端开发
一个小程序轻量AR体感游戏,开发实现解决方案
针对青少年运动兴趣不足问题,AR体感游戏凭借沉浸式互动体验脱颖而出。结合小程序“AI运动识别”插件与WebGL渲染技术,可实现无需外设的轻量化AR健身游戏,如跳糕、切水果等,兼具趣味性与锻炼效果,适用于儿童健身及职工团建,即开即玩,低门槛高参与。
|
5月前
|
移动开发 小程序 前端开发
小程序开发平台有哪些?哪个好
小程序的开发方式丰富多元,开发团队可根据自身的技术背景、项目具体需求以及资源状况,灵活挑选最为适宜的开发路径。以下将详细介绍几种主流的小程序开发方式。
548 1
|
5月前
|
运维 小程序 数据可视化
小程序开发平台有哪些?SaaS小程序制作平台哪个好
小程序开发模式详解:自主开发、SaaS小程序制作平台与外包全对比 选择合适的小程序开发模式,是项目成功的基石。这三种模式在成本、周期、控制力和灵活性上各有千秋,适用于不同阶段和不同类型的企业。下面我们将逐一深入剖析。
450 8
|
5月前
|
移动开发 小程序 前端开发
小程序快速开发平台有哪些?
小程序开发并非“一刀切”,需结合技术储备、资金预算、时间规划及功能需求等多维度因素综合考量。以下为您详细拆解五种主流开发方案及其适用场景,助您精准匹配开发路径。
337 3
|
5月前
|
移动开发 小程序 前端开发
小程序开发平台有哪些?小程序开发制作软件推荐
小程序开发方案全解析:5种主流方式与选择指南 小程序开发需根据技术能力、预算、时间及功能需求综合决策。以下为5种主流开发方案及适用场景分析:
26057 0
|
7月前
|
小程序 JavaScript API
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
这篇文章介绍了使用uni-halo框架进行微信小程序开发的过程,包括选择该框架的原因、开发目标以及项目配置和部署的步骤。
383 0
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
|
10月前
|
小程序 前端开发 Android开发
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
1991 29
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
|
11月前
|
人工智能 开发框架 小程序
工会成立100周年纪念,开发职工健身AI运动小程序、APP方案推荐
为庆祝中华全国总工会成立100周年,特推出基于AI技术的智能健身系统,以小程序和APP形式呈现,助力职工健康生活。方案包括:1) 小程序插件,支持多种运动识别,开箱即用;2) APP插件,提供更高精度的运动检测;3) 成熟的「AI乐运动」系统,支持赛事活动管理。这些方案满足不同需求,推动全民健身体验升级,彰显工会对职工健康的关怀。

热门文章

最新文章