'White line below UIRefreshControl when pulled.. tableView
I am implementing a very basic Refresh control...
var refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: Selector(("refresh:")), for: UIControlEvents.valueChanged)
refreshControl.backgroundColor = UIColor.red
self.tableView.addSubview(refreshControl)
for some reason though whenever I pull down to refresh it's like the refresh control cannot keep up with the table view and there is a white gap between the two.
here is the problem on the simulator... it is worse on the iPhone I believe
Solution 1:[1]
While I also suggest you should do what Artem posted, it didn't directly remove that gap for me. Turns out I was running into 2 different issues related to UIRefreshControl
and found a few 'hacks' to get around them. The easy fix is to set the tableView's background colour to the same colour as your refresh control, but that has the side effect of seeing the same colour at the bottom of your table view.
My set up is a UINavigationController
hosting a UIViewController
with a UITableView
subview and a UISearchBar
set as the tableView's tableHeaderView. My goal is to match the colour of the navigation bar, refresh control, and the search bar.
Issue 1
I think this the same issue that you're seeing. It seems like as soon as you drag to start the pull to refresh action, there's a gap that appears during the first few pts of the gesture. After some threshold, the refresh control becomes the correct colour. On the way back to the table view's resting scroll state though, we see that same gap again just before it reaches a content offset of 0. Here's what that looks like:
Solution 1
If you subclass UIRefreshControl
and override the frame
and isHidden
properties and just print out their values when they are set, you'll notice that the refresh control doesn't actually get unhidden until the distance from the top of the table view is 4pt. Similarly, when you scroll back down you'll also see that it is set to hidden around the same spot, which is before you can't visibly see the refresh control anymore and why we see the gap peeking to the tableView background.
In our subclass, we can prevent this 'early' hiding and 'late' unhiding by overriding the setter and getter of isHidden
and the didSet
of frame
to only hide when the refresh control's offset is actually 0.
class RefreshControl: UIRefreshControl {
override var isHidden: Bool {
get {
return super.isHidden
}
set(hiding) {
if hiding {
guard frame.origin.y >= 0 else { return }
super.isHidden = hiding
} else {
guard frame.origin.y < 0 else { return }
super.isHidden = hiding
}
}
}
override var frame: CGRect {
didSet {
if frame.origin.y < 0 {
isHidden = false
} else {
isHidden = true
}
}
}
}
I call this a hack because I'm not a huge fan of modifying the existing behaviour of UIRefreshControl, but I haven't found a better way to get around this yet.
Issue 2
When pulling to refresh past that gap threshold in issue 1, it seems like the frame of the UIRefreshControl can't keep up with the search bar. This gives us another kind of gap that follows the search bar around. This is what it looks like:
Solution 2
This lagging gap looks like the frames aren't being updated as fast as our scrolling maybe even animated. Turns out that if we set the frame to itself in somewhere like layoutSubviews
, we get the following behaviour:
override func layoutSubviews() {
super.layoutSubviews()
var originalFrame = frame
frame = originalFrame
}
Again, this is pretty hacky, but I haven't found a different way to go about this either.
Result
Solution 2:[2]
Why do you add refreshControl
as a subview? You must do that:
refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged)
tableView.refreshControl = refreshControl
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |