Cách đặt Chiều rộng và Chiều cao UICollectionViewCell theo lập trình


103

Tôi đang cố gắng thực hiện a CollectionView. Khi tôi đang sử dụng Autolayout, các ô của tôi sẽ không thay đổi kích thước mà là sự liên kết của chúng.

Bây giờ tôi muốn thay đổi kích thước của chúng thành ví dụ:

//var size = CGSize(width: self.view.frame.width/10, height: self.view.frame.width/10)

Tôi đã thử thiết lập trong CellForItemAtIndexPath

collectionCell.size = size

nó đã không hoạt động mặc dù.

Có cách nào để đạt được điều này?

chỉnh sửa :

Có vẻ như câu trả lời sẽ chỉ thay đổi chiều rộng và chiều cao CollectionView của tôi. Có thể có xung đột trong Ràng buộc không? Bất kỳ ý tưởng về điều đó?

Câu trả lời:


267

Sử dụng phương pháp này để đặt chiều rộng chiều cao ô tùy chỉnh.

Đảm bảo thêm các giao thức này

UICollectionViewDelegate

UICollectionViewDataSource

UICollectionViewDelegateFlowLayout

Nếu bạn đang sử dụng swift 5 hoặc xcode 11 trở lên, bạn cần đặt Estimate Sizethành nonesử dụng bảng phân cảnh để làm cho nó hoạt động bình thường. Nếu bạn không đặt điều đó hơn mã dưới đây sẽ không hoạt động như mong đợi.

nhập mô tả hình ảnh ở đây

Swift 4 trở lên

extension YourViewController: UICollectionViewDelegate {
    //Write Delegate Code Here
}

extension YourViewController: UICollectionViewDataSource {
    //Write DataSource Code Here
}

extension YourViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: screenWidth, height: screenWidth)
    }
}

Objective-C

@interface YourViewController : UIViewController<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(CGRectGetWidth(collectionView.frame), (CGRectGetHeight(collectionView.frame)));
}

1
@RamyAlZuhouri Đã chỉnh sửa câu trả lời của tôi, vui lòng kiểm tra và cho tôi biết nếu chúng tôi vẫn cần làm rõ hơn
PinkeshGjr

8
Tôi đã quá quen với việc làm mọi thứ theo chương trình nên bây giờ điều này có vẻ xa lạ với tôi. Trong cài đặt Storyboard, Kích thước ước tính thành Không có và thêm UICollectionViewDelegateFlowLayout là mẹo nào
Lance Samaria

5
Đặt Kích thước ước tính thành không hiệu quả với tôi. Cảm ơn bạn @PinkeshGjr
Mohan

5
Tôi rất vui vì tôi đã tìm thấy cái này, tôi đã lãng phí 2 giờ theo đuổi cái này chỉ để học phép thuật 'Kích thước ước tính để không'
Klajd Deda

3
đặt Kích thước ước tính thành không lưu ngày của tôi.
tounaobun

73

Đảm bảo thêm giao thức UICollectionViewDelegateFlowLayoutvào classkhai báo của bạn

class MyCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout
{
    //MARK: - UICollectionViewDelegateFlowLayout

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

Đừng quên sử dụng bố cục luồng chứ không phải tùy chỉnh. Vậy thì của bạn là cái duy nhất phù hợp với tôi. Cảm ơn!
Sean

như thế nào chúng ta có thể cung cấp cho chiều cao năng động ở đây cho chiều cao tĩnh như 100.0
sangavi

65

Nếu một người đang sử dụng bảng phân cảnh và ghi đè UICollectionViewDelegateFlowLayout thì trong swift 5 và Xcode 11 cũng đặt Kích thước ước tính thành Không có nhập mô tả hình ảnh ở đây


2
Điều đó rất hữu ích. Cảm ơn!!
Hải quân Hasan

Đó chắc chắn là điều tôi sắp phát điên. Trừ khi bạn đặt nó thành không, bạn không thể thấy kích thước chính xác mà bạn đã cung cấp trong phương thức sizeForItem.
Yusuf Kamil AK

2
Đặt kích thước ước tính thành không cố định mọi thứ
MMK

2
Kích thước ước tính cài đặt Thnx thành không có sự cố nào được khắc phục
Salman500

2
Sửa chữa tốt. Dưới đây là chẩn đoán của tôi về vấn đề này theo tài liệu hướng dẫn của Apple : UICollectionViewFlowLayoutdường như mặc định estimatedItemSizeđể UICollectionViewFlowLayout.automaticSizekhi sử dụng IB mặc dù các tài liệu nói nó nên mặc định CGSizeZero. Như Apple tuyên bố, automaticSize"cho phép các ô tự định kích thước cho chế độ xem bộ sưu tập của bạn." Đó là lý do tại sao các thay đổi kích thước khác trong IB không làm gì cả.
Andrew Kirna

20

Cuối cùng cũng có câu trả lời. Bạn nên mở rộng UICollectionViewDelegateFlowLayout
Điều này sẽ làm việc với các câu trả lời ở trên.


Bạn có thể viết một ví dụ?
Mamdouh El Nakeeb

Trên thực tế, tôi đã tạo một tiện ích mở rộng với cả hai giao thức nguồn dữ liệu và ủy quyền FlowLayout và nó không hoạt động. Điều hoạt động là tách phần FlowLayout thành một phần mở rộng của riêng nó. Không chắc tại sao nhưng nó hoạt động nhanh chóng 3.
Skywalker

15

nhanh chóng 4,1

Bạn có 2 cách để thay đổi kích thước của CollectionView.
Cách đầu tiên -> thêm giao thức này UICollectionViewDelegateFlowLayout
cho Trong trường hợp của tôi, tôi muốn chia ô thành 3 phần trong một dòng. Tôi đã làm mã này bên dưới

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource ,UICollectionViewDelegateFlowLayout{
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
    {
            // In this function is the code you must implement to your code project if you want to change size of Collection view
            let width  = (view.frame.width-20)/3
            return CGSize(width: width, height: width)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return collectionData.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath)
        if let label = cell.viewWithTag(100) as? UILabel {
            label.text = collectionData[indexPath.row]
        }
        return cell
    }
}

Cách thứ hai -> bạn không phải thêm UICollectionViewDelegateFlowLayout nhưng bạn phải viết một số mã trong hàm viewDidload thay vì mã dưới đây

class ViewController: UIViewController {
@IBOutlet weak var collectionView1: UICollectionView!
        var collectionData = ["1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10.", "11.", "12."]

    override func viewDidLoad() {
        super.viewDidLoad()
        let width = (view.frame.width-20)/3
        let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
        layout.itemSize = CGSize(width: width, height: width) 
    }
}


extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return collectionData.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath)
        if let label = cell.viewWithTag(100) as? UILabel {
            label.text = collectionData[indexPath.row]
        }

        return cell
    }
}

Dù bạn viết mã theo cách thứ nhất hay cách thứ hai, bạn sẽ nhận được kết quả tương tự như trên. Tôi đã viết nó. Nó đã làm việc cho tôi

nhập mô tả hình ảnh ở đây


2
Trực tiếp từ raywenderlich.com 😂
Andrew Kirna

12

Tỷ lệ kích thước theo kích thước iPhone:

Đây là những gì bạn có thể làm để có chiều rộng và chiều cao khác nhau cho các ô liên quan đến kích thước iPhone:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    let width = (self.view.frame.size.width - 12 * 3) / 3 //some width
    let height = width * 1.5 //ratio
    return CGSize(width: width, height: height)
}

Và có thể bạn cũng nên tắt các ràng buộc Tự động thanh toán của mình trên ô để câu trả lời này hoạt động.


Tôi đã thử điều này và tất cả các giải pháp ở trên nhưng nội dung trong ô không tự động lưu trữ, làm cách nào tôi có thể sửa lỗi này
Biasi Wiga

7

Dạng xem bộ sưu tập có một đối tượng bố cục . Trong trường hợp của bạn, nó có thể là một bố cục luồng ( UICollectionViewFlowLayout ). Đặt thuộc itemSizetính của bố cục luồng .


Đã thử điều này. cho tôi vấn đề tương tự như trước đây. Bằng cách nào đó, CollectionView của tôi thay đổi kích thước nó thay vì các ô của tôi.
JVS

