프로그래밍 방식으로 UICollectionViewCell 너비 및 높이를 설정하는 방법


103

나는 CollectionView. 자동 레이아웃을 사용할 때 셀의 크기가 변경되지 않고 정렬이 변경됩니다.

이제는 크기를 예를 들어 변경하고 싶습니다.

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

내 설정을 시도 CellForItemAtIndexPath

collectionCell.size = size

그래도 작동하지 않았습니다.

이것을 달성하는 방법이 있습니까?

편집 :

대답은 CollectionView 너비와 높이 자체 만 변경하는 것 같습니다. 제약 조건에 충돌이있을 수 있습니까? 그것에 대한 어떤 아이디어?

답변:


267

이 방법을 사용하여 사용자 지정 셀 높이 너비를 설정합니다.

이 프로토콜을 추가해야합니다.

UICollectionViewDelegate

UICollectionViewDataSource

UICollectionViewDelegateFlowLayout

당신이 사용하는 경우 신속 5 또는 엑스 코드 (11) 와 나중에는 세트에 필요 Estimate Size로 none제대로 작동하게하기 위해 스토리 보드를 사용하여. 아래 코드보다 설정하지 않으면 예상대로 작동하지 않습니다.

여기에 이미지 설명 입력

Swift 4 이상

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

목표 -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 내 대답을 수정하고 확인하고 더 명확하게
— 해야하는지

8
나는 모든 것을 프로그래밍 방식으로하는 데 너무 익숙해서 지금은 나에게 너무 이질적인 것 같다. Storyboard에서 Estimated Size 를 None으로 설정 하고 UICollectionViewDelegateFlowLayout을 추가하는 것이 트릭을 수행하는 것입니다
— Lance Samaria

5
Estimate Size를 none으로 설정하면 효과가 없었습니다. @PinkeshGjr 감사합니다
— Mohan

5
나는 이것을 발견해서 기쁘다, 나는 단지 마법의 'Estimate Size to none'을 배우기 위해 이것을 쫓는 데 2 ​​시간을 낭비했다
— Klajd Deda

3
내 일을 저장하지 않음으로 예상 크기를 설정하십시오.
— tounaobun

73

선언에 프로토콜을 추가해야합니다 UICollectionViewDelegateFlowLayout.class

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

사용자 정의가 아닌 흐름 레이아웃을 사용하는 것을 잊지 마십시오. 그렇다면 당신의 것이 나를 위해 일한 유일한 사람입니다. 감사!
— Sean

여기서 정적 높이를 100.0으로 지정하는 동적 높이를 어떻게 줄 수
— 있습니까?

65

스토리 보드를 사용하고 UICollectionViewDelegateFlowLayout 을 재정의하는 경우 신속한 5 및 Xcode 11에서도 Estimate size를 None으로 설정합니다. 여기에 이미지 설명 입력


2
도움이되었습니다. 감사!!
— Naval Hasan

그게 내가 미친 짓 이었어. none으로 설정하지 않으면 sizeForItem 메서드에서 지정한 올바른 크기를 볼 수 없습니다.
— Yusuf Kamil AK

2
예상 크기를 없음으로 설정하면 모든 것이 수정 됨
— MMK

2
Thnx 설정 추정 크기를 문제로 해결되지 않음
— Salman500

2
좋은 수정. 여기에 따라이 문제의 내 진단의 애플의 설명서 : UICollectionViewFlowLayout기본 보인다 estimatedItemSize에 UICollectionViewFlowLayout.automaticSize문서가이 기본합니다 말한다하더라도 IB를 사용하는 경우 CGSizeZero. Apple은 automaticSize"컬렉션 뷰에 대해 셀 자체 크기 조정을 활성화합니다."라고 말합니다. 이것이 IB의 다른 크기 변경이 아무 일도하지 않는 이유입니다.
— Andrew Kirna

20

마침내 답을 얻었습니다. 확장 UICollectionViewDelegateFlowLayout
해야합니다 이것은 위의 답변으로 작업해야합니다.


예를 써주시 겠어요?
— Mamdouh El Nakeeb

실제로 데이터 소스와 delegateFlowLayout 프로토콜을 모두 사용하여 확장을 만들었으나 작동하지 않았습니다. 성공한 것은 FlowLayout 부분을 자체 확장으로 분리하는 것입니다. 이유는 확실하지 않지만 스위프트 3에서 작동했습니다.
— Skywalker

15

신속한 4.1

CollectionView의 크기를 변경하는 방법에는 두 가지가 있습니다.
첫 번째 방법 ->이 프로토콜 추가 UICollectionViewDelegateFlowLayout
for 제 경우에는 셀을 한 줄에 세 부분으로 나누고 싶습니다. 아래 코드를 작성했습니다.

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

