ios UICollectionView 自定义单元格在 Swift 中填充宽度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29986379/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 05:50:54  来源:igfitidea点击:

UICollectionView Custom Cell to fill width In Swift

iosswiftuicollectionviewuicollectionviewlayout

提问by AaoIi

I've been trying to figure-out how can i make the cell fill the width, as you can see in the picture the width between the cells is too big. i am using custom cell with only one imageView.

我一直在试图弄清楚如何让单元格填充宽度,正如您在图片中看到的那样,单元格之间的宽度太大。我正在使用只有一个 imageView 的自定义单元格。

enter image description here

enter image description here

I tried to customize it from the storyboard but i guess there is no option for that or it should be done programmatically. enter image description here

我试图从情节提要中自定义它,但我想没有选择,或者应该以编程方式完成。 enter image description here

my UICollectionViewController :

我的 UICollectionViewController :

 @IBOutlet var collectionView2: UICollectionView!

    let recipeImages = ["angry_birds_cake", "creme_brelee", "egg_benedict", "full_breakfast", "green_tea", "ham_and_cheese_panini", "ham_and_egg_sandwich", "hamburger", "instant_noodle_with_egg.jpg", "japanese_noodle_with_pork", "mushroom_risotto", "noodle_with_bbq_pork", "starbucks_coffee", "thai_shrimp_cake", "vegetable_curry", "white_chocolate_donut"]

    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Do any additional setup after loading the view.

    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        //#warning Incomplete method implementation -- Return the number of sections
        return 1
    }


    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        //#warning Incomplete method implementation -- Return the number of items in the section
         return recipeImages.count
    }

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! RecipeCollectionViewCell

        // Configure the cell
        cell.recipeImageView.image = UIImage(named: recipeImages[indexPath.row])

        return cell
    }

回答by Matthew Quiros

You need to do this programatically.

您需要以编程方式执行此操作。

Implement UICollectionViewDelegateFlowLayoutin your view controller and provide the size in collectionView:layout:sizeForItemAtIndexPath:

UICollectionViewDelegateFlowLayout在您的视图控制器中实现并提供大小collectionView:layout:sizeForItemAtIndexPath:

func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        let kWhateverHeightYouWant = 100
        return CGSizeMake(collectionView.bounds.size.width, CGFloat(kWhateverHeightYouWant))
}

You will also want to call collectionView.collectionViewLayout.invalidateLayout()inside your view controller's viewWillLayoutSubviews()so that when the main view's dimensions change (on rotation, for example), the collection view is re-laid out.

您还需要collectionView.collectionViewLayout.invalidateLayout()在视图控制器内部调用,viewWillLayoutSubviews()以便当主视图的尺寸发生变化时(例如,在旋转时),集合视图会重新布局。

Swift 4 Update

斯威夫特 4 更新

func collectionView(_ collectionView: UICollectionView,
                            layout collectionViewLayout: UICollectionViewLayout,
                            sizeForItemAt indexPath: IndexPath) -> CGSize {
            let kWhateverHeightYouWant = 100
            return CGSize(width: collectionView.bounds.size.width, height: CGFloat(kWhateverHeightYouWant))
}

回答by mustafa

Inside your view controller override viewDidLayoutSubviewsmethod

在您的视图控制器覆盖viewDidLayoutSubviews方法中

@IBOutlet weak var collectionView: UICollectionView!

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
        let itemWidth = view.bounds.width / 3.0
        let itemHeight = layout.itemSize.height
        layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
        layout.invalidateLayout()
    }
}

(collectionViewproperty is your collectionView)

collectionView属性是你的 collectionView)

回答by Nimit Parekh

Use Following code for set the width of UICollectionViewCell.

使用以下代码设置UICollectionViewCell.

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {        
    return CGSize(width: screenWidth/3, height: screenWidth/3);
}

回答by brycejl

Also in Swift 3,

同样在 Swift 3 中,

Make sure your view controller complies with the following:

确保您的视图控制器符合以下要求:

UICollectionViewDelegate,
UICollectionViewDataSource,
UICollectionViewDelegateFlowLayout

UICollectionViewDelegate、
UICollectionViewDataSource、
UICollectionViewDelegateFlowLayout

回答by Raju Abe

I have the same requirement, in my case below solution is worked. I set UIImageViewtop, left, bottom and right constraints to 0inside UICollectionviewCell

