UICollectionView bên trong UITableViewCell - chiều cao động?


125

Một trong các màn hình ứng dụng của chúng tôi yêu cầu chúng tôi đặt UICollectionViewbên trong một UITableViewCell. Điều này UICollectionViewsẽ có một số mục động, dẫn đến chiều cao cũng phải được tính toán động. Tuy nhiên, tôi đang gặp sự cố khi cố gắng tính toán chiều cao của phần nhúng UICollectionView.

Tính năng bao quát của chúng tôi UIViewControllerđã được tạo trong Bảng phân cảnh và sử dụng bố cục tự động. Nhưng, tôi không biết làm thế nào để tăng chiều cao động UITableViewCelldựa trên chiều cao của UICollectionView.

Bất cứ ai có thể đưa ra một số mẹo hoặc lời khuyên về cách thực hiện điều này?


bạn có thể nói thêm một chút về bố cục mà bạn đang cố gắng thực hiện không? Chiều cao của biểu tượng có UITableViewCellkhác với chế độ xem bảng acutal của nó không? Bạn có cần di chuyển dọc trên cả UICollectionViewUITableView
apouche

3
Chiều cao của UITableViewCell được cho là động, dựa trên chiều cao của UICollectionView là một phần của ô xem bảng. Bố cục của UICollectionView của tôi là 4 cột và một số hàng động. Vì vậy, với 100 mục, tôi sẽ có 4 cột và 25 hàng trong UICollectionView của mình. Chiều cao của ô cụ thể - như được chỉ ra bởi heightForRowAtIndexPath của UITableView - cần có thể điều chỉnh dựa trên kích thước của UICollectionView đó. Đó là một chút rõ ràng hơn?
Shadowman

@Shadowman, vui lòng đề xuất cho tôi giải pháp cho tình huống này
Ravi Ojha

Câu trả lời:


127

Câu trả lời đúng là , bạn CÓ THỂ làm điều này.

Tôi đã gặp vấn đề này vài tuần trước. Nó thực sự dễ dàng hơn bạn có thể nghĩ. Đặt các ô của bạn vào NIB (hoặc bảng phân cảnh) và ghim chúng để cho phép bố cục tự động thực hiện tất cả công việc

Cho cấu trúc sau:

TableView

TableViewCell

CollectionView

CollectionViewCell

CollectionViewCell

CollectionViewCell

[... số lượng ô thay đổi hoặc các kích thước ô khác nhau]

Giải pháp là yêu cầu bố cục tự động tính toán kích thước collectionViewCell trước tiên, sau đó đến contentSize của chế độ xem bộ sưu tập và sử dụng nó làm kích thước ô của bạn. Đây là phương pháp UIView "làm nên điều kỳ diệu":

-(void)systemLayoutSizeFittingSize:(CGSize)targetSize 
     withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority 
           verticalFittingPriority:(UILayoutPriority)verticalFittingPriority

Bạn phải đặt ở đây kích thước của TableViewCell, trong trường hợp của bạn là kích thước contentSize của CollectionView.

CollectionViewCell

Tại CollectionViewCell, bạn phải yêu cầu ô bố cục mỗi khi bạn thay đổi mô hình (ví dụ: bạn đặt UILabel bằng văn bản, sau đó ô phải được bố trí lại).

- (void)bindWithModel:(id)model {
    // Do whatever you may need to bind with your data and 
    // tell the collection view cell's contentView to resize
    [self.contentView setNeedsLayout];
}
// Other stuff here...

TableViewCell

Các TableViewCell làm sự kỳ diệu. Nó có một lối ra cho collectionView của bạn, cho phép bố trí tự động cho các ô collectionView bằng cách sử dụng Kích thước ước tính của UICollectionViewFlowLayout .

Sau đó, mẹo là đặt kích thước ô tableView của bạn tại phương thức systemLayoutSizeFittingSize .... (LƯU Ý: iOS8 trở lên)

LƯU Ý: Tôi đã cố gắng sử dụng phương pháp chiều cao của ô đại biểu của tableView -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath. Nhưng đã quá muộn để hệ thống bố cục tự động tính toán CollectionView contentSize và đôi khi bạn có thể tìm thấy các ô được thay đổi kích thước sai.

@implementation TableCell

- (void)awakeFromNib {
    [super awakeFromNib];
    UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;

    // Configure the collectionView
    flow.minimumInteritemSpacing = ...;

    // This enables the magic of auto layout. 
    // Setting estimatedItemSize different to CGSizeZero 
    // on flow Layout enables auto layout for collectionView cells.
    // https://developer.apple.com/videos/play/wwdc2014-226/
    flow.estimatedItemSize = CGSizeMake(1, 1);

    // Disable the scroll on your collection view
    // to avoid running into multiple scroll issues.
    [self.collectionView setScrollEnabled:NO];
}

- (void)bindWithModel:(id)model {
    // Do your stuff here to configure the tableViewCell
    // Tell the cell to redraw its contentView        
    [self.contentView layoutIfNeeded];
}

// THIS IS THE MOST IMPORTANT METHOD
//
// This method tells the auto layout
// You cannot calculate the collectionView content size in any other place, 
// because you run into race condition issues.
// NOTE: Works for iOS 8 or later
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority {

    // With autolayout enabled on collection view's cells we need to force a collection view relayout with the shown size (width)
    self.collectionView.frame = CGRectMake(0, 0, targetSize.width, MAXFLOAT);
    [self.collectionView layoutIfNeeded];

    // If the cell's size has to be exactly the content 
    // Size of the collection View, just return the
    // collectionViewLayout's collectionViewContentSize.

    return [self.collectionView.collectionViewLayout collectionViewContentSize];
}

// Other stuff here...

@end

TableViewController

Hãy nhớ kích hoạt hệ thống bố cục tự động cho các ô tableView trong TableViewController của bạn :

- (void)viewDidLoad {
    [super viewDidLoad];

    // Enable automatic row auto layout calculations        
    self.tableView.rowHeight = UITableViewAutomaticDimension;
    // Set the estimatedRowHeight to a non-0 value to enable auto layout.
    self.tableView.estimatedRowHeight = 10;

}

CREDIT: @rbarbera đã giúp giải quyết vấn đề này


4
Vâng. Những công việc này. Đây phải là câu trả lời được chấp nhận.
csotiriou

1
Bất kỳ cơ quan có thể cung cấp cho tôi một mã mẫu cho nó? tôi muốn hiển thị nhiều hình ảnh trong bộ sưu tập nhìn thẳng đứng, mà là bên trong tế bào tableview ..
Ravi Ojha

4
Cuối cùng thì điều này cũng hiệu quả với tôi, nhưng tôi phải thực hiện một thủ thuật khác: cell.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 10000);Điều này sẽ "mô phỏng" một ô dài với một collectionView dài, vì vậy, collectionView sẽ tính toán kích thước tất cả các ô của nó. Nếu không, collectionView chỉ tính kích thước ô hiển thị và đặt sai chiều cao talbeViewCell.
ingaham

20
khi đặt chiều cao khung hình thành tối đa systemLayoutSizeFittingSize, tôi gặp sự cố nhanh chóng khi tải lại ô, các ứng dụng dường như bị kẹt sau self.collectionView.layoutIfNeeded(). Tôi đã sửa nó bằng cách đặt chiều cao khung bằng 1 thay vì chiều cao tối đa. Hy vọng nó sẽ giúp nếu bất cứ ai vấp ngã trong vấn đề này.
titan

6
Đây là những gì cố định nó cho tôi - trong systemLayoutSizeFitting, đảo ngược thứ tự của những gì đang thể hiện trong câu trả lời hiện nay, do đó đầu tiên collectionView.layoutIfNeeded()chạy, sau đócollectionView.frame = CGRect.init(origin: .zero, size: CGSize.init(width: targetSize.width, height: 1))
xaphod

101

Tôi nghĩ rằng giải pháp của tôi đơn giản hơn nhiều so với giải pháp được đề xuất bởi @PabloRomeu.

