在布局更改的同时重新加载/动画 UICollectionView

2024-04-07

这个问题 https://stackoverflow.com/questions/40680588/uicollectionviewcell-contents-do-not-animate-alongside-cells-contentview(及其答案)已经让我实现了我想要的一半。

但现在我陷入了下一部分,(老实说)我什至不确定这是否可能。

我已经像这样定义了一个单元格......

class ExpandableCell: UICollectionViewCell {

    var priority: Expandable.Priority = .low {
        didSet {
            imageView.isHidden = priority != .high
        }
    }

    private let imageView: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .red
        v.heightAnchor.constraint(equalTo: v.widthAnchor).isActive = true
        return v
    }()

    private let label: UILabel = {
        let l = UILabel()
        l.translatesAutoresizingMaskIntoConstraints = false
        l.font = UIFont.preferredFont(forTextStyle: .headline)
        l.numberOfLines = 0
        l.text = "Tap Me!"
        l.setContentCompressionResistancePriority(.required, for: .vertical)
        l.adjustsFontForContentSizeCategory = true
        l.textAlignment = .center
        return l
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)

        let labelStack: UIStackView = {
            let s = UIStackView(arrangedSubviews: [label])
            s.translatesAutoresizingMaskIntoConstraints = false
            s.axis = .vertical
            s.alignment = .center
            s.distribution = .equalCentering
            s.isLayoutMarginsRelativeArrangement = true
            return s
        }()

        let stackView: UIStackView = {
            let s = UIStackView(arrangedSubviews: [imageView, labelStack])
            s.translatesAutoresizingMaskIntoConstraints = false
            s.axis = .horizontal
            s.spacing = 10
            s.layoutMargins = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
            s.alignment = .fill
            s.distribution = .fill
            s.isLayoutMarginsRelativeArrangement = true
            return s
        }()

        addSubview(stackView)

        NSLayoutConstraint.activate([
            stackView.topAnchor.constraint(equalTo: topAnchor),
            stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
            stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
            ])

        clipsToBounds = true

        backgroundColor = UIColor.init(white: 0.8, alpha: 1.0)

        layer.cornerRadius = 6
    }

    func display(button: DigestButton) {
        label.text = button.title
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
        super.apply(layoutAttributes)
        layoutIfNeeded()
    }
}

它具有由优先级设置的三种可能的状态(小、中或大)。

我正在更新集合视图的布局,以根据数据中存储的优先级更新大小。

它的工作原理是这样的......

正如您从这段代码中看到的......

var priority: Expandable.Priority = .low {
    didSet {
        imageView.isHidden = priority != .high
    }
}

更新优先级将显示/隐藏单元格中的“imageView”。这只是一个标准UIView出于概念证明的目的。

但它只是显示/隐藏imageView布局完成更新后。

根据链接的问题,我正在使用代码更新事物的布局......

collectionView.performBatchUpdates(nil) { _ in
    // completion block
    collectionView.reloadItems(at: changedIndexPaths)
}

我正在完成块中重新加载已更改单元格的数据。 (因此动画完成后进行更新)。

如果我像这样移动它...

collectionView.performBatchUpdates({
    collectionView.reloadItems(at: changedIndexPaths)
}) { _ in
    // completion block
}

然后动画就变成这样了……

...这比我开始时更糟糕。

有没有办法使细胞状态的变化动画化?理想情况下,我希望图像视图的动画速度与布局动画相同。

如果我不改变单元内的东西,那么这不是问题。但在某些情况下,我会想要改变单元内的内容,并且我希望无论哪种方式都能顺利过渡。


好吧...我在这里添加这个作为初步答案,但我想我刚刚破解了它。

诀窍是通过以下方式将布局动画期间所需的任何信息传递到单元格中:UICollectionViewLayoutAttributes.

从文档中可以看出,您可以对布局属性进行子类化,以在其中添加布局所需的附加信息。

通过把priority将信息添加到布局属性中,我现在可以在单元格移动和调整大小的同时对进入视图的图像视图进行动画处理。

Boom! :D

好的...像这样子类化 UICollectionViewLayoutAttributes...

fileprivate class PriorityLayoutAttributes: UICollectionViewLayoutAttributes {
    var priority: DigestExpandable.Priority? = nil

    override func copy(with zone: NSZone? = nil) -> Any {
        let copy = super.copy(with: zone) as! PriorityLayoutAttributes
        copy.priority = self.priority
        return copy
    }

    override func isEqual(_ object: Any?) -> Bool {
        guard let rhs = object as? PriorityLayoutAttributes else {
            return false
        }

        return super.isEqual(rhs) && priority == rhs.priority
    }
}

...然后将这些属性用于这个特定的单元格。

在单元格中我更新了apply(_)像这样的功能...

override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
    super.apply(layoutAttributes)

    if let attributes = layoutAttributes as? PriorityLayoutAttributes,
        let priority = attributes.priority {
        self.priority = priority
    }

    layoutIfNeeded()
}

