Disable bottom bounce in UITableView with UIRefreshControl - ios

I want to disable UITableView bottom bounce, I can't use standard "bounce" property in storyboard, bcs UIRefreshControl needs top bounce for work. So I have tried this solution:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height) {
[scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, scrollView.contentSize.height - scrollView.frame.size.height)];
}
}
It works fine if content height bigger then size of screen, but crashes in other case:
As u see on picture above UIRefreshControl is not hidden (and there are only 3 cells in uitableview with blank space on bottom if UIRefreshControll is hidden). I have tried to resolve this problem by adding UIRefreshControl height to my method but it didn't help either:
override func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height - self.refreshControl!.frame.size.height {
scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: scrollView.contentSize.height - scrollView.frame.size.height + self.refreshControl!.frame.size.height), animated: false)
}
}
I am having blank space at top and RefreshControl stops working:
What am I doing wrong? Thx.
P.S. My viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl = UIRefreshControl()
self.refreshControl!.attributedTitle = NSAttributedString(string: "Обновление")
self.refreshControl!.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
self.edgesForExtendedLayout = UIRectEdge.None;
tableView.allowsMultipleSelectionDuringEditing = false;
tableView.tableFooterView = UIView()
// menu button
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
}

At the moment I found pretty dumb solution:
override func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView.contentSize.height > self.view.frame.size.height && scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height {
scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: scrollView.contentSize.height - scrollView.frame.size.height), animated: false)
}
}
I disable bounce only if contentSize.height > self.view.frame.size.height , hope some1 knew how to do it better.

Related

How to keep UIButton floating AFTER scrollViewDidScroll(_ scrollView: UIScrollView) reached bottom?

The following is the current implementation. The grey button is floating on the scroll view. Is there a way to make the button appear once the yellow view (end of scroll view) is reached. Then keep it floating on the screen at the very bottom.
I'm using the following code:
override func scrollViewDidScroll(scrollView: UIScrollView) {
if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
//reached bottom - how to show button below yellow
// and keep it floating as shown above
}
}
Adding additional code of what I've tried so far:
#IBOutlet weak var btnScroll: UIButton!
var startingFrame : CGRect!
var endingFrame : CGRect!
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) && self.btnScroll.isHidden {
self.btnScroll.isHidden = false
self.btnScroll.frame = startingFrame // outside of screen somewhere in bottom
UIView.animate(withDuration: 1.0) {
self.btnScroll.frame = self.endingFrame // where it should be placed
}
}
}
func configureSizes() {
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
startingFrame = CGRect(x: 0, y: screenHeight+100, width: screenWidth, height: 100)
endingFrame = CGRect(x: 0, y: screenHeight-100, width: screenWidth, height: 100)
}
override func viewDidLoad() {
super.viewDidLoad()
configureSizes()
}
If I understand you right you want to put button on the position which shown on the gif
Try this code:
override func scrollViewDidScroll(scrollView: UIScrollView) {
if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) && self.button.isHidden {
self.button.isHidden = false
self.button.frame = startingFrame // outside of screen somewhere in bottom
UIView.animate(withDuration: 1.0) {
self.button.frame = yourFrame // where it should be placed
}
}
}
UPDATE
add this code to hide your button before animation will show it
override func viewDidLoad() {
super.viewDidLoad()
self.button.isHidden = true
...
}

How to forbid WKWebView's horizontal bounce?

As the gif showed blow,I want to forbid the horizontal bounce,it's so ugly.
You can use this to stop bounces:
self.webView.scrollView.bounces = false
Update:
To disable only horizontal bounce, you can use this code:
First set the webview's scrollview delegate to self
self.webView.scrollView.delegate = self
and then implement it like this.
extension UIViewController: UIScrollViewDelegate{
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if(scrollView.contentOffset.x < 0){
scrollView.setContentOffset(CGPoint.init(x: 0, y: scrollView.contentOffset.y), animated: false)
}else if (scrollView.contentOffset.x >= scrollView.contentSize.width - scrollView.frame.size.width) {
scrollView.setContentOffset(CGPoint.init(x: scrollView.contentSize.width - scrollView.frame.size.width, y: scrollView.contentOffset.y), animated: false)
}
}
}
Hope it helps.

UIScrollView doesn't scroll upwards sometimes

I am using 2 scroll Views When the inner Scroll View is scrolled upwards, outer scrollView also moves upwards(positive contentoffset.y) and when inner SV's contentoffset.y goes less than y, both scroll Views come back to their original positions.
Here is the code:
//secondView is a UIView inside outerScrollView and above inner SV(scrollView).
var scollView: UIScrollView!
var yOffset: CGFloat!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.automaticallyAdjustsScrollViewInsets = true
self.outerScrollView.delegate = self
self.scrollView = UIScrollView(frame: CGRect(x: 0, y: self.secondView.frame.origin.y + self.secondView.frame.height, width: self.view.frame.width, height: self.view.frame.height - (264)))
self.scrollView.delegate = self
self.outerView.addSubview(self.scrollView)
self.scrollView.setContentOffset(CGPoint.zero, animated: true)
}
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
if (scrollView == self.scrollView) {
if (scrollView.contentOffset.y > 0) {
if (self.outerScrollView.contentOffset.y <= 0 ) {
let contentnOffset:CGPoint = CGPoint(x: 0.0, y: self.yOffset)
DispatchQueue.main.async {
self.outerScrollView.setContentOffset(contentnOffset, animated: true)
self.scrollView.frame.size = CGSize(width: self.view.frame.width, height: self.view.frame.height - self.qLabel.frame.height - 9)
if (scrollView.contentSize.height < self.view.frame.height - self.qLabel.frame.height - 9) {
let downPanGesture: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(self.handlePan))
downPanGesture.direction = .down
self.scrollView.addGestureRecognizer(downPanGesture)
}
}
}
} else {
DispatchQueue.main.async {
self.outerScrollView.setContentOffset(CGPoint.zero, animated: true)
self.scrollView.frame.size = CGSize(width: self.view.frame.width, height: self.view.frame.height - (self.scrollView.frame.origin.y))
}
}
}
}
Although everything works fine, there is just 1 small problem. After the inner scrollView is scrolled upwards and contentoffset has changed and I want to keep on scrolling this view, it sometimes just doesn't scroll(upwards). So, I have to first scrooll it downwards and then it will again start scrolling fine. It only happens rarely but it's quite annoying.
Can anybody tell me what could be the possible problem?
Thanks!
P.S. I have tried all other scrollView's delegate methods like didenddecelerating() or didenddragging() etc.