Bước 1. Tạo lối ra từ UICollectionViewđến UITableViewCell subclass, nơi UICollectionViewđược đặt. Hãy để, tên của nó sẽ làcollectionView

Bước 2. Thêm IB để UICollectionViewhạn chế chiều cao và tạo cả lối ra UITableViewCell subclass. Hãy để, tên của nó sẽ là collectionViewHeight.

Bước 3. tableView:cellForRowAtIndexPath:Thêm mã:

// deque a cell
cell.frame = tableView.bounds;
[cell layoutIfNeeded];
[cell.collectionView reloadData];
cell.collectionViewHeight.constant = cell.collectionView.collectionViewLayout.collectionViewContentSize.height;

1
Bạn đã thực sự thử điều này chưa? Có vẻ như không thể vừa đặt giới hạn chiều cao trên chế độ xem bộ sưu tập vừa ghim nó vào lề của ô chế độ xem bảng. Bạn có thể kết thúc với quá ít ràng buộc (do đó có cảnh báo kích thước bằng không) hoặc bạn kết thúc với các ràng buộc xung đột (một trong số đó bị bỏ qua). Vui lòng giải thích cách thiết lập các ràng buộc cho giải pháp này.
Dale

2
Tôi đã làm việc. Tôi thêm các ràng buộc cho collectionViewtất cả các mặt của UITableViewCellvà đặt tableView.estimatedRowHeight = 44;tableView.rowHeight = UITableViewAutomaticDimension;
Igor

3
Cái này hoạt động giống như nhà vô địch ... đơn giản và hiệu quả ... cảm ơn bạn. Nếu đối với ai đó, nó không hoạt động thì có lẽ lý do là, chúng ta cần liên kết ô dưới cùng của chế độ xem bộ sưu tập với ô dưới cùng của chế độ xem bảng. Sau đó, nó sẽ bắt đầu hoạt động. Chúc bạn viết mã vui vẻ .. :)
Sebin Roy 13/10/16

2
Điều này có hoạt động khi màn hình được thay đổi kích thước, chẳng hạn bằng cách xoay iPad? Điều đó có khả năng thay đổi chiều cao của chế độ xem bộ sưu tập và do đó là chiều cao của ô, nhưng nếu trên màn hình, ô đó có thể không nhất thiết phải được tải lại bởi chế độ xem bảng, do đó không bao giờ gọi phương thức cellForRowAtIndexPath: và không cho bạn cơ hội thay đổi hằng số ràng buộc. Tuy nhiên, có thể buộc phải tải lại Dữ liệu.
Carl Lindberg

