[英]Detect when UITableView section header snaps to the top of the screen
I want to detect when the UITableView
section header snaps on top of the screen and then modify header's height, but I have no idea how to do that.我想检测UITableView
部分标题何时捕捉到屏幕顶部,然后修改标题的高度,但我不知道该怎么做。 Can anyone help?任何人都可以帮忙吗?
I was able to accomplish detecting which header is stuck to top of the table view by using the didEndDisplayingHeaderView
and willDisplayHeaderView
delegate methods.通过使用didEndDisplayingHeaderView
和willDisplayHeaderView
委托方法,我能够完成检测哪个标题卡在表格视图的顶部。 The idea here is that the while we are scrolling through the sections of the table view, the rows around the header are becoming visible and we can grab the index paths of all visible rows using tableView.indexPathsForVisibleRows
.这里的想法是,当我们滚动表格视图的各个部分时,标题周围的行变得可见,我们可以使用tableView.indexPathsForVisibleRows
获取所有可见行的索引路径。 Depending on if we are scrolling up or down, we compare the first or last indexPath on screen to the index path of the view that just appeared/disappeared.根据我们是向上还是向下滚动,我们将屏幕上的第一个或最后一个 indexPath 与刚刚出现/消失的视图的索引路径进行比较。
//pushing up
func tableView(_ tableView: UITableView,
didEndDisplayingHeaderView view: UIView,
forSection section: Int) {
//lets ensure there are visible rows. Safety first!
guard let pathsForVisibleRows = tableView.indexPathsForVisibleRows,
let lastPath = pathsForVisibleRows.last else { return }
//compare the section for the header that just disappeared to the section
//for the bottom-most cell in the table view
if lastPath.section >= section {
print("the next header is stuck to the top")
}
}
//pulling down
func tableView(_ tableView: UITableView,
willDisplayHeaderView view: UIView,
forSection section: Int) {
//lets ensure there are visible rows. Safety first!
guard let pathsForVisibleRows = tableView.indexPathsForVisibleRows,
let firstPath = pathsForVisibleRows.first else { return }
//compare the section for the header that just appeared to the section
//for the top-most cell in the table view
if firstPath.section == section {
print("the previous header is stuck to the top")
}
}
I went to make my comment into codes and it works like:我去把我的评论变成代码,它的工作原理如下:
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == yourTableView {
if yourTableView.rectForHeader(inSection: <#sectionIWant#>).origin.y <= tableView.contentOffset.y-defaultOffSet.y &&
yourTableView.rectForHeader(inSection: <#sectionIWant#>+1).origin.y > tableView.contentOffset.y-defaultOffSet.y {
print("Section Header I want is at top")
}
} else {
//Handle other scrollViews here
}
}
So you replace sectionIWant
with an Int
and when that section's header is at top, the print
will run.Note that yourTableView
is not a parameter of scrollViewDidScroll
so you have to keep a reference to your UITableView
elsewhere and use it here.所以,你替换sectionIWant
与Int
,当该节的头是在顶部时, print
将run.Note是yourTableView
不是参数scrollViewDidScroll
所以你必须参考存到自己UITableView
的其他地方,并在这里使用它。
Alternatively if you want to be constantly updated on which section header is at top you can use:或者,如果您想不断更新哪个部分标题位于顶部,您可以使用:
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == yourTableView {
var currentSection = 0
while !(tableView.rectForHeader(inSection: currentSection).origin.y <= (tableView.contentOffset.y-defaultOffSet.y) &&
tableView.rectForHeader(inSection: currentSection+1).origin.y > (tableView.contentOffset.y)-defaultOffSet.y) {
if tableView.contentOffset.y <= tableView.rectForHeader(inSection: 0).origin.y {
break //Handle tableView header - if any
}
currentSection+=1
if currentSection > tableView.numberOfSections-2 {
break //Handle last section
}
}
print(currentSection)
}
}
Note that in both codes there is a defaultOffSet
which is the contentOffSet
of the tableView
on load, this is to take into account that the contentOffSet
does not start at 0 in some situations - I am not sure when but I do encounter such cases before.请注意,在两个代码中都有一个defaultOffSet
,它是加载时tableView
的contentOffSet
,这是考虑到contentOffSet
在某些情况下不会从 0 开始 - 我不确定何时但我之前确实遇到过这种情况。
This solution works for me.这个解决方案对我有用。
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.visibleHeaders.forEach { header in
let headerOriginalFrame = self.myTableView.rectForHeader(inSection: header.tag)
let headerCurrentFrame = header.frame
let fixed = headerOriginalFrame != headerCurrentFrame
// Do things you want
}
}
Here is full source code.这是完整的源代码。 https://github.com/jongwonwoo/CodeSamples/blob/master/TableView/TableviewFixedHeader/Tableview/ViewController.swift https://github.com/jongwonwoo/CodeSamples/blob/master/TableView/TableviewFixedHeader/Tableview/ViewController.swift
My solution to this problem turned out to be really working and versatile enough.事实证明,我对这个问题的解决方案确实有效且用途广泛。 I would be very glad if this helps someone如果这对某人有帮助,我会很高兴
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let sectionPosition = tableView.rect(forSection: sectionIndex)
let translation = scrollView.panGestureRecognizer.translation(in: scrollView.superview)
if let dataSource = dataSource,
scrollView.contentOffset.y >= sectionPosition.minY {
//Next section
guard dataSource.count - 1 > sectionIndex else { return }
sectionIndex += 1
} else if translation.y > 0,
scrollView.contentOffset.y <= sectionPosition.minY {
//Last section
guard sectionIndex > 0 else { return }
sectionIndex -= 1
}
Late to the party, but reviewing up all responses didn't solve my issue.派对迟到了,但查看所有回复并没有解决我的问题。
The following approach, borrow a little bit from each one, adding at the same time, a more general and not fixed approach.下面的做法,每一个都借鉴了一点,同时又增加了一个更通用且不固定的做法。
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let visibleIndexs = self.tableView.indexPathsForVisibleRows,
!visibleIndexs.isEmpty else { return }
var visibleHeaders = [Int]()
visibleIndexs.forEach { anIndexPath in
if !visibleHeaders.contains(anIndexPath.section) {
visibleHeaders.append(anIndexPath.section)
}
}
visibleHeaders.forEach { header in
let headerView = tableView.headerView(forSection: header)
let headerOriginalFrame = self.tableView.rectForHeader(inSection: header)
if headerOriginalFrame != headerView?.frame {
//do something with top headerView
} else {
//do something else with all the others headerView(s)
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.