Пользовательская ячейка UICollectionView для заполнения ширины в Swift

Я пытался выяснить, как я могу сделать ячейку заполнить ширину, как вы можете видеть на картинке, ширина между ячейками слишком велика. я использую пользовательскую ячейку только с одним imageView.

enter image description here

Я попытался настроить его из раскадровки, но я думаю, что для этого нет опции, или это должно быть сделано программно. enter image description here

мой 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
    }

10 ответов


вам нужно сделать это программно.

реализовать 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))
}

вы также захотите позвонить collectionView.collectionViewLayout.invalidateLayout() внутри вашего контроллера вида viewWillLayoutSubviews() таким образом, когда размеры основного вида изменяются (например, при вращении), представление коллекции перестраивается.

Обновление Swift 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))
}

внутри вашего контроллера view override 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 свойство-это ваш collectionView)


используйте следующий код для установки ширины UICollectionViewCell.

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

также в Swift 3,

убедитесь, что контроллер вида соответствует следующему:

UICollectionViewDelegate,
UICollectionViewDataSource,
UICollectionViewDelegateFlowLayout


Swift 3

если вы используете swift 3, Используйте этот метод:

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

    }

обратите внимание на изменения:

  1. добавить _ до collectionView в имя метода
  2. NSIndexPath изменения IndexPath

У меня такое же требование, в моем случае работает решение bellow. Я установил UIImageView верхний, левый, нижний и правый ограничения на 0 внутри UICollectionviewCell

@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

}

программно установить itemSize до [UIScreen mainScreen].bounds.size.width/3


в моем случае, предполагая, что каждая ячейка имеет ширину 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));
}

лучшим решением является изменение itemSize вашего UICollectionViewFlowLayout на viewDidLayoutSubviews. Вот где вы можете получить наиболее точный размер UICollectionView. Вам не нужно вызывать invalidate на вашем макете,это будет сделано для вас уже.


для моего случая я хотел показать два столбца и 3 строки в UICollectionView

Я добавил делегат uicollectionviewdelegateflowlayout в свой класс

затем я переопределяю 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))
}

30-это межстрочный интервал, 20-это insent между ячейками