On iOS devices the section headers in UITableView's have a nice behavior where they stick or 'float' to the top of the screen as you scroll through a section. The section headers in my particular case are loaded from other XIB files.
Is it possible to change the section headers depending on whether or not they are currently floating? Specifically I'd like to add a small shadow to appear under the header only while it's s开发者_如何学运维tuck to the top of the view.
Thanks!
Here's the function I created to update whether each header has a shadow or not. All the section headers in this case are a UIView subclass ListHeader
. They're retained and returned by the viewForHeaderInSection
function.
- (void) updateHeaderShadows {
int i=0;
int sectionHeight = 0;
int totalHeight = 0;
UIView * sectionHeader;
while (i<[self numberOfSectionsInTableView:self.tableView]) {
sectionHeight = [self.tableView rectForSection:i].size.height;
sectionHeader = [self tableView:self.tableView viewForHeaderInSection:i];
if ([sectionHeader respondsToSelector:@selector(shadow)]) {
if (sectionHeader.frame.origin.y == totalHeight || sectionHeader.frame.origin.y == totalHeight + sectionHeight - sectionHeader.frame.size.height) {
[((ListHeader *) sectionHeader).shadow setHidden:YES];
} else {
[((ListHeader *) sectionHeader).shadow setHidden:NO];
}
}
totalHeight += sectionHeight;
i++;
}
}
I haven't tested it yet, but I don't see any reason why it wouldn't be possible.
Just make sure you set the right bounds
(because your shadow needs to be on top of your view, not above it).
You can use the following approach:
- Use
scrollView:didScroll:
to get notified about scroll-events. - In this method, check whether you need to add your shadow-view to your (floating) header-view.
- If so, add it. (just
[view addSubview:shadowView]
.) Something likeCGRectMake(0.f, yourDefaultHeaderHeight, 320.f, yourShadowHeight)
should be theframe
of yourshadowView
. - Now, update the
bounds
ofview
, so it can show yourshadowView
:CGRectMake(0.f, 0.f - yourShadowHeight, 320.f, yourDefaultHeaderHeight + 2 * yourShadowHeight)
. - When you find out that your header isn't floating anymore (by using
scrollView:didScroll:
), remove the shadow-view.
Your headerView
s bounds
should be 0.f - yourShadowHeight
because if you use just 0.f
, it'll blur (I don't know why ...).
You would have to have your own UIView in the header. Then you would need a reference to it. Then hook into scrollViewWillBeginDragging:
with your UIScrollViewDelegate. In that function, add the shadow to the custom view.
Hook into scrollViewDidEndDragging:willDecelerate:
and remove the shadow in this function.
@Anthony Mattox answer for Swift
protocol SectionHeaderWithShadowProtocol where Self: UIView {
var shadow: Bool { get set }
}
class SectionHeaderView: UITableViewHeaderFooterView, SectionHeaderWithShadowProtocol {
@IBOutlet weak var shadowView: UIView!
var shadow: Bool = false {
didSet {
shadowView.isHidden = shadow
}
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
updateHeaderShadows()
}
func updateHeaderShadows() {
var i = 0
var sectionHeight: CGFloat = 0
var totalHeight: CGFloat = 0
while i < numberOfSections() {
sectionHeight = tableView.rect(forSection: i).size.height
if let sectionHeader = tableView.headerView(forSection: i) as? SectionHeaderWithShadowProtocol {
if sectionHeader.frame.origin.y == totalHeight || sectionHeader.frame.origin.y == totalHeight + sectionHeight - sectionHeader.frame.size.height {
sectionHeader.shadow = false
} else {
sectionHeader.shadow = true
}
}
totalHeight += sectionHeight
i += 1
}
}
精彩评论