WXML部分
 1 <view class="index">
 2 
 3   <!-- 数据展示区 -->
 4   <scroll-view
 5     class="scroll-list" 
 6     scroll-y 
 7     style="height: {{windowHeight - bottomHeight}}px"
 8     bindscroll="bindscroll">
 9     <view class="scroll-item" wx:for="{{optionsList}}" wx:key="index">
10       <view>{{item.time}}</view>
11     </view>
12   </scroll-view>
13 
14   <!-- 页面可拖拽区域 -->
15   <view
16     wx:if='{{editting}}'
17     class="touchView" 
18     catchtouchstart="scrollTouchStart" 
19     catchtouchmove="scrollTouchMove" 
20     catchtouchend="scrollTouchEnd"
21     style="height: {{windowHeight - bottomHeight}}px">
22     </view>
23 
24   <!-- 页面拖拽处理区域 -->
25   <movable-area
26     wx:if='{{editting}}'
27     class="moveable_row"
28     style="height: {{windowHeight - bottomHeight}}px">
29         <movable-view  
30       class="moveable_item {{moveData ? 'show' : 'hide'}}" 
31       style="height: {{scrollItemHeight}}px;" 
32       direction="vertical" 
33       x="{{moveData.x}}" 
34       y="{{moveData.y}}" 
35       inertia="false" 
36       damping="9999"
37       friction="9999"
38     >
39       <view class="scroll-item moving" hidden='{{!moveData}}'>
40         <view>{{selectItem.time}}</view>
41       </view>
42         </movable-view>
43     </movable-area>
44 
45   <!-- 底部栏 -->
46   <view class="index-bottom">
47     <button type="primary" wx:if='{{!editting}}' bindtap="changeEditing">编辑</button>
48     <button type="warn" wx:else bindtap="changeEditing">取消</button>
49   </view>
50 
51 </view>
 
WXSS部分
 1 .index {
 2   position: relative;
 3 }
 4 
 5 /* 数据展示区 */
 6 .scroll-list{
 7   width: 100%;
 8 }
 9 .scroll-item {
10   width: 100%;
11   padding: 10rpx 20rpx;
12   box-sizing: border-box;
13   border: 1px solid #999;
14 }
15 .scroll-item.moving {
16   border: 1px dashed blue;
17 }
18 
19 /* 页面可拖拽区域 */
20 .touchView {
21   width: 100%;
22   position: absolute;
23   left: 0;
24   top: 0;
25   z-index: 1;
26 }
27 
28 /* 页面拖拽处理区域 */
29 .moveable_row {
30   width: 100%;
31   position: absolute;
32   left: 0;
33   top: 0;
34 }
35 .moveable_item {
36   width: 100%;
37 }
38 .moveable_item.show {
39   background: #fff;
40 }
41 .moveable_item.hide {
42   background: transparent;
43 }
44 
45 
46 /* 底部栏 */
47 .index-bottom {
48   width: 100%;
49   display: flex;
50   justify-content: flex-end;
51   padding: 10rpx 20rpx;
52   box-sizing: border-box;
53 }
 
js部分  
  1 Page({
  2     data:{
  3         optionsList: [],      // 数据源
  4     windowHeight: 0,      // 屏幕高度
  5     scrollItemHeight: 0,  // 列表单项高度
  6     bottomHeight: 0,      // 底部按钮高度
  7     selectItem: {},       // 当前选中元素
  8     selectIndex: 0,       // 当前选中索引
  9     editting: true,      // 是否是“编辑”状态
 10     moveData: null,       // 列表项移动时记录移动位置
 11     scrollTop: 0          // scroll-view距离顶部距离
 12     },
 13     // 初始化页面数据
 14   init() {
 15     this.setData({
 16       optionsList: [{time: '12:00'}, {time: '13:00'}, {time: '14:00'}, {time: '15:00'}, {time: '16:00'}, {time: '17:00'}, {time: '18:00'}, {time: '19:00'}, {time: '20:00'}, {time: '21:00'}, {time: '22:00'}, {time: '23:00'}, {time: '24:00'}, {time: '25:00'}, {time: '26:00'}, {time: '27:00'}, {time: '28:00'}, {time: '29:00'}, {time: '30:00'}, {time: '31:00'}, {time: '32:00'}, {time: '33:00'}, {time: '34:00'}, {time: '35:00'}],
 17       windowHeight: wx.getSystemInfoSync().windowHeight
 18     }, () => {
 19       wx.createSelectorQuery().select('.index-bottom').boundingClientRect(res => {
 20         this.setData({
 21           bottomHeight: res.height
 22         })
 23       }).exec()
 24       wx.createSelectorQuery().select('.scroll-item').boundingClientRect(res => {
 25         this.setData({
 26           scrollItemHeight: res.height
 27         })
 28       }).exec()
 29     });
 30   },
 31 
 32   // 开始拖拽
 33   scrollTouchStart(event) {
 34     const { scrollItemHeight } = this.data
 35     const firstTouchPosition = {
 36       x: event.changedTouches[0].pageX,
 37       y: event.changedTouches[0].pageY,
 38     }
 39     const { data, index } = this.getPositionDomByXY(firstTouchPosition);
 40     this.setData({
 41       moveData:{
 42         x: 0,
 43         y: firstTouchPosition.y - scrollItemHeight / 2
 44       },
 45       selectItem: data,
 46       selectIndex: index
 47     })
 48 
 49   },
 50 
 51   // 拖拽ing...
 52   scrollTouchMove(event) {
 53     const { scrollItemHeight } = this.data
 54     this.setData({
 55       moveData:{
 56         x: 0,
 57         y: event.changedTouches[0].pageY - scrollItemHeight / 2
 58       },
 59     })
 60 
 61   },
 62 
 63   // 拖拽结束
 64   scrollTouchEnd:function (event) {
 65     const { selectIndex, optionsList } = this.data
 66     const endTouchPosition = {
 67       x: event.changedTouches[0].pageX,
 68       y: event.changedTouches[0].pageY,
 69     }
 70     const { index } = this.getPositionDomByXY(endTouchPosition)
 71     // 交换顺序
 72     const temp = optionsList[selectIndex]
 73     optionsList[selectIndex] = optionsList[index]
 74     optionsList[index] = temp
 75     this.setData({
 76       optionsList,
 77       moveData: null
 78     })
 79   },
 80 
 81   // 根据(x,y)坐标轴获取页面元素
 82   getPositionDomByXY(potions) {
 83     const { scrollItemHeight, optionsList, scrollTop } = this.data
 84     const y = potions.y + scrollTop;
 85     const len = optionsList.length
 86     for(let i = 0; i < len; i++){
 87       if(y >= i*scrollItemHeight && y < (i+1)*scrollItemHeight){
 88         // 返回匹配到的数据项
 89         return {
 90           data: optionsList[i],
 91           index: i
 92         };
 93       }
 94     }
 95     return y > (len-1)*scrollItemHeight ? {
 96       // 匹配项位于列表之下
 97       data: optionsList[len - 1],
 98       index: len - 1
 99     } : {
100       // 匹配项位于列表之上
101       data: optionsList[0],
102       index: 0
103     }
104   },
105 
106   // 切换编辑状态
107   changeEditing() {
108     const { editting } = this.data
109     this.setData({ editting: !editting })
110   },
111 
112   // 监听滚动事件
113   bindscroll(e) {
114     this.data.scrollTop = e.detail.scrollTop
115   },
116   onLoad: function () {
117     this.init()
118   },
119 });