2
Bạn đã thử các kích thước ô collectionView khác nhau chưa? Đó là vấn đề của tôi. Nếu bạn có các kích thước ô khác nhau của collectionView, nó không hoạt động ... :(
Pablo Romeu

22

Cả chế độ xem bảng và chế độ xem bộ sưu tập đều là các UIScrollViewlớp con và do đó không thích được nhúng vào bên trong một chế độ xem cuộn khác khi chúng cố gắng tính toán kích thước nội dung, sử dụng lại các ô, v.v.

Tôi khuyên bạn chỉ nên sử dụng chế độ xem bộ sưu tập cho mọi mục đích của mình.

Bạn có thể chia nó thành các phần và "coi" bố cục của một số phần là dạng xem bảng và các phần khác là dạng xem bộ sưu tập. Rốt cuộc, không có gì bạn không thể đạt được với chế độ xem bộ sưu tập mà bạn có thể làm với chế độ xem bảng.

Nếu bạn có bố cục lưới cơ bản cho "các bộ phận" trong chế độ xem bộ sưu tập của mình, bạn cũng có thể sử dụng các ô bảng thông thường để xử lý chúng. Tuy nhiên, nếu bạn không cần hỗ trợ iOS 5, bạn nên sử dụng chế độ xem bộ sưu tập.


1
Bạn đã đặt "xử lý" trong dấu ngoặc kép, vì bạn KHÔNG thể xác định các bố cục khác nhau cho mỗi phần CollectionView, phải không? Tôi không tìm thấy tùy chọn để xác định các bố cục khác nhau cho các phần xem bộ sưu tập khác nhau. Tôi đang bỏ qua điều gì đó hay bạn đang nói về việc phản hồi khác với 'layoutAttributesForItemAtIndexPath' cho các phần khác nhau trong lớp con tùy chỉnh của riêng tôi về UICollectionViewLayout?
alex da franca

Có -> Bạn đang nói về việc phản hồi khác nhau đối layoutAttributesForItemAtIndexPathvới các phần khác nhau trong lớp con tùy chỉnh của riêng tôi UICollectionViewLayout?
Rivera

2
@Rivera, câu trả lời của bạn là hợp lý nhất và nghe có vẻ đúng. Tôi đã đọc gợi ý này trên nhiều nơi. Bạn cũng có thể chia sẻ một số liên kết đến mẫu hoặc giới thiệu về cách thực hiện điều đó hoặc ít nhất là một số gợi ý. TIA
thesummersign

3
Câu trả lời của bạn giả định rằng bạn đang bắt đầu lại từ đầu và chưa có một bảng tổng hợp phức tạp lớn mà bạn cần phải phù hợp. Câu hỏi được hỏi cụ thể về cách đặt chế độ xem bộ sưu tập trong chế độ xem bảng. IMO câu trả lời của bạn không phải là "câu trả lời"
xaphod 14/09/17

2
Đây là một câu trả lời tồi. Có chế độ xem bộ sưu tập bên trong chế độ xem bảng là một điều phổ biến phải làm, hầu hết mọi ứng dụng đều làm điều đó.
crashhoverride777

10

Câu trả lời của Pablo Romeu ở trên ( https://stackoverflow.com/a/33364092/2704206 ) đã giúp tôi rất nhiều trong vấn đề của mình. Tuy nhiên, tôi đã phải làm một số việc khác nhau để điều này có hiệu quả với vấn đề của tôi. Đầu tiên, tôi không phải gọi điện layoutIfNeeded()thường xuyên. Tôi chỉ phải gọi nó trên hàm collectionViewtrong systemLayoutSizeFitting.

Thứ hai, tôi có các ràng buộc bố cục tự động trên chế độ xem bộ sưu tập của mình trong ô chế độ xem bảng để tạo cho nó một số khoảng đệm. Vì vậy, tôi đã phải trừ các lề đầu và lề targetSize.widthkhi thiết lập collectionView.framechiều rộng của. Tôi cũng phải thêm lề trên và dưới vào CGSizechiều cao giá trị trả về .

Để có được các hằng số ràng buộc này, tôi có tùy chọn tạo các cửa hàng cho các ràng buộc, mã hóa cứng các hằng số của chúng hoặc tìm kiếm chúng bằng một mã định danh. Tôi quyết định sử dụng tùy chọn thứ ba để làm cho lớp ô chế độ xem bảng tùy chỉnh của tôi có thể dễ dàng sử dụng lại. Cuối cùng, đây là mọi thứ tôi cần để nó hoạt động:

class CollectionTableViewCell: UITableViewCell {

    // MARK: -
    // MARK: Properties
    @IBOutlet weak var collectionView: UICollectionView! {
        didSet {
            collectionViewLayout?.estimatedItemSize = CGSize(width: 1, height: 1)
            selectionStyle = .none
        }
    }

    var collectionViewLayout: UICollectionViewFlowLayout? {
        return collectionView.collectionViewLayout as? UICollectionViewFlowLayout
    }

    // MARK: -
    // MARK: UIView functions
    override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        collectionView.layoutIfNeeded()

        let topConstraintConstant = contentView.constraint(byIdentifier: "topAnchor")?.constant ?? 0
        let bottomConstraintConstant = contentView.constraint(byIdentifier: "bottomAnchor")?.constant ?? 0
        let trailingConstraintConstant = contentView.constraint(byIdentifier: "trailingAnchor")?.constant ?? 0
        let leadingConstraintConstant = contentView.constraint(byIdentifier: "leadingAnchor")?.constant ?? 0

        collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width - trailingConstraintConstant - leadingConstraintConstant, height: 1)

        let size = collectionView.collectionViewLayout.collectionViewContentSize
        let newSize = CGSize(width: size.width, height: size.height + topConstraintConstant + bottomConstraintConstant)
        return newSize
    }
}

Là một chức năng trợ giúp để truy xuất một ràng buộc theo mã định danh, tôi thêm phần mở rộng sau:

extension UIView {
    func constraint(byIdentifier identifier: String) -> NSLayoutConstraint? {
        return constraints.first(where: { $0.identifier == identifier })
    }
}

LƯU Ý: Bạn sẽ cần đặt số nhận dạng cho các ràng buộc này trong bảng phân cảnh của mình hoặc bất cứ nơi nào chúng đang được tạo. Trừ khi chúng có hằng số 0, thì điều đó không quan trọng. Ngoài ra, như trong phản hồi của Pablo, bạn sẽ cần sử dụng UICollectionViewFlowLayoutlàm bố cục cho chế độ xem bộ sưu tập của mình. Cuối cùng, đảm bảo bạn liên kết collectionViewIBOutlet với bảng phân cảnh của mình.

Với ô chế độ xem bảng tùy chỉnh ở trên, bây giờ tôi có thể phân lớp nó trong bất kỳ ô chế độ xem bảng nào khác cần chế độ xem bộ sưu tập và để nó triển khai các giao thức UICollectionViewDelegateFlowLayoutUICollectionViewDataSource. Hy vọng điều này sẽ hữu ích cho người khác!


5

Tôi đọc qua tất cả các câu trả lời. Điều này dường như phục vụ tất cả các trường hợp.

override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        collectionView.layoutIfNeeded()
        collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width , height: 1)
        return collectionView.collectionViewLayout.collectionViewContentSize
}

3

Một giải pháp thay thế cho giải pháp của Pablo Romeu là tùy chỉnh chính UICollectionView, thay vì thực hiện công việc trong ô xem bảng.

Vấn đề cơ bản là theo mặc định, chế độ xem bộ sưu tập không có kích thước nội tại và do đó không thể thông báo bố cục tự động về các kích thước sẽ sử dụng. Bạn có thể khắc phục điều đó bằng cách tạo một lớp con tùy chỉnh trả về một kích thước nội tại hữu ích.

Tạo một lớp con của UICollectionView và ghi đè các phương thức sau

override func intrinsicContentSize() -> CGSize {
    self.layoutIfNeeded()

    var size = super.contentSize
    if size.width == 0 || size.height == 0 {
        // return a default size
        size = CGSize(width: 600, height:44)
    }

    return size
 }

override func reloadData() {
    super.reloadData()
    self.layoutIfNeeded()
    self.invalidateIntrinsicContentSize()
}

(Bạn cũng nên ghi đè các phương thức liên quan: reloadSices, reloadItemsAtIndexPaths theo cách tương tự như reloadData ())

Việc gọi layoutIfNeeded buộc chế độ xem bộ sưu tập phải tính toán lại kích thước nội dung mà sau đó có thể được sử dụng làm kích thước nội tại mới.

Ngoài ra, bạn cần xử lý rõ ràng các thay đổi đối với kích thước chế độ xem (ví dụ: xoay thiết bị) trong bộ điều khiển chế độ xem bảng

    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
{
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    dispatch_async(dispatch_get_main_queue()) {
        self.tableView.reloadData()
    }
}

bạn có thể vui lòng giúp đỡ vấn đề của tôi stackoverflow.com/questions/44650058/… ?
Tháng

3

Gần đây, tôi đang gặp phải vấn đề tương tự và tôi gần như đã thử mọi giải pháp trong các câu trả lời, một số giải pháp trong số đó có hiệu quả và những giải pháp khác không phải là mối quan tâm chính của tôi về cách tiếp cận @PabloRomeu là nếu bạn có nội dung khác trong ô (ngoài chế độ xem bộ sưu tập) bạn sẽ phải tính toán chiều cao của chúng và độ cao của các ràng buộc của chúng và trả về kết quả để có được bố cục tự động đúng và tôi không thích tính toán mọi thứ theo cách thủ công trong mã của mình. Vì vậy, đây là giải pháp phù hợp với tôi mà không cần thực hiện bất kỳ tính toán thủ công nào trong mã của tôi.

