Вам нужно создать @IBOutlet
для ограничения высоты представления вашей коллекции.
Когда вы устанавливаете данные календаря/месяца строки, определите, нужны ли вам 5 или 6 строк.
Если это 6, установите .constant
ограничения высоты на 750
Если это 5, установите .constant
ограничения высоты на 675
Изменить
Во-первых, я предлагаю вам забыть об использовании представления коллекции с автоматически изменяющимся размером. UICollectionView
предназначен для размещения ячеек в зависимости от размера представления коллекции, обеспечивая автоматическую прокрутку, когда ячеек слишком много.
Попытка изменить его размер может работать в одном случае, но не работать в другом. Причина, по которой это не удается в этом случае, заключается в том, что ваше табличное представление размещает ячейку и вычисляет ее высоту до представления коллекции и, следовательно, до того, как оно сможет изменить свой размер.
Вместо этого, поскольку вы знаете, что высота вашей ячейки равна 75, вы можете рассчитать, сколько строк потребуется вашему календарю, и либо установить .constant
для ограничения высоты для вашего представления коллекции, либо (поскольку вы уже используете heightForRowAt
) вычислить там высоту строки .
Посмотрите на этот код:
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
... вычислить и вернуть необходимую высоту строки
Боковое примечание: я бы предложил использовать авто-макет для всех ваших ячеек вместо того, чтобы возвращать различную высоту строк.
person
DonMag
schedule
11.11.2020