index.wxml
<view class="flex box box-lr"> <scroll-view class="flex groups box box-tb" scroll-y="true" scroll-into-view="{{scrollIntoView}}"> <block wx:for="{{groups}}" wx:for-item="group"> <view class="flex" id="{{group.groupName}}"> <view class="group-name">{{group.groupName}}</view> <view class="flex group-users"> <view wx:for="{{group.users}}" wx:for-item="user" wx:for-index="idx" class="user box box-lr"> <view class="user-avatar box box-lr box-pack-center box-align-center"> <image class="user-avatar-img" src="{{user.avatar}}"></image> </view> <view class="flex user-name">{{user.name}}</view> </view> </view> </view> </block> </scroll-view> <view class="nav box box-tb" bindtouchmove="touchmove" bindtouchcancel="touchcancel" bindtouchend="touchend"> <view bindtap="tabLetter" data-index="{{item}}" wx:for="{{letters}}" class="flex box box-align-center box-pack-center letter"> <text class="letter-text {{selected == item ? 'letter-actived' : ''}}">{{item}}</text> </view> </view> </view>
index.js
Page({ data:{ // 当前选择的导航字母 selected: 0, // 选择字母视图滚动的位置id scrollIntoView: 'A', // 导航字母 letters: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'], groups: [{ groupName: 'A', users: [ { name: '阿码', avatar: '../../images/avatar.png' } ] }, { groupName: 'B', users: [ { name: '白娘子', avatar: '../../images/avatar.png' }, { name: '包天齐', avatar: '../../images/avatar.png' } ] }, { groupName: 'C', users: [ { name: '陈大年', avatar: '../../images/avatar.png' }, { name: '丛云山', avatar: '../../images/avatar.png' }, { name: '崔鸣贵', avatar: '../../images/avatar.png' } ] }, { groupName: 'D', users: [ { name: '邓牛牛', avatar: '../../images/avatar.png' }, { name: '刁仁衣', avatar: '../../images/avatar.png' }, { name: '杜长城', avatar: '../../images/avatar.png' } ] }, { groupName: 'F', users: [ { name: '范长龙', avatar: '../../images/avatar.png' }, { name: '冯肖晓', avatar: '../../images/avatar.png' } ] }, { groupName: 'G', users: [ { name: '甘地', avatar: '../../images/avatar.png' }, { name: '高墙', avatar: '../../images/avatar.png' }, { name: '宫都举', avatar: '../../images/avatar.png' } ] }, { groupName: 'H', users: [ { name: '何芸', avatar: '../../images/avatar.png' }, { name: '胡坨坨', avatar: '../../images/avatar.png' }, { name: '黄坨坨', avatar: '../../images/avatar.png' } ] }, { groupName: 'T', users: [ { name: '谭老头儿', avatar: '../../images/avatar.png' }, { name: '汤云西', avatar: '../../images/avatar.png' }, { name: '图图', avatar: '../../images/avatar.png' } ] }, { groupName: 'X', users: [ { name: '夏一天', avatar: '../../images/avatar.png' }, { name: '鲜轰轰', avatar: '../../images/avatar.png' }, { name: '谢大佩', avatar: '../../images/avatar.png' } ] } ] }, onLoad:function(options){ const res = wx.getSystemInfoSync(), letters = this.data.letters; // 设备信息 this.setData({ windowHeight: res.windowHeight, windowWidth: res.windowWidth, pixelRatio: res.pixelRatio }); // 第一个字母距离顶部高度,单位使用的是rpx,须除以pixelRatio,才能与touch事件中的数值相加减,css中定义nav高度为94%,所以 *0.94 const navHeight = this.data.windowHeight * 0.94, // eachLetterHeight = navHeight / 26, comTop = (this.data.windowHeight - navHeight) / 2, temp = []; this.setData({ eachLetterHeight: eachLetterHeight }); // 求各字母距离设备左上角所处位置 for(let i = 0, len = letters.length; i < len; i++) { const x = this.data.windowWidth - (10 + 50) / this.data.pixelRatio, y = comTop + (i * eachLetterHeight); temp.push([x, y]); } this.setData({ lettersPosition: temp }) }, tabLetter(e) { const index = e.currentTarget.dataset.index; this.setData({ selected: index, scrollIntoView: index }) this.cleanAcitvedStatus(); }, // 清除字母选中状态 cleanAcitvedStatus() { setTimeout(() => { this.setData({ selected: 0 }) }, 500); }, touchmove(e) { const x = e.touches[0].clientX, y = e.touches[0].clientY, lettersPosition = this.data.lettersPosition, eachLetterHeight = this.data.eachLetterHeight, letters = this.data.letters; console.log(y); // 判断触摸点是否在字母导航栏上 if(x >= lettersPosition[0][0]) { for(let i = 0, len = lettersPosition.length; i < len; i++) { // 判断落在哪个字母区域,取出对应字母所在数组的索引,根据索引更新selected及scroll-into-view的值 const _y = lettersPosition[i][1], // 单个字母所处高度 __y = _y + eachLetterHeight; // 单个字母最大高度取值范围, 50为字母高50rpx if(y >= _y && y <= __y) { this.setData({ selected: letters[i], scrollIntoView: letters[i] }); break; } } } }, touchend(e) { this.cleanAcitvedStatus(); } })
index.wxss
page { background-color: #eee; } .nav { position: fixed; right: 10rpx; top: 3%; height: 94%; width: 50rpx; font-family: Arial, Helvetica, sans-serif } .letter { width: 50rpx; height: 50rpx; font-size: 30rpx; } .letter-text { display: inline-block; width: 100%; height: 100%; text-align: center; line-height: 50rpx; border-radius: 50%; } .letter-actived { background-color: #ccc; } .groups { /*height: 100%;*/ } .group-name { padding: 10rpx 30rpx; height: 50rpx; line-height: 50rpx; } .group-users { background-color: #fff; } .user { height: 100rpx; line-height: 100rpx; padding: 0 30rpx; border-bottom: 1px solid #eee; } .user-avatar { border-right: 1px solid #eee; width: 100rpx; } .user-avatar-img { width: 70rpx; height: 70rpx; border-radius: 50%; } .user-name { padding-left: 30rpx; }
来源:https://blog.csdn.net/qq_30641447/article/details/80985063