2
Vâng, tất cả phụ thuộc khi bạn làm điều đó. Bạn chưa hiển thị mã thực của mình, vậy ai biết bạn đang làm gì? Tôi đảm bảo với bạn rằng nó hoạt động.
matt

7

trong Swift3Swift4, bạn có thể thay đổi kích thước ô bằng cách thêm UICollectionViewDelegateFlowLayout và triển khai nó như sau:

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

hoặc nếu tạo UICollectionView theo chương trình, bạn có thể làm như sau:

    let layout = UICollectionViewFlowLayout()
                    layout.scrollDirection = .horizontal //this is for direction
                    layout.minimumInteritemSpacing = 0 // this is for spacing between cells
                    layout.itemSize = CGSize(width: view.frame.width, height: view.frame.height) //this is for cell size
let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)

4

swift4 swift 4 ios collection view collectionview ví dụ xcode mẫu làm việc mã mới nhất

Thêm cái này vào phần Ủy quyền ở trên cùng

UICollectionViewDelegateFlowLayout

và sử dụng chức năng này

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = (self.view.frame.size.width - 20) / 3 //some width
    let height = width * 1.5 //ratio
    return CGSize(width: width, height: height)
}

///// mã hoàn chỉnh mẫu

tạo trên chế độ xem bộ sưu tập và ô collectionview trong bảng phân cảnh cung cấp tham chiếu đến bộ sưu tập dưới dạng
@IBOutlet yếu var cv Nội dung: UICollectionView!

dán cái này vào View controller

 import UIKit

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    var arrVeg = [String]()
    var arrFruits = [String]()
    var arrCurrent = [String]()
    
    @IBOutlet weak var cvContent: UICollectionView!
    
  
    
    override func viewDidLoad() {
        super.viewDidLoad()
        arrVeg = ["Carrot","Potato", "Tomato","Carrot","Potato", "Tomato","Carrot","Potato", "Tomato","Carrot","Potato", "Tomato"]
        
        arrVeg = ["Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange"]
        
        
        arrCurrent = arrVeg
    }
    //MARK: - CollectionView
    


    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = (self.view.frame.size.width - 20) / 3 //some width
        let height = width * 1.5 //ratio
        return CGSize(width: width, height: height)
    }
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {

        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
        
        return arrCurrent.count
    }
    
    
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ContentCollectionViewCell
        cell.backgroundColor =  UIColor.green
        return cell
    }
}

2

Hãy thử phương pháp dưới đây

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: 100.0, height: 100.0)
}

2

Swift 5 có lập trình

lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal

        //Provide Width and Height According to your need
        let cellWidth = UIScreen.main.bounds.width / 10
        let cellHeight = UIScreen.main.bounds.height / 10
        layout.itemSize = CGSize(width: cellWidth, height: cellHeight)

        //You can also provide estimated Height and Width
        layout.estimatedItemSize = CGSize(width: cellWidth, height: cellHeight)

        //For Setting the Spacing between cells
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0

        return UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
    }()

1
**Swift 5**
To make this work you have to do the following.

Add these protocols

 - UICollectionViewDelegate


 - UICollectionViewDataSource


 - UICollectionViewDelegateFlowLayout

Your code will then look like this

extension YourViewController: UICollectionViewDelegate {
    //Write Delegate Code Here
}

extension YourViewController: UICollectionViewDataSource {
    //Write DataSource Code Here
}

extension YourViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: screenWidth, height: screenWidth)
    }
}

Now the final and crucial step to see this take effect is to go to your viedDidLoad function inside your Viewcontroller.

    override func viewDidLoad() {
        super.viewDidLoad()
        collection.dataSource = self // Add this
        collection.delegate = self // Add this

        // Do any additional setup after loading the view.
    }

Without telling your view which class the delegate is it won't work.

1

