FSCalendar.week周视图模式底部多余空白适配问题咨询
FSCalendar周视图模式底部多余空白问题
问题描述
使用FSCalendar做iOS开发时,将scope属性设置为.week切到周视图模式后,日历控件底部会出现非预期的空白区域,效果如下:
如果直接手动缩小控件高度,控件内字体会同步缩放,整体内容被挤压变形,效果如下:
问题复现Swift代码:
class ViewController: UIViewController { fileprivate weak var calendar: FSCalendar! override func viewDidLoad() { super.viewDidLoad() let calendar = FSCalendar(frame: CGRect(x: 0, y: 100, width: self.view.frame.width, height: 300)) self.calendar = calendar view.addSubview(calendar) calendar.locale = Locale(identifier: "en_US") calendar.backgroundColor = .lightGray calendar.scope = .week calendar.headerHeight = 0 } }
待解答疑问
- 是否有可行方案移除日历底部的多余空白,让控件尺寸刚好匹配日历实际显示内容?
- FSCalendar初始化时的高度是否必须设置为300?
- FSCalendar是否支持使用AutoLayout Constraint添加自动布局约束?
问题解答
1. 移除底部多余空白方案
周视图下的底部空白是初始化时给月视图预留的高度没有自动更新导致的,直接硬改高度会触发控件内部的内容缩放逻辑,造成字体缩小、内容挤压。
正确处理方式是实现FSCalendarDelegate的calendar(_:boundingRectWillChange:animated:)代理方法,该方法会在控件切换scope时返回当前模式下的实际渲染高度,直接用这个值更新控件高度即可,不会出现内容变形问题。
核心实现代码:
class ViewController: UIViewController, FSCalendarDelegate { fileprivate weak var calendar: FSCalendar! override func viewDidLoad() { super.viewDidLoad() let calendar = FSCalendar(frame: CGRect(x: 0, y: 100, width: self.view.frame.width, height: 300)) self.calendar = calendar view.addSubview(calendar) calendar.locale = Locale(identifier: "en_US") calendar.backgroundColor = .lightGray calendar.scope = .week calendar.headerHeight = 0 // 绑定代理 calendar.delegate = self } func calendar(_ calendar: FSCalendar, boundingRectWillChange bounds: CGRect, animated: Bool) { // 更新为实际渲染高度,自动消除底部空白 calendar.frame.size.height = bounds.height } }
如果通过headerHeight = 0隐藏了顶部头部栏,代理返回的高度已经自动扣除了头部栏占位,不需要额外手动计算。
2. 初始化高度是否必须为300
不是必须。300只是官方Demo中给月视图模式设置的参考初始值,没有强制要求。初始化时传入的高度只是控件首次加载的临时占位值,最终显示高度以boundingRectWillChange代理返回的实际渲染高度为准,初始化时可以传入任意临时高度,后续在代理回调中更新为正确高度即可。
3. 是否支持AutoLayout自动布局
完全支持,使用时注意两个要点即可:
- 给控件添加上下左右位置、宽度约束后,添加高度约束时不要设置为必需优先级(
UILayoutPriorityRequired),将高度约束优先级调整为defaultHigh,避免和控件内部的固有内容尺寸约束冲突 - 在
calendar(_:boundingRectWillChange:animated:)代理回调中,将高度约束的constant值更新为bounds.height,调用父视图的layoutIfNeeded()方法即可完成动态高度适配,不需要手动计算frame。
内容的提问来源于stack exchange,提问作者Dan Choi
相关产品推荐
相关产品推荐

