RXSwift - RxCollectionViewSectionedReloadDataSource - 拖放移动(重新排序)



我已经使用RxCollectionViewSectionedReloadDataSource将我的数据加载到UICollectionView

let dataSource = RxCollectionViewSectionedReloadDataSource<SectionModel<String, WorkGroup>>(
configureCell: { (_, collectionView, indexPath, item) in
guard let cell = collectionView
.dequeueReusableCell(withReuseIdentifier: WorkGroupCell.identifier, for: indexPath) as? WorkGroupCell else {
return WorkGroupCell()
}
cell.viewModel = item
return cell
}
)

viewModel.items.bind(to: tileCollectonView.rx.items(dataSource: dataSource)).disposed(by: disposeBag)

tileCollectonView.rx.setDelegate(self).disposed(by: disposeBag)

使用上面的代码我可以显示数据。但是我想拖放(重新排序)单元格。

请告诉我如何使用RxSwift重新订购。

感谢您的帮助。

通常情况下,您需要状态机。

所涉及的逻辑很简单:

struct State<Item> {
var items: [Item] = []
}
func state<Item>(initialState: State<Item>, itemMoved: Observable<ItemMovedEvent>) -> Observable<State<Item>> {
itemMoved
.scan(into: initialState) { (state, itemMoved) in
state.items.move(from: itemMoved.sourceIndex.row, to: itemMoved.destinationIndex.row)
}
.startWith(initialState)
}
extension Array
{
mutating func move(from oldIndex: Index, to newIndex: Index) {
if oldIndex == newIndex { return }
if abs(newIndex - oldIndex) == 1 { return self.swapAt(oldIndex, newIndex) }
self.insert(self.remove(at: oldIndex), at: newIndex)
}
}

上面的代码使用RxCocoa为表视图提供的ItemMovedEvent。为了为集合视图创建类似的东西,您需要将UICollectionViewDragDelegate包装在委托代理中。一篇关于如何做到这一点的文章可以在这里找到:转换Swift委托到RxSwift Observables

所以我假设你使用的是RxDataSources

设置数据源变量后,还需要设置两个属性:canMoveItemAtIndexPathmoveItem

// in CollectionViewSectionedDataSource class
public typealias MoveItem = (CollectionViewSectionedDataSource<Section>, _ sourceIndexPath:IndexPath, _ destinationIndexPath:IndexPath) -> Void
public typealias CanMoveItemAtIndexPath = (CollectionViewSectionedDataSource<Section>, IndexPath) -> Bool
let dataSource = ...
dataSource.canMoveItemAtIndexPath = { dataSource, indexPath in
return true
}

dataSource.moveItem = {dataSource, source, destination in
...
}

和使用UICollectionView方法来开始/更新/结束交互。在我的例子中,我添加了长按手势来处理拖动

//in viewDidLoad
let startDragGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleDragging))
collectionView.addGestureRecognizer(startDragGesture)
...

@objc func handleDragging(gesture: UILongPressGestureRecognizer){
switch gesture.state {
case .began:
guard let indexPath = collectionView.indexPathForItem(at: gesture.location(in: collectionView)) else { return }

collectionView.beginInteractiveMovementForItem(at: indexPath)
case .changed:
collectionView.updateInteractiveMovementTargetPosition(gesture.location(in: collectionView))
case .ended:
collectionView.endInteractiveMovement()
default:
collectionView.cancelInteractiveMovement()
}
}

然后你可以拖动单元格

moveItem闭包中,您应该移动集合中的实际数据。

相关内容

  • 没有找到相关文章

最新更新