现在它可以正常工作并且动画精美了:D

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在布局更改的同时重新加载/动画 UICollectionView 的相关文章

  • 选择 UITableViewCell 时 UIView 背景颜色消失

    我在界面生成器中构建了一个简单的 tableViewCell 它包含一个包含图像的 UIView 现在 当我选择单元格时 会显示默认的蓝色选择背景 但 UIView 的背景颜色消失了 我的 UITableViewCell 的实现文件没有做任
  • iOS uiwebview 在 WebThread 中崩溃

    我正在寻求一些建议或帮助诊断我所看到的这次崩溃 目前 我认为这可能是一个 webkit 错误 但一切皆有可能 因此请提供您可能有的任何见解 Incident Identifier AEB8EE37 E5D4 4975 97F4 2B2038
  • 如何区分 iTunes Connect / Apple TestFlight 上的 STAGE 和 PRODUCTION 版本?

    阶段构建与阶段服务器的对话 阶段服务器与生产服务器尽可能相同 以用于测试目的 生产构建与生产服务器的通信 生产服务器存储真实的关键数据 这些构建本质上是针对同一应用程序的 但是 iTunes Connect 界面将向您显示以下内容 即构建由
  • SceneKit unproject Z 文档解释?

    我正在经历一些 SceneKit 概念 而我试图在脑海中巩固的一个概念是 unprojectPoint 我知道该函数将获取 2D 中的一个点并返回 3D 中的一个点 因此具有正确的 Z 值 当我阅读文档时 我读到了以下内容 method u
  • 为具有多个目标和不同平台的项目编写 Podfile

    我正在准备一个支持 OS X 和 iOS 的 Pod 我的 pod 有一些自己的依赖项 这些依赖项在 podspec 文件中定义 因此我使用 Podfile 来管理我用来开发 pod 和运行测试的项目的依赖项 我正在使用 CocoaPods
  • Swift:检查 UISearchBar.text 是否包含 url

    如何检查 UISearchBar text 是否包含 URL 我想做这样的事情 if searchBar text NSTextCheckingType Link 但我收到错误 String is not convertible to NS
  • 在 ios 版 Ionic 中接收 URL

    我正在使用离子框架 我正在尝试设置一种从另一个应用程序接收网址的方法 就像 您在浏览器中 单击共享 然后将链接发送到另一个应用程序 我的应用程序 我找到了这个cordova https stackoverflow com questions
  • 在 UITableViewController 中重新排序行后 UI 更新不正确

    因此 我对表中的行重新排序 用户界面最终结果不正确 场景如下 表内容原文 a b c d e 如果我移动第 0 行 当前a 到第 4 行 当前e 我看到的最终结果是 c d e a a 一些背景 该表正在读取 Realm 对象的列表 我确认
  • 带约束的嵌套集合视图的意外行为 (Swift 4)

    我的表格视图中有一个单元格 其中包含水平分页集合视图 该集合视图的每个页面内都有一个垂直集合视图 为了避免 滚动滚动 问题 我在垂直集合视图中禁用了垂直滚动 垂直集合视图的单元格计数不是静态的 可以是任意数字 因此 这会产生一个问题 集合视
  • NSURLCache 不缓存

    我正在使用 Xcode 6 1 6A1030 iOS7 和 iOS8 模拟器 NSURLCache 似乎没有缓存任何东西 我使用 Cache Control 标头 我的服务器返回带有 max age 6000 的 Cache Control
  • 访问 google reader 的 Endpoints API 时出错

    我正在尝试在iPhone APP中实现google reader 到目前为止我已经成功收到了sid and auth 当我尝试使用以下命令调用 Endpoints API 时 问题就出现了GET 这是代码 ASIHTTPRequest re
  • 使用 BGTaskScheduler 进行后台获取与调试模拟完美配合,但在实践中却不起作用

    我在 appDelegate 的 didFinishLaunchingWithOptions 中注册后台获取任务 BGTaskScheduler shared register forTaskWithIdentifier Backgroun
  • 在 Swift 中以编程方式为 iOS 制作带有名字首字母的图像,例如 Gmail

    我需要在 UITableView 中显示与其姓名相对应的每个用户的个人资料图片 在下载图像之前 我需要显示一张带有他名字的第一个字母的图像 就像在 GMail 应用程序中一样 如何在 Swift for iOS 中以编程方式执行此操作 不需
  • XCode 7 中的 AWSS3TransferManagerUploadRequest

    我今天升级到 Xcode 7 Swift 2 0 我的项目正在使用 CocoaPods 我正在 POD 文件中导入所有与 AWS 相关的文件 我已经设置了桥接标头 并导入了 Amazon 告诉我的所有文件 在升级到 Swift 2 0 之前
  • iOS Swift 和 reloadRowsAtIndexPaths 编译错误

    我与 xCode Swift 陷入僵局并刷新 UITableView 的单行 这条线有效 self tableView reloadData 而这条线没有 self tableView reloadRowsAtIndexPaths curr
  • 子类 PFObject 上的 PFUser 属性

    我使用以下类 动态属性以及 m 文件中的 load 和 parseClassName 方法 对 PFObject 进行了子类化 interface DAOpponents PFObject
  • 检查 Swift 中关联类型是否符合协议

    在类似情况下 如何检查对象是否符合 可表示 协议 protocol Representable associatedtype RepresentType var representType RepresentType get set cla
  • 领域:结果 和列表

    是否可以转换Results
  • WKWebview 中的 iCLoud 文档选择器关闭容器视图

    我有一个 WKWebview 加载基于 Web 的 UI 我希望用户能够从其 iCloud 文档上传文件 我已授予正确的权限 并且可以浏览 iCloud 文档 但是 当我选择文件或单击取消按钮时 文档选择器视图也会关闭 WKWebview
  • 无需越狱即可检测iOS9上哪个应用程序处于前台

    我正在尝试记录用户在 iOS9 上的个人应用程序使用情况 我宁愿它不会使用越狱有限的解决方案 不言自明 在越狱手机上执行此应用程序的变体应该不难 https www andyibanez com create mobilesubstrate

随机推荐