두 번째 방법은 -> 당신은 하지 않습니다 추가해야 UICollectionViewDelegateFlowLayout을 하지만 당신은 몇 가지 코드를 작성할 필요가 있는 viewDidLoad 함수를 아래 코드로 대신

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

첫 번째 방법 또는 두 번째 방법으로 코드를 작성하면 위와 동일한 결과를 얻을 수 있습니다. 내가 썼어. 그것은 나를 위해 일했습니다

여기에 이미지 설명 입력


2
raywenderlich.com에서 바로 😂
— Andrew Kirna

12

iPhone 크기에 따른 크기 비율 :

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

이 답변이 작동하려면 셀에서 AutoLayout 제약 조건을 비활성화해야 할 수도 있습니다.


나는 이것을 시도하고 위의 모든 솔루션을 시도했지만 셀의 내용이 자동 크기 조정되지 않습니다. 어떻게 해결할 수
— 있습니까

7

컬렉션보기에는 레이아웃 개체가 있습니다. 귀하의 경우에는 아마도 흐름 레이아웃 ( UICollectionViewFlowLayout ) 일 것입니다. 흐름 레이아웃의 itemSize속성을 설정합니다 .


이것을 시도했습니다. 이전과 같은 문제가 발생합니다. 어떻게 든 내 CollectionView가 내 셀이 아닌 크기를 변경합니다.
— JVS

2
글쎄, 그것은 모두 당신이 그것을 할 때 달려 있습니다. 실제 코드를 보여주지 않았는데, 당신이 무엇을하는지 누가 압니까? 나는 그것이 작동한다고 확신합니다.
— matt

7

Swift3 및 Swift4 에서는 UICollectionViewDelegateFlowLayout 을 추가하고 다음 과 같이 구현 하여 셀 크기를 변경할 수 있습니다 .

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

또는 프로그래밍 방식으로 UICollectionView를 생성하는 경우 다음과 같이 할 수 있습니다.

    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 example xcode 최신 코드 작업 샘플

상단의 델리게이트 섹션에 추가

UICollectionViewDelegateFlowLayout

이 기능을 사용하십시오

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

///// 샘플 전체 코드


@IBOutlet weak var cvContent : UICollectionView 로 컬렉션에 대한 참조를 제공합니다 .

뷰 컨트롤러에 붙여 넣기

 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

아래 방법을 시도하십시오

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

2

프로그래밍 방식으로 Swift 5

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 년, 절대적으로 간단한 방법 :

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource {

"UICollectionViewDelegateFlowLayout"을 추가해야합니다. 그렇지 않으면 자동 완성이 없습니다.

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {

"sizeForItemAt ..."을 입력합니다. 끝났습니다!

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {

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

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

그게 다야.

예를 들어 "각 셀이 전체 컬렉션보기를 채 웁니다"를 원하는 경우 :

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

0

다른 방법은 흐름 레이아웃에서 직접 값을 설정하는 것입니다.

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

0

따라서 셀 섹션의 collectionView 속성에 대한 스토리 보드에서 Size를 none으로 설정해야하며 ViewController에서이 메서드를 구현하기위한 위임 메서드가 필요합니다. optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize


0

UICollectionViewDelegateFlowLayout 메서드를 사용해보십시오. Xcode 11 이상에서는 스토리 보드에서 Estimate Size를 none으로 설정해야합니다.

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

간단한 방법 :

간단한 고정 크기 가 필요한 경우 :

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

그게 전부입니다.

스토리 보드에서 클래스를 UICollectionView에서 SizedCollectionView로 변경하기 만하면됩니다.

하지만 !!!

기본 클래스에는 "UI 'I'CollectionView"가 있습니다. Initializer의 경우 'I'입니다.

컬렉션 뷰에 이니셜 라이저를 추가하는 것은 쉽지 않습니다. 다음은 일반적인 접근 방식입니다.

컬렉션 뷰 ... 초기화 포함 :

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

대부분의 프로젝트에서 "이니셜 라이저가있는 컬렉션 뷰"가 필요합니다. 따라서 UIICollectionView프로젝트에 어쨌든 (초기화에 대한 추가 I에 유의하십시오!) 가있을 것입니다 .


0

Swift 5, 프로그래밍 방식 UICollectionView 설정 셀 너비 및 높이

// 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

이것은 내 버전이며 귀하의 요구 사항에 따라 셀 크기를 얻기 위해 적합한 비율을 찾으십시오.

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
return CGSizeMake(CGRectGetWidth(collectionView.frame)/4, CGRectGetHeight(collectionView.frame)/4); 
} 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.