1, the background

Recently, I was working on a small program of the company. One of the designs was that when you scroll up and down the list, the TAB bar at the top will be linked together. When you click the TAB bar, the list data will be linked together.

Here is an example of the implementation:

The top header does not scroll with the list; Below the header area is the scroll area.

2, implementation,

2.1 Principles

The implementation of this place mainly with the help of wechat applet native Scroll view components.

Using its scroll-into-view property, you can click the TAB bar at the top to scroll the page to the specified list position.

Using the BindScroll event, you can know the scrolling distance of the current page and switch the TAB bar according to the scrolling distance.

2.1 Page layout code

First, the overall layout of the lower interface is mainly divided into two parts, the head fixed area + scrollable list area.

The title bar in the scrollable list area should also be fixed to the top after scrolling a certain distance.

Code implementation:

<! --index.wxml--> <view class="list"> <! < p style=" word-break: break-all; color: RGB (0, 0, 0); width: 100%; background-color: burlywood; text-align: center;" > Header </view> <! < span style=" max-width: 100%; clear: both; min-height: 1em; height: {{scrollAreaHeight}}px;" bindscroll="scroll" scroll-into-view="{{scrollToItem}}" scroll-with-animation="true" scroll-top="{{scrollTop}}"> <! <scroll view scroll x="true" style="height: 88rpx; width: 100%;" > <view class="head-area {{float ? 'head-float' : ''}}" > <view class="head-area-item {{curSelectTab === index ? 'head-area-item-select' : ''}}" wx:for="{{appGroupList}}" bindtap="tabClick" data-index="{{index}}"> {{item.name}} </view> </view> </scroll-view> <! <view class="list-group" style="height: {{listGroupHeight}}px; > <view class="list-group-item" id="v_{{index}}" wx:for="{{appGroupList}}" data-index="{{index}}"> <view class="group-name"> {{item.name}} </view> <view class="group-children" > <view wx:for="{{item.children}}" class="group-children-item" style="width: {{itemWidth}}px;" > <image src="{{item.url}}"></image> <view>{{item.name}}</view> </view> </view> </view> </view> </scroll-view> </view>Copy the code

There are a few points to note in the layout code:

1. ScrollAreaHeight Calculates the height of the rolling area. Get the window height of the current device minus the height of the top fixed area

2, whether the horizontal TAB column is placed at the top. — Judging by the scrolling distance of the page, if the scrolling distance is greater than or equal to the height of the horizontal TAB bar, the top;

3, set the id of the data list =”v_{{index}}” id, then click TAB to scroll to the specified position is based on this ID to achieve.

2.2 Style Code

/**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;
}

Copy the code

2.3 Logical Code

// Index.js Page({heightArr: [], // Note the height of the swellview in the highlighted view, 0, data: {appGroupList: [{name: "grouping 01," children: [{" name ":" test 0 ", "url" : ". / images/bluetooth PNG} ", {" name ":" 1 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 2 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 3 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 4 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 5 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 6 ", "url" : ". / images/bluetooth PNG} ", Test ({" name ":" 7 ", "url" : ". / images/bluetooth PNG}}, {name: "grouping 02," children: [{" name ":" test 0 ", "url" : ". / images/bluetooth PNG} ", {" name ":" 1 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 2 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 3 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 4 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 5 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 6 ", "url" : ". / images/bluetooth PNG} ", Test ({" name ":" 7 ", "url" : ". / images/bluetooth PNG}}, {name: "grouping 03," children: [{" name ":" test 0 ", "url" : ". / images/bluetooth PNG} ", {" name ":" 1 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 2 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 3 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 4 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 5 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 6 ", "url" : ". / images/bluetooth PNG} ", Test ({" name ":" 7 ", "url" : ". / images/bluetooth PNG}}, {name: "grouping 04", the children: [{" name ":" test 0 ", "url" : ". / images/bluetooth PNG} ", {" name ":" 1 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 2 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 3 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 4 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 5 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 6 ", "url" : ". / images/bluetooth PNG} ", Test ({" name ":" 7 ", "url" : ". / images/bluetooth PNG}}, {name: "grouping 05," the children: [{" name ":" test 0 ", "url" : ". / images/bluetooth PNG} ", {" name ":" 1 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 2 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 3 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 4 ", "url" : ". / images/bluetooth PNG} ", {" name ":" test 5 ", "url" : ". / images/bluetooth PNG "}, {" name ":" test 6 ", "url" : ". / images/bluetooth PNG} ", Test ({" 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 }) } let scrollTop = e.detail.scrollTop; let current = this.data.curSelectTab; If (scrollTop >= this.distance) {// Slide the page up // The distance from the bottom to the top of the current visible area of the list exceeds the height of the current list selected items from the top (without subscripting out of bounds), For example, if (current + 1 < this.heightarr. Length && scrollTop >= this.heightarr [current]) {this.setData({curSelectTab: Current + 1})}} else {// Slide the page down // If the distance from the top to the top of the current visible area of the list is less than the height from the top of the current list selected items, In the TAB column, switch the highlighted item if (current-1 >= 0 && scrollTop < this.heightarr [current-1]) {this.setData({curSelectTab: This.distance = scrollTop; this.distance = scrollTop; }, tabClick(e){ this.setData({ curSelectTab: e.currentTarget.dataset.index, scrollToItem: "V_" + e.c. with our fabrication: urrentTarget. Dataset. The index})}, / / calculate each item height cacluItemHeight () {let that = this; this.heightArr = []; let h = 0; const query = 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 ] }) }) }, })Copy the code

There are two main places in logical code:

1. CacluItemHeight calculates an array of heights for the items in the list, and stores the final calculation in the heightArr array.

The values of each entry in the heightArr array are summed over the previous one.

2. Determine the current scrolling direction in scroll, determine the current scrolling direction according to the scrolling distance, and set the TAB to be selected according to the scrolling distance.

Ok, so much, based on the above content can basically achieve the desired scrolling linkage, switch TAB linkage effect.