I know how to disable bouncing of uitableview on top only - but how can I do it only on the bottom?

I managed to disable bouncing effect when user scrolls to the top. I would like to reverse it somehow so that the bouncing effect is disabled on the bottom. Could you help me with modifying my code for that purpose?
var lastY: CGFloat = 0.0
func scrollViewDidScroll(scrollView: UIScrollView) {
let currentY = scrollView.contentOffset.y
let currentBottomY = scrollView.frame.size.height + currentY
if currentY > lastY {
//"scrolling down"
tableView.bounces = true
} else {
//"scrolling up"
// Check that we are not in bottom bounce
if currentBottomY < scrollView.contentSize.height + scrollView.contentInset.bottom {
tableView.bounces = false
}
}
lastY = scrollView.contentOffset.y
}
Did you try setting bounce and VerticalBounce property to NO.
You can set these properties programatically like
In Swift
tableView.bounces = false
tableView.alwaysBounceVertical = false
In Objective-C
tableView.bounces = NO;
tableView.alwaysBounceVertical = NO;
OR
if you want to do it from Storyboard. Make you tableview setting like below :
You can try this code
override func scrollViewDidScroll(scrollView: UIScrollView)
{
if scrollView.contentOffset.y <= 0
{
scrollView.contentOffset = CGPointZero
}
}
Try this:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == tableView {
if (self.tableView.contentOffset.y >= (self.tableView.contentSize.height - self.tableView.bounds.size.height))
{
scrollView.contentOffset = CGPoint(x: 0, y: (self.tableView.contentSize.height - self.tableView.bounds.size.height))
}
}
}

UIButton not showing when UIScrollView showing on ViewController

I have a UIViewController that is attached to a class, Swift code below. The code basically adds to the View Controller a UIScrollView with an image.
I am wanting to add a UIButton to the ViewController which I could do through code, however in this case, I want to add the UIButton to the ViewController using the Storyboard.
When I add a UIButton and then run my project, the UIButton is not visible, only the UIScrollView is visible.
Question:
What is going on, why is the UIButton not visible? How can I add a UIButton (to the Storyboard) and ensure that it is visible and in front of the UIScrollView (that is created programatically) when I run the project?
class ScrollViewController: UIViewController, UIScrollViewDelegate {
var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView = UIImageView(image: UIImage(named: "image.png"))
scrollView = UIScrollView(frame: view.bounds)
scrollView.backgroundColor = UIColor.blackColor()
scrollView.contentSize = imageView.bounds.size
scrollView.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
scrollView.contentOffset = CGPoint(x: 1000, y: 450)
scrollView.addSubview(imageView)
view.addSubview(scrollView)
scrollView.delegate = self
setZoomScale()
setupGestureRecognizer()
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
override func viewWillLayoutSubviews() {
setZoomScale()
}
func setZoomScale() {
let imageViewSize = imageView.bounds.size
let scrollViewSize = scrollView.bounds.size
let widthScale = scrollViewSize.width / imageViewSize.width
let heightScale = scrollViewSize.height / imageViewSize.height
scrollView.minimumZoomScale = min(widthScale, heightScale)
scrollView.zoomScale = 1.0
}
func scrollViewDidZoom(scrollView: UIScrollView) {
let imageViewSize = imageView.frame.size
let scrollViewSize = scrollView.bounds.size
let verticalPadding = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
let horizontalPadding = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0
scrollView.contentInset = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
}
func setupGestureRecognizer() {
let doubleTap = UITapGestureRecognizer(target: self, action: "handleDoubleTap:")
doubleTap.numberOfTapsRequired = 2
scrollView.addGestureRecognizer(doubleTap)
}
func handleDoubleTap(recognizer: UITapGestureRecognizer) {
if (scrollView.zoomScale > scrollView.minimumZoomScale) {
scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
} else {
scrollView.setZoomScale(scrollView.maximumZoomScale, animated: true)
}
}
}
Your scrollview is blocking the UIButton on z axis, please use
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
to insert scrollview below UIButton
Swift:
func insertSubview(view: UIView, atIndex index: Int) {
}
Answer:
Instead of this line view.addSubview(scrollView), you need to do self.view.insertSubview(scrollView, atIndex: 0) and make sure UIButton is above the scrollView.
You have to write:
self.view.insertSubview(scrollview, belowSubview: button)

Resources