gpt4 book ai didi

ios - 使用 UICollectionViewFlowLayout 重新排列不同大小的 UICollectionView 项

转载 作者:行者123 更新时间:2023-12-01 17:35:48 38 4
gpt4 key购买 nike

假设我有一个带有 UICollectionViewFlowLayout 的 UICollectionView,并且我的项目大小不同。所以我已经实现了 collectionView(_:layout:sizeForItemAt:) .

现在假设我允许用户重新排列项目( collectionView(_:canMoveItemAt:) )。

问题就在这里。当一个单元格被拖动而其他单元格移开时,collectionView(_:layout:sizeForItemAt:)被反复调用。但它显然需要错误的索引路径:一个单元格的大小与它被视觉移动到的位置的索引路径有关。因此,当它穿梭到不同位置时,它在拖动过程中采用了错误的尺寸。

enter image description here

一旦拖动结束和collectionView(_:moveItemAt:to:)被调用,我更新数据模型并重新加载数据,所有单元格都假定它们的大小正确。该问题仅在拖动期间发生。

我们显然没有在 collectionView(_:layout:sizeForItemAt:) 中获得足够的信息知道在拖动过程中返回什么答案。或者我应该说,我们被要求提供错误索引路径的大小。

我的问题是:人们到底在做什么呢?

最佳答案

诀窍是实现

override func collectionView(_ collectionView: UICollectionView, 
targetIndexPathForMoveFromItemAt orig: IndexPath,
toProposedIndexPath prop: IndexPath) -> IndexPath {

在拖动过程中,该方法会被重复调用,但会出现一个单元格与另一个单元格交叉并且单元格被推开以进行补偿的时刻。那一刻, origprop有不同的值(value)观。因此,此时您需要根据单元格的移动方式修改所有尺寸。

为此,您需要在重新排列尺寸时模拟界面在单元格四处移动时的作用。运行时对此没有任何帮助!

这是一个简单的例子。假设用户只能在同一部分内移动单元格。并假设我们的数据模型看起来像这样,每个 Item 记住自己的大小一次 collectionView(_:layout:sizeForItemAt:)最初计算它:
struct Item {
var size : CGSize
// other stuff
}
struct Section {
var itemData : [Item]
// other stuff
}
var sections : [Section]!

方法如下 sizeForItemAt:将计算出的尺寸内存到模型中:
func collectionView(_ collectionView: UICollectionView, 
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let memosize = self.sections[indexPath.section].itemData[indexPath.row].size
if memosize != .zero {
return memosize
}
// no memoized size; calculate it now
// ... not shown ...
self.sections[indexPath.section].itemData[indexPath.row].size = sz // memoize
return sz
}

然后,当我们听到用户以一种使单元格移动的方式进行拖动时,我们读取了所有 size此部分的值,执行与界面相同的删除和插入操作,并放置重新排列的 size值回到模型中:
override func collectionView(_ collectionView: UICollectionView, 
targetIndexPathForMoveFromItemAt orig: IndexPath, toProposedIndexPath
prop: IndexPath) -> IndexPath {
if orig.section != prop.section {
return orig
}
if orig.item == prop.item {
return prop
}
// they are different, we're crossing a boundary - shift size values!
var sizes = self.sections[orig.section].rowData.map{$0.size}
let size = sizes.remove(at: orig.item)
sizes.insert(size, at:prop.item)
for (ix,size) in sizes.enumerated() {
self.sections[orig.section].rowData[ix].size = size
}
return prop
}

结果是 collectionView(_:layout:sizeForItemAt:)现在在拖动过程中给出正确的结果。

额外的难题是,当拖动开始时,您需要保存所有原始尺寸,当拖动结束时,您需要将它们全部恢复,以便拖动结束时结果也将是正确的。

关于ios - 使用 UICollectionViewFlowLayout 重新排列不同大小的 UICollectionView 项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51502528/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com