【问题标题】:Change UITableViewCell Height based UICollectionView content size height更改基于 UICollectionView 内容大小高度的 UITableViewCell 高度
【发布时间】:2021-02-22 18:46:51
【问题描述】:

我正在处理使用UICollectionView 创建的日历。

UICollectionView 位于 UITableViewCellheightForRowAt方法中的UITableViewCellreturn UITableView.automaticDimension

用于创建日历的UICollectionView 会根据显示的天数更新其高度,例如11 月 月份的第一天是星期日 所以要将日期放在标签“星期日”下,collectionView 必须添加一整行。

通常每个月有 5 行(周),但当 每月的第一天发生在 星期日时,collectionview 返回 6

现在正如我所说,我能够根据返回的行数更新 UICollectionView 的高度,但我无法动态更改 TableViewCellheight包含collectionView

如何根据其中CollectionView 的高度调整tableViewCell 的大小?


编辑

我的细胞


我已将UITableView.automaticDimension 设置为包含CalendarView 的单元格的高度

CalendarView: UIView类中我创建了一个变量CGFloat calendarH来设置collectionView的默认高度

CollectionView 实现

我添加了一个观察者,它在 collctionView 发生变化时跟踪它的高度

我目前可以更改collectionView 的高度,但它的父视图 (bookingCalendarView) 和 tableView 单元格继续保持固定高度并且不适应 collectionView

【问题讨论】:

  • 你如何设置收藏视图的高度?
  • @DonMag 我没有设置固定高度.. 我把顶部、前导、尾随和底部锚放在单元格上
  • OK - 集合视图没有固有高度。如果你知道你的行高是 20 ......并且你有 5 行,那么集合视图需要 100 的高度约束(如果有的话,加上间距)......如果你有 6 行,集合视图需要高度限制为 120(加上间距,如果有的话)。
  • @DonMag 我有一个包含 6 个单元格的 collectionView(我已经输入了 collectionView 达到的最高高度......例如一周的第一天发生在星期日)。高度为 450(75(单元格)x 6 行),但是当 collectionView 更改行数时,tableviewcell 不会更新其大小。我添加了一张 xib 的照片以向您展示我输入的约束

标签: ios uitableview uicollectionview row-height


【解决方案1】:

您需要为集合视图的高度约束创建一个@IBOutlet

设置一行的日历/月份数据时,确定是需要5行还是6行。

如果是 6,则将高度约束上的 .constant 设置为 750

如果是 5,则将高度约束上的 .constant 设置为 675


编辑

首先,我建议您忘记使用“自行调整大小”的集合视图。 UICollectionView 旨在根据集合视图的大小布置单元格,当单元格过多时提供自动滚动。

尝试“自行调整大小”可能在一种情况下有效,但在另一种情况下会失败。在这种情况下它失败的原因是因为您的表格视图布置了单元格并计算了它的高度集合视图被填充之前,因此在它可以“自我调整大小”之前。”

相反,由于您知道您的单元格高度为 75,您可以计算您的日历需要多少行,并为您的集合视图设置 .constant 高度限制,或者(因为您已经在使用 @987654329 @) 在那里计算行高。

看看这段代码:

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

我们可以把它放在一个循环中,然后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")
        
    }
    
}

这是输出:

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

所以...要么在:

  • cellForRowAt ... 计算所需高度并在单元格中设置 CV 高度,或者
  • heightForRowAt ... 计算并返回行所需的高度

旁注:我建议对所有单元格使用自动布局,而不是返回各种行高。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-07-15
  • 2019-10-12
  • 2014-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多