CollectionView sizeForItemAtIndexPath không bao giờ được gọi


94

Điều này khiến tôi điên mất! Tôi có một UICollectionViewController như hình dưới đây:

class PhrasesCompactCollectionViewController: UICollectionViewController

NumberOfSection và cellForItemAt đang được gọi nhưng sizeForItemAtIndexPath không bao giờ được gọi. Tôi đang sử dụng cùng một mã chính xác ở một nơi khác và nó kích hoạt chính xác. Tôi đang sử dụng Xcode 8 Beta 6.

func collectionView(collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAtIndexPath indexPath:  NSIndexPath) -> CGSize {

        return CGSize(width: 120, height:120) 
    }

Câu trả lời:


251

Bạn cần chỉ định rằng bạn triển khai giao thức UICollectionViewDelegateFlowLayouttrong khai báo lớp của mình.

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout


10
Tôi đã làm điều này nhưng nó vẫn không được gọi. :(
Van Du Tran

57

Trong Swift 3+ Sử dụng phương pháp này:

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

Đảm bảo rằng lớp của bạn tuân thủ cả hai Ủy quyền

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout


4
Việc tuân thủ UICollectionViewDelegatenhư UICollectionViewController đã làm là không cần thiết.
Van Du Tran

3
@VanDuTran Nó không dôi dư để trạng thái đó nó yêu cầu vì bị một UICollectionViewController không yêu cầu ...
Michael Hudson

Tôi nghĩ bạn muốn nói rằng một chế độ xem không phải là bộ sưu tập, Viewcontroller có thể là UICollectionViewDelegate.
ScottyBlades

1
UICollectionViewDelegateFlowLayout kế thừa từ UICollectionViewDelegate nên chỉ cần triển khai UICollectionViewDelegateFlowLayout
evya

46

Tôi đã từng gặp vấn đề tương tự. Một điều đã giúp tôi là tạo 'Kích thước ước tính' cho Kích thước ô trong bộ kiểm tra kích thước của bộ sưu tậpXem 'Không có'.

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


8
Bạn đã cứu người bạn trong ngày của tôi, bạn là một anh hùng
Asif Ali

1
Bằng cách nào đó, tất cả các câu trả lời khác trên tất cả các bài viết khác về việc sử dụng sizeForItemAtkhông đề cập đến điều này. Rất hữu ích.
JCutting8

Điều này là điên!!!! Tôi đã thử nghiệm trên trình mô phỏng iPhone 5 với phiên bản iOS 10.3.1 và phương pháp này được gọi. trên iPhone 5s giả lập với phiên bản 10.3.1 phương pháp không được gọi !!! Tôi đã thay đổi Kích thước Ước tính thành Không có. Nó bắt đầu được gọi trên iPhone 5s. WT WT WT
hasan

Cảm ơn rất nhiều! Chế độ xem bộ sưu tập của tôi với tùy chỉnh sizeForItemAthoạt động tốt cho đến Xcode 11.4 thì đột nhiên các ô có chiều rộng sai. Đã thử nhiều thứ và điều này cuối cùng đã thành công.
Filip

Bạn đã tiết kiệm thời gian của tôi. Cảm ơn rất nhiều.
Shahbaz Akram

15

Swift 3

Để đặt Kích thước ô của UICollectionView, bạn cần tạo và tùy chỉnh đối tượng của UICollectionViewFlowLayout. Tùy chỉnh các thuộc tính và đặt đối tượng bố trí đó thành đối tượng UICollectionView.

Thay đổi các đối tượng cellheight và cell cellWidth theo yêu cầu của bạn (chiều cao và chiều rộng của ô bạn muốn).

override func viewDidLoad() {
    super.viewDidLoad()

    let cellWidth : CGFloat = myCollectionView.frame.size.width / 4.0
    let cellheight : CGFloat = myCollectionView.frame.size.height - 2.0
    let cellSize = CGSize(width: cellWidth , height:cellheight)

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical //.horizontal
    layout.itemSize = cellSize
    layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
    layout.minimumLineSpacing = 1.0
    layout.minimumInteritemSpacing = 1.0
    myCollectionView.setCollectionViewLayout(layout, animated: true)

    myCollectionView.reloadData()
}

Hãy chắc chắn rằng: nếu bạn đã thêm phương thức sizeForItemAt indexPath thì phải XÓA phương thức ...

Loại bỏ phương pháp bên dưới

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

}

12
Làm thế nào là điều này hữu ích?
almas

1
Almas, Điều này sẽ hữu ích cho việc đặt kích thước ô tùy chỉnh của UICollectionViewCell ... Có các biến cellWidth và cellHeight, trong đó bạn có thể xác định các giá trị của riêng mình ... Cũng như "layout.sectionInset", "layout.minimumLineSpacing" và "layout .minimumInteritemSpacing ", những biến này cũng quan trọng đối với kích thước UICollectionViewCell ..
Gaurav Rami

