Swift中如何实现UICollectionView的水平与垂直双向滚动?

您好。
我正在尝试制作一个日历事件目录,效果如图所示。我希望垂直滚动时切换目录显示的时段,水平滚动时切换日历的日期。目前已实现垂直滚动功能,但不知道如何在Swift中添加水平滚动功能。请问有没有可行的实现方案?
我询问的是Swift中的实现方法,感谢解答。
Swift实现双滚动日历目录方案
在Swift里做这种横竖双滚动的日历组件,我有两种常用的思路,你可以参考:
方案一:嵌套UIScrollView(简单易上手)
这种方式适合日期数量不多的场景,直接用两个滚动视图嵌套就行:
- 外层用横向UIScrollView,负责切换不同日期的页面,建议开启
isPagingEnabled让切换更顺滑 - 每个日期页面内部,放你已经做好的纵向UIScrollView(也就是时段滚动目录)
- 关键要给两个ScrollView设置正确的
contentSize:- 横向ScrollView的
contentSize.width= 单页面宽度 × 总日期数 - 纵向ScrollView的
contentSize.height= 你的时段列表总高度
- 横向ScrollView的
简单代码示例:
// 初始化横向滚动容器 let horizontalScroll = UIScrollView() horizontalScroll.isPagingEnabled = true horizontalScroll.showsHorizontalScrollIndicator = false horizontalScroll.frame = view.bounds view.addSubview(horizontalScroll) // 假设要展示7天的日历 for dayIdx in 0..<7 { // 复用你已经实现好的纵向滚动视图 let verticalScroll = YourExistingVerticalScrollView() verticalScroll.frame = CGRect( x: CGFloat(dayIdx) * view.bounds.width, y: 0, width: view.bounds.width, height: view.bounds.height ) // 给当前日期的视图加载对应事件数据 verticalScroll.loadEvents(for: getTargetDate(at: dayIdx)) horizontalScroll.addSubview(verticalScroll) } // 设置横向滚动容器的内容尺寸 horizontalScroll.contentSize = CGSize( width: view.bounds.width * 7, height: view.bounds.height )
方案二:UICollectionView横向分页+内部纵向列表(高性能)
如果需要展示的日期数量很多,用这种复用Cell的方式性能更好:
- 外层用UICollectionView,设置布局为横向滚动的
UICollectionViewFlowLayout,并开启分页 - 每个CollectionViewCell内部嵌入你做好的纵向滚动列表(UITableView或UICollectionView)
- 可以通过
collectionView(_:willDisplay:forItemAt:)监听当前显示的日期,实时更新对应的数据
核心代码示例:
// 配置外层横向CollectionView的布局 let flowLayout = UICollectionViewFlowLayout() flowLayout.scrollDirection = .horizontal flowLayout.itemSize = view.bounds.size flowLayout.minimumLineSpacing = 0 let calendarCollection = UICollectionView( frame: view.bounds, collectionViewLayout: flowLayout ) calendarCollection.isPagingEnabled = true calendarCollection.showsHorizontalScrollIndicator = false calendarCollection.register(CalendarDayCell.self, forCellWithReuseIdentifier: "DayCell") calendarCollection.dataSource = self calendarCollection.delegate = self view.addSubview(calendarCollection) // 自定义Cell,内部包含纵向滚动列表 class CalendarDayCell: UICollectionViewCell { let eventsTable = UITableView() override init(frame: CGRect) { super.init(frame: frame) // 这里配置你的UITableView,复用你之前实现的纵向滚动逻辑 eventsTable.frame = bounds addSubview(eventsTable) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func setup(with events: [CalendarEvent]) { // 更新表格数据 eventsTable.reloadData() } } // 实现CollectionView数据源方法 extension YourViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return totalDaysCount // 你的总日期数 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DayCell", for: indexPath) as! CalendarDayCell let events = getEventsForDay(at: indexPath.item) cell.setup(with: events) return cell } }
两种方案都能满足你的需求,要是日期少就选第一种,快速搞定;日期多的话第二种更省内存~
内容的提问来源于stack exchange,提问作者Seong Min Choo
相关产品推荐
相关产品推荐

