当前位置:   article > 正文

小程序实现左右切换滑动列表思路_小程序如何实现一个框内向右滑动改动一列一列内容

小程序如何实现一个框内向右滑动改动一列一列内容

实现目标

  1. 可左右滑动切换列表;
  2. 点击分类菜单切换到相应的列表;
  3. 每个列表都可以上拉加载及下拉刷新;

结果展示

在这里插入图片描述

思路

通过使用scroll-view组件来实现顶部的菜单列表、多个列表的左右滑动实现父组件及滚动列表,同时监听触摸相关事件来处理左右滑动整个列表而不是滑一部分移动一部分、对列表上下滚动和左右滑动的优化及配合translateY实现scroll-view组件的上拉加载和下拉刷新。

代码实现

基本的wxml文件实现布局:

<view class="page-con">
  <scroll-view class="nav-list" scroll-x="{{true}}" scroll-into-view="{{navList[activeNavIndex].name}}" scroll-with-animation="true" scroll-anchoring="true">
    <view id="{{item.name}}" class="nav-item {{activeNavIndex === index ? 'active' : ''}}" wx:for="{{navList}}" wx:key="index" bindtap="switchPage" data-navIndex="{{index}}">{{item.name}}</view>
  </scroll-view>
  <scroll-view class="list-con" scroll-x="{{canSwitch}}" scroll-into-view="{{navList[activeNavIndex].name}}" scroll-with-animation="true" scroll-anchoring="true">
    <scroll-view id="{{item.name}}" class="list-item" wx:for="{{navList}}" wx:key="index" scroll-y="true" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" bindtouchcancel="touchCancel" bindscroll="listScroll" bindscrolltolower="bottomLoad" style="transform: translateY({{freshDistance}}px)">
      <view class="top-fresh" hidden="{{!item.isFresh}}"></view>
      <view class="card-item" wx:for="{{item.cardNum}}" wx:for-item="cardItem" wx:for-index="cardIndex" wx:key="cardIndex">{{item.name}}-{{cardIndex}}</view>
      <view class="top-fresh" hidden="{{!item.showLoading}}"></view>
    </scroll-view>
  </scroll-view>
</view>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

wxss文件实现页面UI的优化:

