之前在网上搜索拖拽列表的实现时,发现了有好多的方法都是基于像素位置的计算实现的,这种方法要求列表元素的大小以及列表的位置有着非常严格的要求,修改和拓展起来非常的麻烦。于是我自己动手实现了一个基于页面元素定位的实现,这种方法只需要每行的高度,拓展和应用到自己的小程序里非常的简单。
实现效果
JS
Page({
/**
* 页面的初始数据
*/
data: {
optionList: [],
movableViewInfo: {
y: 0,
showClass: 'none',
data: {}
},
pageInfo: {
rowHeight: 47,
scrollHeight: 85,
startIndex: null,
scrollY: true,
readyPlaceIndex: null,
startY: 0,
selectedIndex: null,
}
},
dragStart: function (event) {
var startIndex = event.target.dataset.index
console.log('获取到的元素为', this.data.optionList[startIndex])
// 初始化页面数据
var pageInfo = this.data.pageInfo
pageInfo.startY = event.touches[0].clientY
pageInfo.readyPlaceIndex = startIndex
pageInfo.selectedIndex = startIndex
pageInfo.scrollY = false
pageInfo.startIndex = startIndex
this.setData({
'movableViewInfo.y': pageInfo.startY - (pageInfo.rowHeight / 2)
})
// 初始化拖动控件数据
var movableViewInfo = this.data.movableViewInfo
movableViewInfo.data = this.data.optionList[startIndex]
movableViewInfo.showClass = "inline"
this.setData({
movableViewInfo: movableViewInfo,
pageInfo: pageInfo
})
},
dragMove: function (event) {
var optionList = this.data.optionList
var pageInfo = this.data.pageInfo
// 计算拖拽距离
var movableViewInfo = this.data.movableViewInfo
var movedDistance = event.touches[0].clientY - pageInfo.startY
movableViewInfo.y = pageInfo.startY - (pageInfo.rowHeight / 2) + movedDistance
console.log('移动的距离为', movedDistance)
// 修改预计放置位置
var movedIndex = parseInt(movedDistance / pageInfo.rowHeight)
var readyPlaceIndex = pageInfo.startIndex + movedIndex
if (readyPlaceIndex < 0 ) {
readyPlaceIndex = 0
}
else if (readyPlaceIndex >= optionList.length){
readyPlaceIndex = optionList.length - 1
}
if (readyPlaceIndex != pageInfo.selectedIndex ) {
var selectedData = optionList[pageInfo.selectedIndex]
optionList.splice(pageInfo.selectedIndex, 1)
optionList.splice(readyPlaceIndex, 0, selectedData)
pageInfo.selectedIndex = readyPlaceIndex
}
// 移动movableView
pageInfo.readyPlaceIndex = readyPlaceIndex
// console.log('移动到了索引', readyPlaceIndex, '选项为', optionList[readyPlaceIndex])
this.setData({
movableViewInfo: movableViewInfo,
optionList: optionList,
pageInfo: pageInfo
})
},
dragEnd: function (event) {
// 重置页面数据
var pageInfo = this.data.pageInfo
pageInfo.readyPlaceIndex = null
pageInfo.startY = null
pageInfo.selectedIndex = null
pageInfo.startIndex = null
pageInfo.scrollY = true
// 隐藏movableView
var movableViewInfo = this.data.movableViewInfo
movableViewInfo.showClass = 'none'
this.setData({
pageInfo: pageInfo,
movableViewInfo: movableViewInfo
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var optionList = [
"段落1 内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容",
"段落2 内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容",
"段落3 内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容",
"段落4 内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容",
"段落5 内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容",
"段落6 内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容",
"段落7 内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容",
"段落8 内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容",
"段落9 内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
]
this.setData({
optionList: optionList
})
},
})
WXML
<view class='zhuti'>
<view class='row title-row' style='height: {{pageInfo.rowHeight}}px;'>
<view class="col1">信息</view>
<view class="col2">详情</view>
<view class="col3">排序</view>
</view>
<movable-area class='movable-area'
style='display:{{movableViewInfo.showClass}}; height:{{pageInfo.scrollHeight}}%;'>
<movable-view class='row list-row movable-row'
out-of-bounds='true'
damping='999'
style='height:{{pageInfo.rowHeight}}px;'
direction="vertical"
y="{{movableViewInfo.y}}">
<view class='col1 content' >{{movableViewInfo.data}}</view>
<view class="col2" >
<icon type='info' color='Gray' size='22' />
</view>
<view class="col3" >
<icon type='download' color='Gray' size='25' />
</view>
</movable-view>
</movable-area>
<scroll-view scroll-y='{{pageInfo.scrollY}}' style='height: {{pageInfo.scrollHeight}}%'>
<block wx:for='{{optionList}}'>
<view class='row list-row {{pageInfo.readyPlaceIndex == index ? "ready-place" : ""}}' style='height: {{pageInfo.rowHeight}}px;'>
<view class='col1 content' >{{item}}</view>
<view class="col2" >
<icon type='info' color='Gray' size='22'
data-index='{{index}}'
bindtap='showDetail'
/>
</view>
<view class="col3" >
<icon type='download' color='Gray' size='25'
data-index='{{index}}'
bindtouchstart='dragStart'
bindtouchmove='dragMove'
bindtouchend='dragEnd'
/>
</view>
</view>
</block>
</scroll-view>
</view>
WXSS
page {
height: 100%;
width: 100%;
}
.zhuti {
height: 100%;
width: 100%;
position: relative;
}
.row {
height: 47px;
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
}
.title-row {
border-bottom: 1px solid #888888;
color: #888888;
}
.list-row {
padding: 8px 0px;
border-bottom: 1px solid #D9D9D9;
background-color: white;
}
.movable-area {
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
}
.movable-row {
box-shadow: #D9D9D9 0px 0px 20px;
}
.col1 {
width: 60%;
}
.col2 {
width: 10%;
}
.col3 {
width: 10%;
}
.ready-place {
background-color: #CCCCCC
}
.content {
font-size: 17px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
作者:HoPGoldy