Ios UICollectionView动态数据源项添加到集合视图的开头
我正在使用动态内容加载功能创建集合视图。就我而言,我在做日历。当前日期将显示在可见部分(加载后)。如果向上滚动,则会显示较旧的日期,如果向下滚动,则会看到下一个日期 我的集合视图使用标准流布局。我一行有7个单元格,4个可见行 我在添加较旧日期时遇到问题(例如,向上滚动时出现的单元格)。我正在做的是:首先,我实现了用于检测滚动事件的滚动视图方法。Ios UICollectionView动态数据源项添加到集合视图的开头,ios,swift,uiscrollview,uicollectionview,uicollectionviewlayout,Ios,Swift,Uiscrollview,Uicollectionview,Uicollectionviewlayout,我正在使用动态内容加载功能创建集合视图。就我而言,我在做日历。当前日期将显示在可见部分(加载后)。如果向上滚动,则会显示较旧的日期,如果向下滚动,则会看到下一个日期 我的集合视图使用标准流布局。我一行有7个单元格,4个可见行 我在添加较旧日期时遇到问题(例如,向上滚动时出现的单元格)。我正在做的是:首先,我实现了用于检测滚动事件的滚动视图方法。 startOffsetY是在viewDidLoad中设置的contentOffset.y值。它不等于0,因为我设置了contentInsetupd只是一
startOffsetY
是在viewDidLoad中设置的contentOffset.y值。它不等于0,因为我设置了contentInset
upd
只是一个标志,表示可以开始新的更新
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView.contentOffset.y <= startOffsetY - 20 && upd {
calendar.updateDataSource()
}
}
但是,当添加行和滚动正在进行时,我有明显的延迟
我尝试了不同的策略:我使用了reloadData()。从这一点上,我发现,插入项目的动画可能是问题所在。我试图将performBatchUpdates
包装到ui视图中。perform没有动画
块,但也没有运气
我真的在寻找一些帮助,我不寻找现成的解决方案,除非它们能像我描述的那样工作(上下滚动并加载内容),我可以看看它是如何工作的。再一次,滚动已经加载的项目不是问题,问题是在我的数据数组中添加内容时出现滞后
编辑
Swift中@teamnorge提供的代码
func scrollViewDidScroll(scrollView: UIScrollView) {
let currentOffset = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
var offset : CGFloat!
println(currentOffset)
/* 0.125 - 1/8, 0.5 - 1/2 */
if currentOffset < contentHeight * 0.125 {
offset = contentHeight * 0.125 - currentOffset
// reload content here
scrollView.contentOffset = CGPoint(x: 0, y: currentOffset + contentHeight * 0.5 + offset - CGFloat(cellHeight))
}
/* 0.75 - 6/8, 0.5 - 1/2 */
if currentOffset > contentHeight * 0.75 {
offset = currentOffset - contentHeight * 0.75
// reload content here
scrollView.contentOffset = CGPoint(x: 0, y: currentOffset - contentHeight * 0.5 - offset + CGFloat(cellHeight))
}
我认为布局的失效导致了这些滞后。那么,我可能需要定制流程布局?如果是的话,你能给出什么建议。这实际上是一个非常有趣的话题。我将尝试解释我在开发另一个日历应用程序时提出的想法
在我的例子中,它不是日历视图,而是日视图,从上到下列出了小时数00:00-24:00,因此我有UITableView
而不是UICollectionView
,但在这种情况下它并不重要
使用的语言不是Swift,而是Objective-C,所以我只是尝试翻译代码示例
我用固定数量的行创建了UITableView
,而不是使用数据源进行操作,在我的情况下,只存储两天(48行,每行两天24小时)。您可以选择在两个全屏中包含的行数
重要的是行的总数必须是8的倍数。
然后需要一个公式,根据第一行中的内容计算每个特定单元格的天数
其思想是,UICollectionView
实际上是UIScrollView
,因此当我们向下或向上滚动时,我们可以处理相应的事件并计算可见偏移量
为了模拟无限滚动,我们处理scrollViewDidScroll
并检查您是否刚刚通过UIScrollView
高度滚动的1/8
,将UIScrollView
移动到高度加上精确偏移的1/2
,使其平滑地移动到“第二屏”。如果向下滚动时传递了UIScrollView
高度的6/8
,请将UIScrollView
向上移动到其高度减去偏移量的1/2
当您这样做时,您会看到滚动指示器上下跳跃,这非常混乱,因此我们必须将其隐藏,只需将其放置在viewDidLoad
中的某个位置:
calendarView.showsHorizontalScrollIndicator = false
calendarView.showsVerticalScrollIndicator = false
其中,calendarView
是您的UICollectionView
实例名称
以下是代码(此处翻译自Objective-C,未在实际项目中试用):
func scrollViewDidScroll(scrollView_:UIScrollView) {
if !enableScrollingHandling {return}
var currentOffsetX:CGFloat = scrollView_.contentOffset.x
var currentOffSetY:CGFloat = scrollView_.contentOffset.y
var contentHeight:CGFloat = scrollView_.contentSize.height
var offset:CGFloat
/* 0.125 - 1/8, 0.5 - 1/2 */
if currentOffSetY < (contentHeight * 0.125) {
enableScrollingHandling = false
offset = (contentHeight * 0.125) - currentOffSetY
// @todo: your code, specify which days are listed in the first row (2nd screen)
scrollView_.contentOffset = CGPoint(x: currentOffsetX, y: currentOffset +
contentHeight * 0.5 + offset - CGFloat(kRowHeight))
enableScrollingHandling = true
return
}
/* 0.75 - 6/8, 0.5 - 1/2 */
if currentOffSetY > (contentHeight * 0.75) {
enableScrollingHandling = false
offset = currentOffSetY - (contentHeight * 0.75)
// @todo: your code, specify which days are listed in the first row (1st screen)
scrollView_.contentOffset = CGPoint(x: currentOffsetX, y: currentOffset -
contentHeight * 0.5 - offset + CGFloat(kRowHeight))
enableScrollingHandling = true
return
}
}
func scrollViewDidScroll(scrollView\uUiScrollView){
如果!启用滚动处理{return}
var currentOffsetX:CGFloat=scrollView\uView.contentOffset.x
var currentOffset:CGFloat=scrollView\uView.contentOffset.y
var contentHeight:CGFloat=scrollView\ux.contentSize.height
var偏移量:CGFloat
/* 0.125 - 1/8, 0.5 - 1/2 */
如果currentOffSetY<(内容高度*0.125){
enableScrollingHandling=false
偏移量=(内容高度*0.125)-currentOffSetY
//@todo:您的代码,指定第一行(第二屏)列出的日期
scrollView_u2;.contentOffset=CGPoint(x:currentOffsetX,y:currentOffset+
contentHeight*0.5+偏移量-CGFloat(kroweight))
enableScrollingHandling=true
返回
}
/* 0.75 - 6/8, 0.5 - 1/2 */
如果currentOffSetY>(内容高度*0.75){
enableScrollingHandling=false
偏移量=当前偏移量-(内容高度*0.75)
//@todo:您的代码,指定第一行(第一屏)中列出的日期
scrollView.contentOffset=CGPoint(x:currentOffsetX,y:currentOffset-
contentHeight*0.5-偏移量+CGFloat(克朗)
enableScrollingHandling=true
返回
}
}
然后,在您的collectionView:cellForItemAtIndexPath:
中,根据第一行的内容(这是第一个屏幕的内容还是第二个屏幕的内容)以及当前可见天数(公式),您只需更新单元格内容
这个公式也可能是一个棘手的部分,可能需要一些变通方法,特别是如果您决定在两个月之间输入月份名称。我也有一些关于如何组织的想法,所以如果你遇到任何问题,我们可以在这里讨论
但这种模拟“两屏循环并在两屏之间跳跃”的不定式滚动的方法真的很有魅力,在老式手机上也测试过非常平滑的滚动行为
PS:kroweight只是一个常数
calendarView.showsHorizontalScrollIndicator = false
calendarView.showsVerticalScrollIndicator = false
func scrollViewDidScroll(scrollView_:UIScrollView) {
if !enableScrollingHandling {return}
var currentOffsetX:CGFloat = scrollView_.contentOffset.x
var currentOffSetY:CGFloat = scrollView_.contentOffset.y
var contentHeight:CGFloat = scrollView_.contentSize.height
var offset:CGFloat
/* 0.125 - 1/8, 0.5 - 1/2 */
if currentOffSetY < (contentHeight * 0.125) {
enableScrollingHandling = false
offset = (contentHeight * 0.125) - currentOffSetY
// @todo: your code, specify which days are listed in the first row (2nd screen)
scrollView_.contentOffset = CGPoint(x: currentOffsetX, y: currentOffset +
contentHeight * 0.5 + offset - CGFloat(kRowHeight))
enableScrollingHandling = true
return
}
/* 0.75 - 6/8, 0.5 - 1/2 */
if currentOffSetY > (contentHeight * 0.75) {
enableScrollingHandling = false
offset = currentOffSetY - (contentHeight * 0.75)
// @todo: your code, specify which days are listed in the first row (1st screen)
scrollView_.contentOffset = CGPoint(x: currentOffsetX, y: currentOffset -
contentHeight * 0.5 - offset + CGFloat(kRowHeight))
enableScrollingHandling = true
return
}
}