.page-con{
  width: 100vw;
  height: 100vh;
  background: #f5f5f5;
}
.nav-list{
  position: sticky;
  top: 0;
  width: 100%;
  padding: 10rpx 20rpx;
  box-sizing: border-box;
  background: #fff;
  white-space: nowrap;
}
.nav-item{
  display: inline-block;
  height: 40rpx;
  line-height: 40rpx;
  padding: 10rpx 20rpx;
  background: #f5f5f5;
  border-radius: 6rpx;
  margin-right: 12rpx;
}
.nav-item.active{
  background: #2CAE73;
  color: #fff;
}
.list-con{
  width: 100%;
  height: calc(100% - 80rpx);
  white-space: nowrap;
}
.list-item{
  display: inline-block;
  width: 100vw;
  height: 100%;
  box-sizing: border-box;
  transition: all 200ms;
}
.card-item{
  width: calc(100% - 48rpx);
  height: 300rpx;
  background: #fff;
  border-radius: 8rpx;
  margin: 24rpx auto 0;
  text-align: center;
  line-height: 300rpx;
}
.top-fresh{
  padding: 10rpx 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
.top-fresh::after{
  content: '';
  width: 30rpx;
  height: 30rpx;
  border-radius: 15rpx;
  border: 4rpx solid #2CAE73;
  border-left-color: transparent;
  border-bottom-color: transparent;
  border-right-color: transparent;
  animation: freshLoading 600ms linear infinite;
}
@keyframes freshLoading {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

js实现相关功能:

let pageData = {};
Page({
  data: {
    navList:[
      { id: 0, name: 'test1', isFresh: false, showLoading: false, cardNum: 20 },
      { id: 1, name: 'test2', isFresh: false, showLoading: false, cardNum: 20 },
      { id: 2, name: 'test3', isFresh: false, showLoading: false, cardNum: 20 },
      { id: 3, name: 'test4', isFresh: false, showLoading: false, cardNum: 20 },
      { id: 4, name: 'test5', isFresh: false, showLoading: false, cardNum: 20 },
      { id: 5, name: 'test6', isFresh: false, showLoading: false, cardNum: 20 },
      { id: 6, name: 'test7', isFresh: false, showLoading: false, cardNum: 20 }
    ],
    activeNavIndex: 0,
    canSwitch: true,
    freshDistance: 0
  },
  onPullDownRefresh() {
    wx.stopPullDownRefresh();
  },
  switchPage(e) {
  	//实现点击菜单切换列表
    const { navindex = 0 } = e.currentTarget.dataset;
    this.setData({ activeNavIndex: navindex });
  },
  touchStart(e) {
  	//记录开始触摸时的坐标,后续用来进行切换滚动的优化及下拉刷新的距离计算。
    const { clientX = 0, clientY = 0 } = e.changedTouches[0];
    Object.assign(pageData, { startX: clientX, startY: clientY });
  },
  touchMove(e) {
  	//手指移动时判断是左右滑动还是上下滚动。手指向下拉时记录下拉的距离;当上下滑动的距离大于左右距离且小于5时也记录下拉距离同时使左右滑动失效。
    const { clientX = 0, clientY = 0 } = e.changedTouches[0], { startY = 0, startX = 0 } = pageData;
    let { canSwitch = true, navList = [], activeNavIndex = 0 } = this.data;
    let distanceY = clientY - startY, distanceX = clientX - startX;
    if (canSwitch){
      if (Math.abs(distanceX) < Math.abs(distanceY) && Math.abs(distanceX) < 5){
        if (distanceY > 0) {
          Object.assign(navList[activeNavIndex], { isFresh: true, });
          this.setData({ freshDistance: distanceY, canSwitch: false, navList });
        }
      }
    }else{
      if (distanceY > 0) {
        Object.assign(navList[activeNavIndex], { isFresh: true, });
        this.setData({ freshDistance: distanceY, canSwitch: false, navList });
      }
    }
  },
  touchEnd(e) {
  	//触摸结束时判断若此时左右滑动无失效时判断左右滑动方向来切花列表;失效时表明是上下滚动,同时若是下拉判断下拉距离达到刷新的距离时触发刷法模拟刷新。
    const { clientX = 0 } = e.changedTouches[0], { startX = 0 } = pageData;
    let { activeNavIndex = 0, canSwitch = true, navList = [], freshDistance = 0 } = this.data;
    if (canSwitch){
      let distanceX = clientX - startX, direction = distanceX > 0 ? 'switchLeft' : (distanceX < 0 ? 'switchRight' : 'current');
      distanceX = Math.abs(distanceX);
      if (distanceX >= 20) {
        if (direction === 'current') {
          this.setData({ activeNavIndex });
        } else if (direction === 'switchLeft') {
          this.setData({ activeNavIndex: activeNavIndex ? activeNavIndex - 1 : activeNavIndex });
        } else if (direction === 'switchRight') {
          this.setData({ activeNavIndex: activeNavIndex === navList.length - 1 ? activeNavIndex : activeNavIndex + 1 });
        }
      } else {
        this.setData({ activeNavIndex });
      }
    }else{
      if (freshDistance < 20) {
        this.setData({ freshDistance: 0, canSwitch: true });
      } else {
        this.setData({ freshDistance: 20 }, () => {
          setTimeout(() => {
            Object.assign(navList[activeNavIndex], { isFresh: false, cardNum: 20 });
            this.setData({ freshDistance: 0, canSwitch: true, navList })
          }, 2000);
        });
      }
    }
  },
  touchCancel(e) {
  	//触摸结束时判断若此时左右滑动无失效时判断左右滑动方向来切花列表;失效时表明是上下滚动,同时若是下拉判断下拉距离达到刷新的距离时触发刷法模拟刷新。
    const { clientX = 0 } = e.changedTouches[0], { startX = 0 } = pageData;
    let { activeNavIndex = 0, canSwitch = true, navList = [], freshDistance = 0 } = this.data;
    if (canSwitch) {
      let distanceX = clientX - startX, direction = distanceX > 0 ? 'switchLeft' : (distanceX < 0 ? 'switchRight' : 'current');
      distanceX = Math.abs(distanceX);
      if (distanceX >= 20) {
        if (direction === 'current') {
          this.setData({ activeNavIndex });
        } else if (direction === 'switchLeft') {
          this.setData({ activeNavIndex: activeNavIndex ? activeNavIndex - 1 : activeNavIndex });
        } else if (direction === 'switchRight') {
          this.setData({ activeNavIndex: activeNavIndex === navList.length - 1 ? activeNavIndex : activeNavIndex + 1 });
        }
      } else {
        this.setData({ activeNavIndex });
      }
    } else {
      if (freshDistance < 20) {
        this.setData({ freshDistance: 0, canSwitch: true });
      } else {
        this.setData({ freshDistance: 20 }, () => {
          setTimeout(() => {
            Object.assign(navList[activeNavIndex], { isFresh: false, cardNum: 20 });
            this.setData({ freshDistance: 0, canSwitch: true, navList })
          }, 2000);
        });
      }
    }
  },
  //自定义下拉刷新
  listScroll(e) {
  	//列表滚动时使左右切换失效
    this.setData({ canSwitch: false });
  },
  bottomLoad(e){
  	//上拉加载更多数据
    let { activeNavIndex = 0, navList = [] } = this.data;
    Object.assign(navList[activeNavIndex], { showLoading: true, });
    this.setData({ navList }, () => {
      setTimeout(() => {
        Object.assign(navList[activeNavIndex], { showLoading: false, cardNum: navList[activeNavIndex].cardNum + 20 });
        this.setData({ navList });
      }, 2000);
    });
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/97014
推荐阅读
相关标签