trong cellForRow:atIndexPathchế độ xem bảng, tôi làm như sau:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //do dequeue stuff
    //initialize the the collection view data source with the data
    cell.frame = CGRect.zero
    cell.layoutIfNeeded()
    return cell
}

Tôi nghĩ rằng điều xảy ra ở đây là tôi buộc ô trong chế độ xem bảng điều chỉnh chiều cao của nó sau khi chiều cao của chế độ xem bộ sưu tập đã được tính toán. (sau khi cung cấp ngày collectionView cho nguồn dữ liệu)


2

Tôi sẽ đặt một phương thức tĩnh trên lớp dạng xem bộ sưu tập sẽ trả về kích thước dựa trên nội dung mà nó sẽ có. Sau đó sử dụng phương thức đó heightForRowAtIndexPathđể trả về kích thước thích hợp.

Cũng lưu ý rằng bạn có thể gặp một số hành vi kỳ lạ khi nhúng các loại viewControllers này. Tôi đã làm điều đó một lần và có một số vấn đề về trí nhớ kỳ lạ mà tôi chưa bao giờ giải quyết.


Đối với tôi, tôi đang cố gắng nhúng bộ điều khiển chế độ xem bảng bên trong bộ điều khiển chế độ xem bộ sưu tập. Mỗi khi một ô được sử dụng lại, nó sẽ ghi nhớ một số ràng buộc tự động thanh toán mà tôi đã áp dụng cho chúng. Nó rất khó hiểu và cuối cùng là một ý tưởng khủng khiếp. Tôi nghĩ rằng tôi sẽ chỉ sử dụng một chế độ xem bộ sưu tập duy nhất để thay thế.
fatuhoku

2

Có thể biến thể của tôi sẽ hữu ích; tôi đã quyết định nhiệm vụ này trong suốt hai giờ qua. Tôi không giả vờ nó đúng hoặc tối ưu 100%, nhưng kỹ năng của tôi còn rất nhỏ và tôi muốn nghe ý kiến ​​từ các chuyên gia. Cảm ơn bạn. Một lưu ý quan trọng: điều này hoạt động đối với bảng tĩnh - nó được chỉ định bởi công việc hiện tại của tôi. Vì vậy, tất cả những gì tôi sử dụng là viewWillLayoutSubviews của tableView . Và một chút nữa.

private var iconsCellHeight: CGFloat = 500 

func updateTable(table: UITableView, withDuration duration: NSTimeInterval) {
    UIView.animateWithDuration(duration, animations: { () -> Void in
        table.beginUpdates()
        table.endUpdates()
    })
}

override func viewWillLayoutSubviews() {
    if let iconsCell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 1)) as? CategoryCardIconsCell {
        let collectionViewContentHeight = iconsCell.iconsCollectionView.contentSize.height
        if collectionViewContentHeight + 17 != iconsCellHeight {
            iconsCellHeight = collectionViewContentHeight + 17
            updateTable(tableView, withDuration: 0.2)
        }
    }
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch (indexPath.section, indexPath.row) {
        case ...
        case (1,0):
            return iconsCellHeight
        default:
            return tableView.rowHeight
    }
}
  1. Tôi biết rằng collectionView nằm ở hàng đầu tiên của phần thứ hai;
  2. Cho chiều cao của hàng là 17 p. lớn hơn chiều cao nội dung của nó;
  3. iconCellHeight là một số ngẫu nhiên khi chương trình bắt đầu (tôi biết, ở dạng dọc, nó phải chính xác là 392, nhưng nó không quan trọng). Nếu nội dung của collectionView + 17 không bằng số này, thì hãy thay đổi giá trị của nó. Lần tới trong tình huống này, điều kiện đưa ra FALSE;
  4. Sau tất cả, hãy cập nhật tableView. Trong trường hợp của tôi, đó là sự kết hợp của hai thao tác (để cập nhật tốt các hàng mở rộng);
  5. Và tất nhiên, trong heightForRowAtIndexPath hãy thêm một hàng vào mã.