我有同样的要求,就我而言,以下解决方案有效。我在 UICollectionviewCell中将UIImageView顶部、左侧、底部和右侧约束设置为0

@IBOutlet weak var imagesCollectionView: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()
    // flowlayout
    let screenWidth = UIScreen.main.bounds.width
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    layout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 10, right: 0)
    layout.itemSize = CGSize(width: screenWidth/3 - 5, height: screenWidth/3 - 5)
    layout.minimumInteritemSpacing = 5
    layout.minimumLineSpacing = 5
    imagesCollectionView.collectionViewLayout = layout

}

回答by JPetric

Swift 3

斯威夫特 3

If you are using swift 3, use this method:

如果您使用的是 swift 3,请使用以下方法:

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {

    }

Notice the changes:

注意变化:

  1. add _before collectionViewin the method name
  2. NSIndexPathchanges to IndexPath
  1. 在方法名称_之前添加collectionView
  2. NSIndexPath更改为 IndexPath

回答by Eduardo Irias

In my case, assuming every cell has a width of 155 and a height of 220. If I want to show 2 cells per row in a portrait mode and 3 for landscape.

就我而言,假设每个单元格的宽度为 155,高度为 220。如果我想在纵向模式下每行显示 2 个单元格,在横向模式下显示 3 个单元格。

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    var itemsCount : CGFloat = 2.0
    if UIApplication.sharedApplication().statusBarOrientation != UIInterfaceOrientation.Portrait {
        itemsCount = 3.0
    }
    return CGSize(width: self.view.frame.width/itemsCount - 20, height: 220/155 * (self.view.frame.width/itemsCount - 20));
}

回答by ZaBlanc

The best solution is to change the itemSizeof your UICollectionViewFlowLayoutin viewDidLayoutSubviews. That is where you can get the most accurate size of the UICollectionView. You don't need to call invalidate on your layout, that will be done for you already.

最好的解决方案是更改itemSize您的UICollectionViewFlowLayoutin viewDidLayoutSubviews. 在这里您可以获得最准确的UICollectionView. 您不需要在布局上调用 invalidate ,这已经为您完成了。

回答by Firas Shrourou

For my case, I wanted to show two columns and 3 rows in the UICollectionView

就我而言,我想在 UICollectionView 中显示两列和 3 行

I added UICollectionViewDelegateFlowLayout delegate to my class

我在我的班级中添加了 UICollectionViewDelegateFlowLayout 委托

then I override sizeForItemAt indexPath

然后我覆盖 sizeForItemAt indexPath

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let cellHeight = (collectionView.bounds.size.height - 30) / 3 // 3 count of rows to show
    let cellWidth = (collectionView.bounds.size.width - 20) / 2 // 2 count of colomn to show
    return CGSize(width: CGFloat(cellWidth), height: CGFloat(cellHeight))
}

The 30 is the Line spacing, the 20 is the insent between cells

30 是行间距,20 是单元格之间的间隔

回答by froggomad

For my case, autolayout was only allowing the cell to grow to its content size even though I overrode the cell size in the storyboard, conformed to UICollectionViewDelegateFlowLayout, and implemented sizeForItemAt. So I made a dummy UIView the width of the cell's bounds.

对于我的情况下,自动布局才被允许细胞长到即使我在故事板推翻细胞大小的内容大小,符合UICollectionViewDelegateFlowLayout和执行sizeForItemAt。所以我做了一个虚拟的 UIView 单元格边界的宽度。

UICollectionViewController:

UICollectionViewController:

extension CollectionViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = collectionView.bounds.width - 40
        return CGSize(width: width, height: collectionView.bounds.height / 3)
    }
}

Cell (I'm calling this method on dependency injection):

Cell(我在依赖注入时调用此方法):

private func updateViews() {
    let padding:CGFloat = 8
    let innerView = UIView()
    innerView.translatesAutoresizingMaskIntoConstraints = false
    innerView.layer.cornerRadius = 8
    innerView.layer.borderColor = UIColor.black.cgColor
    innerView.layer.borderWidth = 1
    contentView.addSubview(innerView)
    NSLayoutConstraint.activate([
        innerView.widthAnchor.constraint(equalToConstant: bounds.width - padding*2),
        innerView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: padding),
        innerView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -padding),
        innerView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: padding),
        innerView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -padding)
    ])
}