快速组合布局扩展单元会导致不需要的偏移滚动行为

问题描述 投票:0回答:1

我想使用组合布局创建扩展单元格。我面临的一个问题是,每次当我的单元格扩展时,我都会在扩展完成后立即发生这种不需要的偏移变化(将单元格向右移动)。对于我的一生,我不明白为什么它会滚动。从展开状态来看,屏幕左侧的空间并不是不够。所以我不确定是什么原因造成的,以及我们是否可以手动将其关闭。任何建议将不胜感激!

class ViewController: UIViewController, UICollectionViewDelegate {

lazy var collectionView: UICollectionView = {
    let collectionView = UICollectionView(frame: .zero, collectionViewLayout: createLayout())
    collectionView.translatesAutoresizingMaskIntoConstraints = false
    collectionView.delegate = self
    collectionView.contentInsetAdjustmentBehavior = .never
    collectionView.alwaysBounceVertical = true
    collectionView.alwaysBounceHorizontal = true
    return collectionView
}()

var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
var items = [Item]()

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(collectionView)
    setupCollectionViewDataSource()
    ...
}
   func setupCollectionViewDataSource() {
    dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView, cellProvider: { collectionView, indexPath, itemIdentifier in
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ProminentCell.cellId, for: indexPath) as! ProminentCell
        cell.backgroundColor = self.colors.randomElement()
        cell.numberLabel.text = String(indexPath.item)
        cell.delegate = self
        return cell
    })
    
    updateDataSource()
}

func createLayout() -> UICollectionViewLayout {
    let layout = UICollectionViewCompositionalLayout { sectionNumber, env in
        let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(325), heightDimension: .absolute(708))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: itemSize, subitems: [item])
        
        let section = NSCollectionLayoutSection(group: group)
        section.orthogonalScrollingBehavior = .continuous
        
        section.interGroupSpacing = 10
        return section
    }
    return layout
}

private func updateDataSource() {
    var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
    snapshot.appendSections([.carousel])
    snapshot.appendItems(items)
    dataSource.apply(snapshot, animatingDifferences: true, completion: nil)
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if let cell = collectionView.cellForItem(at: indexPath) as? ProminentCell {
        cell.currentState = .expanded
    }
}

func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
    guard let nextIndexPath = context.nextFocusedIndexPath, let prevIndexPath = context.previouslyFocusedIndexPath else { return }
    collectionView.isScrollEnabled = false
    collectionView.scrollToItem(at: nextIndexPath, at: .left, animated: true)
  }
}

extension ViewController: ProminentCellDelegate {
  func expandCell(cell: ProminentCell) {
    let snapshot = dataSource.snapshot()
    dataSource.apply(snapshot, animatingDifferences: true, completion: nil)
  }
}

细胞类

protocol ProminentCellDelegate: AnyObject {
    func expandCell(cell: ProminentCell)
    func collapseCell(cell: ProminentCell)
}

enum ProminentCellState {
    case collapsed, expanded
}

class ProminentCell: UICollectionViewCell {

 static let cellId = "cellId"
 weak var delegate: ProminentCellDelegate?

 var currentState: ProminentCellState {
     didSet {
         if currentState == .collapsed {
             collapseCell {}
         } else {
             expandCell(completion: {})
         }
     }
 }

 let imageStringName = ""

 lazy var backgroundImageView: UIImageView = {
    let imageView = UIImageView(image: UIImage(named: imageStringName))
    imageView.backgroundColor = .systemOrange
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.adjustsImageWhenAncestorFocused = true
    return imageView
}()

let numberLabel: UILabel = {
    let label = UILabel()
    ...
    return label
}()

private let expandedWidth = 1035.0
private let collapsedWidth = 325.0
private let animationDuration = 0.33

var closedConstraint: NSLayoutConstraint? = nil
var openConstraint: NSLayoutConstraint? = nil

override init(frame: CGRect) {
    currentState = .collapsed
    super.init(frame: frame)
    
    contentView.addSubview(backgroundImageView)
    contentView.addSubview(numberLabel)
    contentView.translatesAutoresizingMaskIntoConstraints = false

    let padding = 10.0
    NSLayoutConstraint.activate([
        contentView.topAnchor.constraint(equalTo: topAnchor),
        contentView.leadingAnchor.constraint(equalTo: leadingAnchor),
        contentView.trailingAnchor.constraint(equalTo: trailingAnchor),
        contentView.bottomAnchor.constraint(equalTo: bottomAnchor),
        backgroundImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: padding),
        backgroundImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: padding),
        backgroundImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -padding),
        backgroundImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -padding),
        
        numberLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
        numberLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
    ])
    
    closedConstraint = contentView.widthAnchor.constraint(equalToConstant: collapsedWidth)
    closedConstraint?.isActive = true
    openConstraint = contentView.widthAnchor.constraint(equalToConstant: expandedWidth)
}

private func expandCell(completion: () -> Void) {
    closedConstraint?.isActive = false
    openConstraint?.isActive = true
    
    let curFrame = frame.origin

    let expandedSize = CGRect(x: curFrame.x, y: curFrame.y, width: expandedWidth, height: frame.size.height)
    UIViewPropertyAnimator.runningPropertyAnimator(withDuration: animationDuration, delay: 0, options: [.curveLinear]) {
        self.frame = expandedSize
        self.layoutIfNeeded()
        self.contentView.layoutIfNeeded()
    }
    delegate?.expandCell(cell: self)
}

private func collapseCell(completion: () -> Void) {
    openConstraint?.isActive = false
    closedConstraint?.isActive = true

    let curFrame = frame.origin
    let collapsedSize = CGRect(x: curFrame.x, y: curFrame.y, width: collapsedWidth, height: frame.size.height)

    UIViewPropertyAnimator.runningPropertyAnimator(withDuration: animationDuration, delay: 0, options: [.beginFromCurrentState]) {
        self.frame = collapsedSize
        self.contentView.layoutIfNeeded()
        self.layoutIfNeeded()
    }
    
    delegate?.collapseCell(cell: self)
}
...

}

swift uicollectionview uicollectionviewcompositionallayout
1个回答
0
投票

解决方案是将正交滚动视图的 isScrollEnabled 设置为 false。这会删除滚动视图内容大小更改时发生的本机滚动动画。

© www.soinside.com 2019 - 2024. All rights reserved.