2

Cách tiếp cận dễ nhất mà tôi đã nghĩ ra cho đến nay, Tín dụng cho câu trả lời @igor ở trên,

Trong lớp tableviewcell của bạn, chỉ cần chèn cái này

override func layoutSubviews() {
    self.collectionViewOutlet.constant = self.postPoll.collectionViewLayout.collectionViewContentSize.height
}

và tất nhiên, thay đổi bộ sưu tập với cửa hàng của bạn trong lớp của ô


1
Chiều cao của tế bào không tính toán đúng
Nik Kov

2

Tôi lấy ý tưởng từ bài đăng @Igor và đầu tư thời gian vào việc này cho dự án của mình một cách nhanh chóng

Chỉ qua cái này trong của bạn

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //do dequeue stuff
    cell.frame = tableView.bounds
    cell.layoutIfNeeded()
    cell.collectionView.reloadData()
    cell.collectionView.heightAnchor.constraint(equalToConstant: cell.collectionView.collectionViewLayout.collectionViewContentSize.height)
    cell.layoutIfNeeded()
    return cell
}

Bổ sung: Nếu bạn thấy UICollectionView của mình bị giật khi tải các ô.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {       
  //do dequeue stuff
  cell.layer.shouldRasterize = true
  cell.layer.rasterizationScale = UIScreen.main.scale
  return cell
}

0

Giải pháp của Pablo không hoạt động tốt với tôi, tôi có những hiệu ứng hình ảnh kỳ lạ (collectionView không điều chỉnh chính xác).

Điều hoạt động là điều chỉnh giới hạn chiều cao của collectionView (dưới dạng NSLayoutConstraint) đối với contentSize trong collectionView layoutSubviews(). Đây là phương thức được gọi khi tự động thanh toán được áp dụng cho ô.

// Constraint on the collectionView height in the storyboard. Priority set to 999.
@IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!


// Method called by autolayout to layout the subviews (including the collectionView).
// This is triggered with 'layoutIfNeeded()', or by the viewController
// (happens between 'viewWillLayoutSubviews()' and 'viewDidLayoutSubviews()'.
override func layoutSubviews() {

    collectionViewHeightConstraint.constant = collectionView.contentSize.height
    super.layoutSubviews()
}

// Call `layoutIfNeeded()` when you update your UI from the model to trigger 'layoutSubviews()'
private func updateUI() {
    layoutIfNeeded()
}

-3

Trong UITableViewDelegate của bạn:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return ceil(itemCount/4.0f)*collectionViewCellHeight;
}

Thay thế itemCount và CollectionViewCellHeight bằng các giá trị thực. Nếu bạn có một mảng mảng, itemCount có thể là:

self.items[indexPath.row].count

Hay bất cứ cái gì.


Tôi nghĩ câu hỏi chính là làm thế nào để tính toán collectionViewCellHeight trước khi nó hiển thị.
thesummersign

-3

1.Tạo ô giả.
2.Sử dụng phương thức collectionViewContentSize trên UICollectionViewLayout của UICollectionView sử dụng dữ liệu hiện tại.


Đó phải là câu trả lời tốt nhất ... vì không có khả năng đặt chiều cao của ô bằng 'uicollectionview' mà không đặt nội dung vào ô giả, lấy chiều cao, rồi đặt lại thành ô thích hợp
Bartłomiej Semańczyk

làm thế nào để tôi sử dụng phương pháp đó?
xtrinch

Thêm một ví dụ.
Nik Kov

-5

Bạn có thể tính toán chiều cao của bộ sưu tập dựa trên thuộc tính của nó như itemSize, sectionInset, minimumLineSpacing, minimumInteritemSpacing, nếu bạn collectionViewCellcó biên giới của một quy tắc.

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.