I recently had a strange request in regards to a UITableView. You see, the table in a UI could only display 3 rows before scrolling was enabled. Given the minute stature of this table, showing a user that there were more items in it was important. So it was decided that if this table had more than 3 rows in it, always display the scrollbar. The trouble with this was that Apple Human Interface Guidelines and the iOS SDK don’t allow for this behavior. One is able to flash the scrolling indicator, but that’s about it.
So it was decided that if this table had more than 3 rows in it, always display the vertical scrollbar. The trouble with this was that Apple Human Interface Guidelines and the iOS SDK don’t allow for this behavior. One is able to flash the scrolling indicator, but that’s about it.
So the problem here is twofold.
- Display the scrollbar upon table reload.
- Maintain the visible scrollbar when the table has been scrolled.
These actually aren’t too bad to nail down. You’ll want to set your showsHorizontalScrollIndicator to false. The solution below relies on only having vertical available as we’re going to loop through the table to find a UIImageView (which holds the stretching image used by the table (subclass of UIScrollView)). Set your table up normally beyond this. Make sure you’re using delegates for the table – of course, right?
How do you loop through a table to find it’s scrollbar now?
for view in self.upNextTableView.subviews { if view is UIImageView { let imageView = view as? UIImageView imageView?.isHidden = false imageView?.layer.removeAllAnimations() imageView?.alpha = 1.0 } }
There you go. This is brittle as HELL. If you don’t turn off the horizontal scroll indicator, you’ll affect it t0o – and make that display in addition to the vertical. Didn’t want that. And it’s brittle because Apple could update the underpinnings of how these things are constructed and this method won’t work accurately anymore.
So this turns the scrollbar on. If a user scrolls it at all, though, it’s going to fade away again. This part is a tiny bit tricky. Since you’ve set up delegates for the table, you can implement a scroll view delegate in regards to scrolling… or namely dragging.
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { if scrollView == upNextTableView { if upNextTableView.numberOfRows(inSection: 0) > 3 { for view in self.upNextTableView.subviews { if view is UIImageView { let imageView = view as? UIImageView delay(bySeconds: 0.7) { imageView?.isHidden = false imageView?.layer.removeAllAnimations() imageView?.alpha = 1.0 } } } } } }
There is the delegate method – and because I had more than one table, I perform a check first. You probably don’t need that. Anyway, we wait 0.7 seconds before turning the scrollbar back on after a drag. If we attempt before, the animation will prevent the scrollbar alpha change to “take”. Here is the helper stuff for the delay call:
public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping () -> Void) { let dispatchTime = DispatchTime.now() + seconds dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure) } public enum DispatchLevel { case main, userInteractive, userInitiated, utility, background var dispatchQueue: DispatchQueue { switch self { case .main: return DispatchQueue.main case .userInteractive: return DispatchQueue.global(qos: .userInteractive) case .userInitiated: return DispatchQueue.global(qos: .userInitiated) case .utility: return DispatchQueue.global(qos: .utility) case .background: return DispatchQueue.global(qos: .background) } } }
So without using a custom scrollbar or subclassed table, you’re able to get what you need to be done. This is most of the code, but the gist of this is to show that it can be done, albeit in a very brittle way that makes me cringe.
please do you have a complete project ?
I do but I can’t release it (it was for work). If I get some time maybe I’ll whip together a little project showing it off.
please try to make a little project , it will be helpful for many people like me