2020, cách hoàn toàn đơn giản:

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource {

Bạn phải thêm "UICollectionViewDelegateFlowLayout" hoặc không có tính năng tự động hoàn thành:

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {

Nhập "sizeForItemAt ...". Bạn đã hoàn tất!

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {

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

     return CGSize(width: 37, height: 63)
}

Đó là nó.

Ví dụ, nếu bạn muốn "mỗi ô lấp đầy toàn bộ chế độ xem bộ sưu tập":

     guard let b = view.superview?.bounds else { .. }
     return CGSize(width: b.width, height: b.height)

0

Một cách khác là đặt giá trị trực tiếp trong bố cục luồng

    let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: size, height: size)

0

Vì vậy, bạn cần đặt từ bảng phân cảnh cho thuộc tính cho ước tính collectionView trong phần ô Kích thước thành không và trong ViewController của bạn, bạn cần có phương thức ủy quyền để triển khai phương pháp này: optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize


0

Cố gắng sử dụng phương pháp UICollectionViewDelegateFlowLayout. Trong Xcode 11 trở lên, bạn cần đặt Kích thước ước tính thành không có từ bảng phân cảnh.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let padding: CGFloat =  170
    let collectionViewSize = advertCollectionView.frame.size.width - padding
    return CGSize(width: collectionViewSize/2, height: collectionViewSize/2)
}

0

Một cách đơn giản:

Nếu bạn chỉ cần một kích thước cố định đơn giản :

class SizedCollectionView: UIICollectionView {
    override func common() {
        super.common()
        let l = UICollectionViewFlowLayout()
        l.itemSize = CGSize(width: 42, height: 42)
        collectionViewLayout = l
    }
}

Thats tất cả để có nó.

Trong bảng phân cảnh, chỉ cần thay đổi lớp từ UICollectionView thành SizedCollectionView.

Nhưng !!!

Chú ý lớp cơ sở có "UI 'I' CollectionView". 'I' cho Trình khởi tạo.

Không dễ dàng như vậy để thêm trình khởi tạo vào chế độ xem bộ sưu tập. Đây là một cách tiếp cận phổ biến:

Chế độ xem bộ sưu tập ... với trình khởi tạo:

import UIKit

class UIICollectionView: UICollectionView {
    private var commoned: Bool = false
    
    override func didMoveToWindow() {
        super.didMoveToWindow()
        if window != nil && !commoned {
            commoned = true
            common()
        }
    }
    
    internal func common() {
    }
}

Trong hầu hết các dự án, bạn cần "chế độ xem bộ sưu tập với bộ khởi tạo". Vì vậy, bạn có thể sẽ có UIICollectionView(lưu ý thêm I cho Trình khởi tạo!) Trong dự án của bạn.


0

Swift 5, cài đặt UICollectionView có lập trình Chiều rộng và chiều cao của ô

// MARK: MyViewController

final class MyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
        let layout = UICollectionViewFlowLayout()
        let spacing: CGFloat = 1
        let numOfColumns: CGFloat = 3
        let itemSize: CGFloat = (UIScreen.main.bounds.width - (numOfColumns - spacing) - 2) / 3
        layout.itemSize = CGSize(width: itemSize, height: itemSize)
        layout.minimumInteritemSpacing = spacing
        layout.minimumLineSpacing = spacing
        layout.sectionInset = UIEdgeInsets(top: spacing, left: spacing, bottom: spacing, right: spacing)
        return layout
    }()
    
    private lazy var collectionView: UICollectionView = {
        let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: collectionViewLayout)
        collectionView.backgroundColor = .white
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureCollectionView()
    }
    
    private func configureCollectionView() {
        view.addSubview(collectionView)
        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
        ])
        collectionView.register(PhotoCell.self, forCellWithReuseIdentifier: "PhotoCell")
    }
    
    // MARK: UICollectionViewDataSource

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell
        cell.backgroundColor = .red
        return cell
    }
    
}

// MARK: PhotoCell

final class PhotoCell: UICollectionViewCell {
    
    lazy var imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.layer.masksToBounds = true
        return imageView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init?(coder:) not implemented")
    }
    
    func setupViews() {
        addSubview(imageView)
        NSLayoutConstraint.activate([
            topAnchor.constraint(equalTo: topAnchor),
            bottomAnchor.constraint(equalTo: bottomAnchor),
            leadingAnchor.constraint(equalTo: leadingAnchor),
            trailingAnchor.constraint(equalTo: trailingAnchor)
        ])
    }
    
}

-4

Đây là phiên bản của tôi, hãy tìm tỷ lệ phù hợp của bạn để có được kích thước ô theo yêu cầu của bạn.

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
return CGSizeMake(CGRectGetWidth(collectionView.frame)/4, CGRectGetHeight(collectionView.frame)/4); 
} 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.