gpt4 book ai didi

ios - 像这样的 CollectionView 堆叠单元格如何像钱包一样重叠单元格

转载 作者:行者123 更新时间:2023-12-01 19:31:30 26 4
gpt4 key购买 nike

我想要确切地当点击特定单元格时它会显示展开
enter image description here

let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = -UIScreen.main.bounds.width/2.08
我要扩展单元格?
friend 们任何对我们有帮助的建议和需求
谢谢

最佳答案

通常我们使用UICollectionViewFlowLayout ,一旦给定了项目的大小和间距,项目的框架就确定下来了。
待办事项

CollectionView stacked Cell for Overlapping Cell Like Wallet


您需要为 UICollectionView 中的每个项目提供所需的框架.
通过自定义 UICollectionViewLayout 来完成它, 并使用您自己的 UICollectionViewLayout子类。
最终效果如下图
11
基本的东西:
做自定义布局很容易:
  • override public func prepare() ,

  • 计算每个项目的框架,
    并将项目的框架放入其容器中,您的自定义 UICollectionViewLayoutAttributes
  • override public func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? ,

  • Retrieves layout information for an item at the specified index path with a corresponding cell.


    分配您准备好的自定义 UICollectionViewLayoutAttributes用于项目布局
  • override public func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? ,

  • Retrieves the layout attributes for all of the cells and views in the specified rectangle.


    在这种情况下没有补充 View 和装饰 View ,只是为了处理项目。
    分配您准备好的自定义 UICollectionViewLayoutAttributes对于 UICollectionView布局
    关键:
    你有两种布局状态。
  • 初始状态,和未选择状态相同,当没有选择卡时。

  • 222
    前一张牌部分隐藏,最后一张牌完全显示。
    定制 UICollectionViewLayoutAttributes , 与 isExpand记录是否选择了单元格。 isExpand用于添加的单元格 UIPanGestureRecognizer
    class CardLayoutAttributes: UICollectionViewLayoutAttributes {
    var isExpand = false

    override func copy(with zone: NSZone? = nil) -> Any {
    let attribute = super.copy(with: zone) as! CardLayoutAttributes
    attribute.isExpand = isExpand
    return attribute
    }
    }
    未选择状态的框架计算很容易。
    设置第一项的框架,
    然后第二个... y: titleHeight * CGFloat(index) , 一切都好
     fileprivate func setNoSelect(attribute:CardLayoutAttributes) {
    guard let collection = collectionView else {
    return
    }
    let noneIdx = Int(collection.contentOffset.y/titleHeight)
    if noneIdx < 0 {
    return
    }
    attribute.isExpand = false
    let index = attribute.zIndex
    var currentFrame = CGRect(x: collection.frame.origin.x, y: titleHeight * CGFloat(index), width: cellSize.width, height: cellSize.height)
    if index == noneIdx{
    attribute.frame = CGRect(x: currentFrame.origin.x, y: collection.contentOffset.y, width: cellSize.width, height: cellSize.height)
    }
    else if index <= noneIdx, currentFrame.maxY > collection.contentOffset.y{
    currentFrame.origin.y -= (currentFrame.maxY - collection.contentOffset.y )
    attribute.frame = currentFrame
    }
    else {
    attribute.frame = currentFrame
    }
    }
  • 选中状态,选中一个item,item被展开,其他人会为它腾出空间。

  • 逻辑是把选中的项放在中间, y职位很重要, collection.contentOffset.y + offsetSelected,中心项的框架是已知的,然后计算两侧。
    一侧是来自 (selectedIdx-1) 的项目为0,计算item的frame。
    另一面是来自 (selectedIdx+1) 的项目到最终索引,还要计算项目的框架。
        fileprivate func calculate(for attributes: [CardLayoutAttributes],  choose selectedIP: IndexPath) -> [CGRect]{

    guard let collection = collectionView else {
    return []
    }
    let noneIdx = Int(collection.contentOffset.y / titleHeight)
    if noneIdx < 0 {
    return []
    }
    let x = collection.frame.origin.x

    var selectedIdx = 0
    for attr in attributes{
    if attr.indexPath == selectedIP{
    break
    }
    selectedIdx += 1
    }

    var frames = [CGRect](repeating: .zero, count: attributes.count)

    // Edit here
    let offsetSelected: CGFloat = 100
    let marginBottomSelected: CGFloat = 10
    frames[selectedIdx] = CGRect(x: x, y: collection.contentOffset.y + offsetSelected, width: cellSize.width, height: cellSize.height)
    if selectedIdx > 0{
    for i in 0...(selectedIdx-1){
    frames[selectedIdx - i - 1] = CGRect(x: x, y: frames[selectedIdx].origin.y - titleHeight * CGFloat(i + 1), width: cellSize.width, height: cellSize.height)
    }
    }
    if selectedIdx < (attributes.count - 1){
    for i in (selectedIdx + 1)...(attributes.count - 1){
    frames[i] = CGRect(x: x, y: frames[selectedIdx].origin.y + marginBottomSelected + titleHeight * CGFloat(i - selectedIdx - 1) + cellSize.height, width: cellSize.width, height: cellSize.height)
    }
    }


    return frames

    }
    9999
  • 选择项目后,您应该刷新自定义布局。

  • 调用 invalidateLayout() ,

    Invalidates the current layout and triggers a layout update.

        fileprivate var _selectPath: IndexPath? {
    didSet {
    self.collectionView!.isScrollEnabled = (_selectPath == nil)
    }
    }



    public var selectPath: IndexPath? {
    set {
    _selectPath = (_selectPath == newValue) ? nil : newValue
    self.collectionView?.performBatchUpdates({
    self.invalidateLayout()
    }, completion: nil)
    } get {
    return _selectPath
    }
    }
    还有一件事, the sample demo in github

    关于ios - 像这样的 CollectionView 堆叠单元格如何像钱包一样重叠单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62540491/

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