简体   繁体   English

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

[英]UICollectionView Custom Cell to fill width In Swift

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 的自定义单元格。

在此处输入图片说明

I tried to customize it from the storyboard but i guess there is no option for that or it should be done programmatically.我试图从情节提要中自定义它,但我想没有选择,或者应该以编程方式完成。在此处输入图片说明

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
    }

You need to do this programatically.您需要以编程方式执行此操作。

Implement UICollectionViewDelegateFlowLayout in your view controller and provide the size in collectionView:layout:sizeForItemAtIndexPath:在视图控制器中实现UICollectionViewDelegateFlowLayout并在collectionView:layout:sizeForItemAtIndexPath:提供大小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.您还需要在视图控制器的viewWillLayoutSubviews()调用collectionView.collectionViewLayout.invalidateLayout()以便当主视图的尺寸发生变化时(例如在旋转时),集合视图会重新布局。

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))
}

Inside your view controller override viewDidLayoutSubviews method在您的视图控制器中覆盖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()
    }
}

( collectionView property is your collectionView) collectionView属性是您的 collectionView)

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);
}

Also in Swift 3,同样在 Swift 3 中,

Make sure your view controller complies with the following:确保您的视图控制器符合以下要求:

UICollectionViewDelegate, UICollectionViewDelegate,
UICollectionViewDataSource, UICollectionViewDataSource,
UICollectionViewDelegateFlowLayout UICollectionViewDelegateFlowLayout

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 collectionView in the method name在方法名称中的collectionView前添加_
  2. NSIndexPath changes to IndexPath NSIndexPath更改为IndexPath

I have the same requirement, in my case below solution is worked.我有同样的要求,就我而言,以下解决方案有效。 I set UIImageView top, left, bottom and right constraints to 0 inside 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

}

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 是单元格之间的间隔

以编程方式将itemSize设置为[UIScreen mainScreen].bounds.size.width/3

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));
}

The best solution is to change the itemSize of your UICollectionViewFlowLayout in viewDidLayoutSubviews .最好的解决方案是在viewDidLayoutSubviews更改itemSizeUICollectionViewFlowLayout That is where you can get the most accurate size of the UICollectionView .这是您可以获得UICollectionView最准确大小的UICollectionView You don't need to call invalidate on your layout, that will be done for you already.您不需要在布局上调用 invalidate ,这已经为您完成了。

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 .就我而言,即使我覆盖了情节UICollectionViewDelegateFlowLayout的单元格大小,符合UICollectionViewDelegateFlowLayout并实现了sizeForItemAt ,自动布局也只允许单元格增长到其内容大小。 So I made a dummy UIView the width of the cell's bounds.所以我做了一个虚拟的 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)
    ])
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM