OGeek|极客世界-中国程序员成长平台

标题: ios - 如何获得类似于 AirBNB iOS App 上的 UIScroll 效果,如下图所示 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-11 19:13
标题: ios - 如何获得类似于 AirBNB iOS App 上的 UIScroll 效果,如下图所示

我需要能够应用类似于 iOS AirBNB 中的滚动效果,当您滚动 UI Collection View 单元格图像时,该效果会突出显示

我无法进行滚动,也无法停止并选择一个单元格。

iOS AirBNB App Collection View Scroll

到目前为止我做了什么:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let itemsPerRow:CGFloat = 2.3
    let hardCodedPadding:CGFloat = 15
    let itemWidth = (collectionView.bounds.width / itemsPerRow) - hardCodedPadding
    let itemHeight = collectionView.bounds.height - (2 * hardCodedPadding)
    return CGSize(width: itemWidth, height: itemHeight)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    let indexPath = IndexPath(row: collectionView.indexPathsForVisibleItems[0].row, section: 0)
    
    collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.left, animated: true)
    (collectionView.cellForItem(at: indexPath) as! productImageCell).productImage.layer.borderWidth = 5
    
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let cellWidth = (collectionView.bounds.width / 3)
    return UIEdgeInsetsMake(0, 5 , 0, cellWidth/3)
}



Best Answer-推荐答案


你要做的第一件事是使用UICollectionViewDelegateUICollectionViewDataSourceUICollectionViewDelegateFlowLayout,你还应该创建一些重要的变量

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    // Used to calculate the position after the user end dragging
    var cellWidth: CGFloat? 

    // Used to set the layout for the collectionView
    var layout: UICollectionViewFlowLayout? 

    // The collection view
    var collectionView: UICollectionView?
}

接下来,您将创建实例化布局和 Collection View ,设置一些参数,将 Collection View 添加到 View 中,最后注册我们的单元格类。这可以在您的 viewDidLoad() 方法中完成:

override func viewDidLoad() {
    super.viewDidLoad()

    // You can change the width of the cell for whatever you want
    cellWidth = view.frame.width*0.5

    // instantiate the layout, set it to horizontal and the minimum line spacing
    layout = UICollectionViewFlowLayout()
    layout?.scrollDirection = .horizontal
    layout?.minimumLineSpacing = 0 // You can also set to whatever you want

    let cv = UICollectionView(frame: self.view.frame, collectionViewLayout: layout!)
    cv.backgroundColor = .green
    cv.delegate = self
    cv.dataSource = self
    collectionView = cv
    collectionView?.allowsSelection = true

    guard let collectionView = collectionView else {
        return
    }

    // Add to subview
    view.addSubview(collectionView)

    // Set auto layout constraints
    collectionView.translatesAutoresizingMaskIntoConstraints = false
    collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    collectionView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    collectionView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true

    // Register cell class
    collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: "cell")

}

ViewController 中要做的最后一件事是在用户端拖动后选择正确的单元格,您将使用 scrollViewWillEndDragging(...)方法:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    guard let cellWidth = cellWidth else {
        return
    }

    var cellNumber = 0
    let offsetByCell = targetContentOffset.pointee.x/cellWidth

    // If the user drag just a little, the scroll view will go to the next cell
    if offsetByCell > offsetByCell + 0.2 {
        cellNumber = Int(ceilf(Float(offsetByCell)))
    } else {
        cellNumber = Int(floorf(Float(offsetByCell)))
    }

    // Avoiding index out of range exception
    if cellNumber < 0 {
        cellNumber = 0
    }

    // Avoiding index out of range exception
    if cellNumber >= (collectionView?.numberOfItems(inSection: 0))! {
        cellNumber = (collectionView?.numberOfItems(inSection: 0))! - 1
    }

    // Move to the right position by using the cell width, cell number and considering the minimum line spacing between cells
    targetContentOffset.pointee.x = cellWidth * CGFloat(cellNumber) + (CGFloat(cellNumber) * (layout?.minimumLineSpacing)!)

    // Scroll and select the correct item
    let indexPath = IndexPath(item: cellNumber, section: 0)
    collectionView?.scrollToItem(at: indexPath, at: .left, animated: true)
    collectionView?.selectItem(at: indexPath, animated: true, scrollPosition: .left)
}

这是您必须在 View Controller 中设置的所有内容。

最后,您在代码中要做的最后一件事是转到您的自定义单元格(在我的例子中为 MyCollectionViewCell)并向 selected 添加一个观察者属性,在我的类(class)中,我只是更改所选单元格的背景颜色,但您可以放置​​任何您想要的逻辑:

import UIKit

class MyCollectionViewCell: UICollectionViewCell {

    override var isSelected: Bool {
        didSet {
            backgroundColor = isSelected ? UIColor.blue : UIColor.white
        }
    }

    override init (frame: CGRect){
        super.init(frame: frame)
        backgroundColor = .white

    }

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

}

希望它可以帮助您完成所需的工作。

关于ios - 如何获得类似于 AirBNB iOS App 上的 UIScroll 效果,如下图所示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42731123/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://ogeek.cn/) Powered by Discuz! X3.4