2
Điều này chỉ hoạt động nếu tất cả các ô có cùng kích thước. Câu trả lời dưới đây là câu trả lời chính xác
JeffN

đây là để thay đổi kích thước của UICollectionView nhưng không phải là tế bào bên trong view
Async-

Đây không phải là một câu trả lời cho lý do tại sao các phương pháp đại biểu không được gọi
Ziv Kesten

12

Swift 5

Tất cả các bước này là bắt buộc :

  1. Tuân theo UICollectionViewDelegateFlowLayout <== Hoàn toàn cần thiết !!
  2. và để UICollectionViewDelegate, UICollectionViewDataSource
  3. Đặt chúng trong viewDidLoad: collectionView.delegate = selfcollectionView.dataSource = self
  4. Đặt Kích thước Ước tính thành Không có trong Trình tạo Giao diện
  5. Đảm bảo rằng phương thức sau có sizeForItemAt chứ không phải sizeForItemAtIndexPath

như :

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

2
Ước tính Kích thước thành Không có - tiết kiệm ngày của tôi!
Joe Hallenbeck

6

Lớp đầu tiên cần xác nhận với UICollectionViewDelegateFlowLayout. Sau đó, bạn cần viết mã sau trong viewDidLoad ():

// Để yêu cầu UICollectionView sử dụng các phương thức UICollectionViewDelegateFlowLayout của UIViewController

collectionView.delegate = self

// Nếu bạn muốn đặt bố cục luồng chế độ xem bộ sưu tập của riêng mình

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //depending upon direction of collection view

self.collectionView?.setCollectionViewLayout(layout, animated: true)

Bằng cách sử dụng phương pháp UICollectionViewDelegateFlowLayout mã này

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

sẽ được gọi, bạn có thể đặt kích thước trong phương thức này.


4

Ba điều bạn cần kiểm tra nếu không có câu trả lời nào hoạt động:

  1. Triển khai FlowLayout Delegate: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Sử dụng phương pháp cho kích thước của mặt hàng cho nhanh chóng 3.0+: func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: (collectionView.frame.width / 3) - 1, height: collectionView.frame.width) }

  3. Chọn Estimate size = Nonetrong Kiểm tra phần tử của UICollectionView.


2

Tôi đã gặp vấn đề tương tự và không có gì sẽ sửa chữa nó. Tôi đã có một cảnh báo màu vàng nói rằng hãy đặt nó ở chế độ riêng tư vì nó gần với một chức năng khác được xác định bởi Layout Delegate. Điều đã sửa nó cho tôi là:

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

Lưu ý sự khác biệt từ "sizeForItemAtIndexPath" với "sizeForItemAt" chính xác.

Tôi đã vò đầu bứt tóc trong nhiều ngày để cố gắng tìm ra điều này và cuối cùng nó đã thành công. Dưới đây tôi sẽ bao gồm tất cả các chức năng của tôi để cho bạn thấy cách tôi cũng "ẩn" một ô bằng cách làm cho chiều cao bằng 0.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let findIndex = labelArray.index(of: "\(labelArray[indexPath.row])")
    let screenSize = UIScreen.main.bounds
    let screenWidth = screenSize.width

    if (findIndex! % 2 == 0){
        // Even index, show cell
        return CGSize(width: screenWidth, height: 246)
    }
    else {
        return CGSize(width: screenWidth, height: 0)
    }
}

0

Tôi đã có vấn đề này đêm qua. Cuối cùng đã giải quyết được nó vào lúc nửa đêm khi tôi nhận ra rằng phương thức 'didSelectItemAtIndex' không được đóng bằng dấu ngoặc nhọn "}"

Tôi đã thêm một dấu ngoặc nhọn ở cuối lớp khi được hỏi bởi lỗi biên dịch. Vì vậy, trên thực tế, tất cả các phương thức bên dưới 'didSelectItemAtIndex' đều nằm trong phương thức đó.

Đăng ở đây để đề phòng trường hợp có ai khác lãng phí 4 giờ buổi tối của họ cho cái này :-(


0

Đảm bảo rằng bạn đã đặt nó vào viewDidLoad ()

collectionView.delegate = self

0

vấn đề của tôi là tôi đã tạo đối tượng UICollectionViewDataSource dưới dạng biến cục bộ. Vì vậy, nếu bạn khởi tạo đối tượng dataSource của mình theo cách thủ công trong mã, hãy đảm bảo lưu trữ nó dưới dạng biến toàn cục.


0

Sử dụng phương pháp này

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

}

Thay vì

private func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

}

0

Chỉ cần thêm: UICollectionViewDelegateFlowLayout

class YourClass: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {}

-11

Đối với tôi (trong Swift 3.1), phương thức phải được khai báo công khai như thế này:

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

Đừng quên công khai .


publiclà những gì bạn sử dụng để làm cho mã của bạn có thể truy cập được giữa các khung và mô-đun.
ScottyBlades
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.