简体   繁体   English

更改基于 UICollectionView 内容大小高度的 UITableViewCell 高度

[英]Change UITableViewCell Height based UICollectionView content size height

I'm working on a calendar created with a UICollectionView .我正在处理使用UICollectionView创建的日历。

The UICollectionView is located inside a UITableViewCell The UITableViewCell in the heightForRowAt method return UITableView.automaticDimensionUICollectionView位于内部UITableViewCellUITableViewCellheightForRowAt方法return UITableView.automaticDimension

The UICollectionView used to create the calendar updates its height based on how many days are shown, for example the month of November has its first day which falls on Sunday so to place the day under the label "Sunday" the collectionView must necessarily add a whole line.用于创建日历的UICollectionView根据显示的天数更新其高度,例如11 月第一天落在星期日,因此要将这一天放置在标签“星期日”下collectionView必须添加一个整体线。

Normally each month has 5 rows (week) but when the first day of the month happens on Sunday the collectionview returns 6通常每个月有 5 行(周)但是当月第一天发生在星期日时collectionview返回 6

Now as I said I was able to update the height of the UICollectionView based on how many rows it returns but I cannot dynamically change the height of the TableViewCell that contains the collectionView现在正如我所说,我能够根据它返回的行数更新UICollectionView的高度,但我无法动态更改包含collectionViewTableViewCell高度

How can I resize the tableViewCell based on the height of the CollectionView within it?如何根据其中的CollectionView的高度调整tableViewCell的大小?


EDIT编辑

my cell我的手机

在此处输入图片说明


I have set UITableView.automaticDimension for the height of the cell that contains the CalendarView我已经为包含CalendarView的单元格的高度设置了UITableView.automaticDimension

在此处输入图片说明

In the class CalendarView: UIView I created a variable CGFloat calendarH to set the default height of the collectionView在类CalendarView: UIView我创建了一个变量 CGFloat calendarH 来设置 collectionView 的默认高度

在此处输入图片说明

CollectionView implementation集合视图实现

在此处输入图片说明

I have added an observer which tracks the height of the collctionView when it changes我添加了一个观察者,它在collctionView发生变化时跟踪它的高度

在此处输入图片说明

I am currently able to change the height of the collectionView but its superview ( bookingCalendarView ) and the tableView cell continue to remain with a fixed height and do not adapt to the collectionView我目前可以更改collectionView的高度,但它的bookingCalendarView视图( bookingCalendarView )和 tableView 单元格继续保持固定高度并且不适应collectionView

You need to create an @IBOutlet for your collection view's height constraint.您需要为集合视图的高度约束创建一个@IBOutlet

When you set a row's calendar / month data, determine whether you need 5 or 6 rows.当您设置一行的日历/月份数据时,请确定您需要 5 行还是 6 行。

If it's 6, set the .constant on the height constraint to 750如果是 6,则将高度约束上的.constant设置为750

If it's 5, set the .constant on the height constraint to 675如果是 5,则将高度约束上的.constant设置为675


Edit编辑

First, I'm going to suggest you forget about using a "self-sizing" collection view.首先,我将建议您忘记使用“自我调整大小”的集合视图。 UICollectionView is designed to lay out cells based on the size of the collection view , providing automatic scrolling when there are too many cells. UICollectionView旨在根据集合视图的大小对单元格进行布局,在单元格过多时提供自动滚动。

Trying to "self-size" it may work in one instance, but fail in another.尝试“自我调整”它可能在一种情况下有效,但在另一种情况下会失败。 The reason it fails in this case is because your table view lays out the cell and calculates its height before the collection view is populated, and thus before it can "self-size."在这种情况下它失败的原因是因为您的表格视图填充集合视图之前布置了单元格并计算了它的高度,因此在它可以“自我调整大小”之前。

