简介
最近接手一个小程序的项目,由于自己是Android开发,对前端了解程度不是太深,所以刚开始这个项目确实走了不少弯路。在此分享一个微信小程序仿支付宝应用列表,列表滚动顶部导航栏跟随滚动,点击顶部导航栏列表定位到相应的位置;这个需要我在网上怎么找都没有找到实现的方式,逼的我不得不动手亲自实现一番。
思路
这个需求的页面结构首先是一个横向滚动的导航列表,然后是一个纵向滚动的详细列表,因为横向和纵向都有滚动需求,而且横向列表要求点击其中某一项要滚动到指定位置,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
})
},
});
特别说明下,为了满足点击最后一个标签,纵向列表的最后一个区域能顶到最上部,我这边给一个纵向列表的最后一项一个填充高度,但是这个高度计算不是很精确,大家可以自己动手稍微修改一下。