swift - 当调用此集合视图的 ReloadData 时,附加到 UICollectionView 中的单元格的弹出框移动
问题描述
我有一个用户可以单击的 UICollectionView,它显示了一个附加到单击的单元格的弹出框。在 iOS 12 中,无论是否调用了重新加载数据,弹出框都保持在同一原点(x、y 或单元格),但在 iOS 13 中,当调用集合视图的重新加载数据时,弹出框在单元格之间移动。
关注 iOS 13 中的行为视频: https ://vimeo.com/385021234
演示是使用以下代码完成的:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) else {
return
}
presentPopover(from: self, cell: cell)
}
func presentPopover(from view: UIViewController, cell: UIView) {
let popoverView = PopoverViewController(nibName: "PopoverViewController", bundle: nil)
let popover: UIPopoverPresentationController = popoverView.popoverPresentationController!
popover.sourceRect = cell.bounds
popover.sourceView = cell
view.present(popoverView, animated: true, completion: nil)
}
而 PopoverViewController 正在使用modalPresentationStyle = .popover
有人在 iOS 13 之前遇到过这个问题吗?我们的应用程序在 iOS 11 和 12 中运行良好。
我在以下 git 存储库中有此行为的示例:https ://github.com/diegossantos95/UICollectionViewPopoverBug
在存储库中重现的步骤:
单击集合单元格
弹出框打开
等待重新加载数据
谢谢,
迭戈。
解决方案
您可以使用从单元格的框架创建的临时 UIView,然后将弹出窗口附加到该单元格,而不是将弹出框附加到您可以保证不会出队的单元格。这是完成此操作的相关代码。
class ViewController: UIViewController {
var timer = Timer()
var popOverTempView = UIView()
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(reloadData), userInfo: nil, repeats: true)
self.collectionView.addSubview(popOverTempView)
popOverTempView.isHidden = true
popOverTempView.backgroundColor = .clear
}
}
extension ViewController: UICollectionViewDelegate {
func presentPopover(from view: UIViewController, cell: UIView) {
let popoverView = PopoverViewController(nibName: "PopoverViewController", bundle: nil)
let popover: UIPopoverPresentationController = popoverView.popoverPresentationController!
popoverView.delegate = self
popOverTempView.frame = cell.frame
popOverTempView.isHidden = false
popover.sourceRect = popOverTempView.bounds
popover.sourceView = popOverTempView
view.present(popoverView, animated: true, completion: nil)
}
}
extension ViewController: PopoverViewControllerDelegate {
func willDismissPopover() {
popOverTempView.isHidden = true
}
}
protocol PopoverViewControllerDelegate {
func willDismissPopover()
}
class PopoverViewController: UIViewController {
var delegate: PopoverViewControllerDelegate?
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
delegate?.willDismissPopover()
}
}
20 年 5 月 20 日更新:
我想我找到了一个更清洁更直接的解决方法。与其直接使用单元格的边界,不如将其 contentView 的框架转换为 collectionView 的坐标空间,然后将其用作 sourceRect 并从当前视图控制器的视图中呈现。
func presentPopover(from view: UIViewController, cell: UICollectionViewCell, indexPath: IndexPath) {
let popoverView = PopoverViewController(nibName: "PopoverViewController", bundle: nil)
let popover: UIPopoverPresentationController = popoverView.popoverPresentationController!
var rect = cell.convert(cell.contentView.frame, to: collectionView)
rect = collectionView.convert(rect, to: self.view)
popover.sourceRect = rect
popover.sourceView = self.view
view.present(popoverView, animated: true, completion: nil)
}
推荐阅读
- elasticsearch - Lucene/Solr 搜索文档创建
- c++ - 我不断收到 UE4 FPS 第 3.1 节教程的错误。我应该怎么办?
- python - 如何让 tkinter OptionMenu 显示所选选项的名称?
- excel - 如何知道 Windows 资源管理器预览窗格正在启动 VSTO Word 和 Excel 插件?
- python - 错误:您无权访问此服务器上的“url”。在美丽的汤
- reactjs - 不能在带有 Next.js 的模块外部使用 import 语句
- python - 将项目列表与短语匹配以隔离单词
- python - Maya:草生成器 python
- javascript - 在javascript中记录点击事件的请求和响应
- python - 用中值替换 DataFrame 中的错误值(由 2 个条件证明)。歧义错误