프로그래밍 방식으로 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 Sizenone제대로 작동하게하기 위해 스토리 보드를 사용하여. 아래 코드보다 설정하지 않으면 예상대로 작동하지 않습니다.

여기에 이미지 설명 입력

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 SizeNone으로 설정 하고 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기본 보인다 estimatedItemSizeUICollectionViewFlowLayout.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

Swift3Swift4 에서는 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.