Instead, since you know your cell Height is 75, you can calculate how many rows your calendar will need and either set the .constant on a height constraint for your collection view, or (since you're already using heightForRowAt ) calculate the row height there.相反,因为你知道你的单元格高度是 75,你可以计算你的日历需要多少行,或者在你的集合视图的高度约束上设置.constant ,或者(因为你已经在使用heightForRowAt )计算行高那里。

Look at this code:看看这段代码:

let dateComponents = DateComponents(year: year, month: month)
        
// startDate will be the first date of the month (Jan 1, Feb 1, Mar 1, etc...)
guard let startDate = calendar.date(from: dateComponents) else {
    fatalError("Something is wrong with the date!")
}
// get the range of days in the month
guard let range = calendar.range(of: .day, in: .month, for: startDate) else {
    fatalError("Something is wrong with the date!")
}
        
// get number of days in the month
let numberOfDaysInMonth = range.count
        
// get the day of the week for the first date in the month
//  this returns 1-based numbering
//  Nov 1, 2020 was a Sunday, so this would return 1
let startDayOfWeek = Calendar.current.component(.weekday, from: startDate)
        
// add the "leading days to the start date"
//  so, if startDayOfWeek == 3 (Tuesday)
//  we need to add 2 "empty day cells" for Sunday and Monday
let totalCellsNeeded = numberOfDaysInMonth + (startDayOfWeek - 1)
        
// calculate number of rows needed -- this will be 4, 5 or 6
//  the only time we get 4 is if Feb 1st in a non-leapYear falls on a Sunday
let numRows = Int(ceil(Double(totalCellsNeeded) / Double(7)))
        
// we now know the Height needed for the collection view
//  you said your calendar cell height is 75, so...
//  cvHeight = numRows * 75

We can put that in a loop and print() the information to the debug console like this:我们可以把它放在一个循环中并将信息print()到调试控制台,如下所示:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let calendar = Calendar.current

    // 2026 is the next year where Feb starts on a Sunday
    //  so let's use that year to see that we get 4 rows for Feb
    let year = 2026
    
    for month in 1...12 {
        
        let dateComponents = DateComponents(year: year, month: month)
        
        // startDate will be the first date of the month (Jan 1, Feb 1, Mar 1, etc...)
        guard let startDate = calendar.date(from: dateComponents) else {
            fatalError("Something is wrong with the date!")
        }
        // get the range of days in the month
        guard let range = calendar.range(of: .day, in: .month, for: startDate) else {
            fatalError("Something is wrong with the date!")
        }
        
        // get number of days in the month
        let numberOfDaysInMonth = range.count
        
        // get the day of the week for the first date in the month
        //  this returns 1-based numbering
        //  Nov 1, 2020 was a Sunday, so this would return 1
        let startDayOfWeek = Calendar.current.component(.weekday, from: startDate)
        
        // add the "leading days to the start date"
        //  so, if startDayOfWeek == 3 (Tuesday)
        //  we need to add 2 "empty day cells" for Sunday and Monday
        let totalCellsNeeded = numberOfDaysInMonth + (startDayOfWeek - 1)
        
        // calculate number of rows needed -- this will be 4, 5 or 6
        //  the only time we get 4 is if Feb 1st in a non-leapYear falls on a Sunday
        let numRows = Int(ceil(Double(totalCellsNeeded) / Double(7)))
        
        // we now know the Height needed for the collection view
        //  you said your calendar cell height is 75, so...
        //  cvHeight = numRows * 75
        
        // debug output
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "EEEE"
        let dayName = dateFormatter.string(from: startDate)
        dateFormatter.dateFormat = "LLLL y"
        let dateString = dateFormatter.string(from: startDate)
        
        let dayPadded = dayName.padding(toLength: 10, withPad: " ", startingAt: 0)
        let datePadded = dateString.padding(toLength: 16, withPad: " ", startingAt: 0)

        print("\(datePadded) has \(numberOfDaysInMonth) days, starting on \(dayPadded) requiring \(numRows) rows")
        
    }
    
}

Here's the output:这是输出:

January 2026     has 31 days, starting on Thursday   requiring 5 rows
February 2026    has 28 days, starting on Sunday     requiring 4 rows
March 2026       has 31 days, starting on Sunday     requiring 5 rows
April 2026       has 30 days, starting on Wednesday  requiring 5 rows
May 2026         has 31 days, starting on Friday     requiring 6 rows
June 2026        has 30 days, starting on Monday     requiring 5 rows
July 2026        has 31 days, starting on Wednesday  requiring 5 rows
August 2026      has 31 days, starting on Saturday   requiring 6 rows
September 2026   has 30 days, starting on Tuesday    requiring 5 rows
October 2026     has 31 days, starting on Thursday   requiring 5 rows
November 2026    has 30 days, starting on Sunday     requiring 5 rows
December 2026    has 31 days, starting on Tuesday    requiring 5 rows

So... either in:所以......要么在:

  • cellForRowAt ... calculate the needed height and set the CV height in the cell, or cellForRowAt ... 计算所需的高度并在单元格中设置 CV 高度,或
  • heightForRowAt ... calculate and return the needed height for the row heightForRowAt ... 计算并返回该行所需的高度

Side note: I'd suggest using auto-layout for all of your cells, instead of returning various row heights.旁注:我建议对所有单元格使用自动布局,而不是返回各种行高。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何根据UICollectionView内容大小设置UITableViewCell高度? - How to set UITableViewCell Height according to UICollectionView Content size? 如何根据 UITableViewCell 中的内容调整水平 UICollectionView 高度 - How to resize a horizontal UICollectionView height based on its content in a UITableViewCell 根据内容更新UICollectionView高度 - Update UICollectionView height based on content 如何动态改变UICollectionView的高度以适应内容大小 - How to dynamically change the height of UICollectionView to adapt to content size 通过UICollectionView的高度设置UITableViewCell的高度 - Set height of UITableViewCell by height of UICollectionView 如何将 UICollectionView 的高度调整为 UICollectionView 的内容大小的高度? - How to adjust height of UICollectionView to be the height of the content size of the UICollectionView? UITableViewCell内的UICollectionView如何根据屏幕大小调整tableview单元格高度 - UICollectionView inside UITableViewCell how to adjust tableview cell height based on screen size 自动调整UICollectionView高度以调整其内容大小 - Autoresize UICollectionView height to adjust to its content size 带有UIWebview的UITableViewCell可以将高度调整为内容大小 - UITableViewCell with UIWebview that adjusts height to content size Swift:根据其中的UICollectionView的大小扩展UITableViewCell高度 - Swift: Expand UITableViewCell height depending on the size of the UICollectionView inside it
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM