我有一个我想要在我的应用程序中实现的场景,当我开始强制它滚动超过其正常的内容界限时,我想使UIScrollView的行为更加“僵硬”.
我的意思是,当你在滚动视图的顶部或底部,如果你点击并继续拖动,你通常可以得到滚动视图,以保持超越其界限,但它逐渐建立抵抗,直到它在视野的中间通常约一半.当您抬起手指时,它会回到滚动区域的边界.
我想要实现的是,我想让这个“超越”的拖拽效果变得更加沉重,所以,而不是用户拖动滚动视图,并且它的“触底”中途通过滚动视图界限,它完全停止了大约20%左右的滚动边界.
我一直在试验覆盖scrollViewDidScroll:delegate方法中的滚动视图的contentOffset,但这似乎没有起作用,因为在其中重新设置contentOffset似乎削弱了相同方法的进一步委托调用.
我的下一个想法是监视与scrollview关联的UIPanGestureRecognizer,并根据不同的事件尝试确定正确的UIScrollView contentOffset.话虽如此,我认为这可能会开始恶作剧,所以我以为我会在这里提出我之前没有考虑过的其他解决办法,然后再尝试一些可能会混乱的事情.
谢谢!
解决方法
我在
Swift的以下代码中加注.这是用于水平滚动,可以轻松地适应垂直滚动.解决方案根据是否启用分页是不同的.两者都在下面给出.
class ScrollViewDelegate : NSObject,UIScrollViewDelegate { let maxOffset: CGFloat // offset of the rightmost content (scrollview contentSize.width - frame.width) var prevOffset: CGFloat = 0 // prevIoUs offset (after adjusting the value) var totalDistance: CGFloat = 0 // total distance it would have moved (had we not restricted) let reductionFactor: CGFloat = 0.2 // percent of total distance it will be allowed to move (under restriction) let scaleFactor: CGFloat = UIScreen.mainScreen().scale // pixels per point,for smooth translation in respective devices init(maxOffset: CGFloat) { self.maxOffset = maxOffset // scrollView.contentSize.width - scrollView.frame.size.width } func scrollViewDidScroll(scrollView: UIScrollView) { let flipped = scrollView.contentOffset.x >= maxOffset // dealing with left edge or right edge rubber band let currentOffset = flipped ? maxOffset - scrollView.contentOffset.x : scrollView.contentOffset.x // for right edge,flip the values as if screen is folded in half towards the left if(currentOffset <= 0) // if dragging/moving beyond the edge { if(currentOffset <= prevOffset) // if dragging/moving beyond prevIoUs offset { totalDistance += currentOffset - prevOffset // add the "proposed delta" move to total distance prevOffset = round(scaleFactor * totalDistance * reductionFactor) / scaleFactor // set the prevOffset to fraction of total distance scrollView.contentOffset.x = flipped ? maxOffset - prevOffset : prevOffset // set the target offset,after negating any flipping } else // if dragging/moving is reversed,though still beyond the edge { totalDistance = currentOffset / reductionFactor // set totalDistance from offset (reverse of prevOffset calculation above) prevOffset = currentOffset // set prevOffset } } else // if dragging/moving inside the edge { totalDistance = 0 // reset the values prevOffset = 0 } } }
启用分页时,弹回到休息点看起来似乎不能正常工作.橡胶带不是在页面边界处停止,而是以非页面偏移量超过它并停止.如果来自边缘的拉拽快速滑动,即使在抬起手指之后,在反转方向并返回到静止点之前,它也会沿着该方向继续移动.如果你只是暂停或离开,甚至轻轻地摆放到休息点,它似乎工作正常.为了解决这个问题,在下面的代码中,我尝试确定超调的可能性,并在返回时强制停止它,并试图跨越预期的页面边界.
class PageScrollViewDelegate : NSObject,for smooth translation in respective devices var draggingOver: Bool = false // finger dragging is over or not var overshoot: Bool = false // is there a chance for page to overshoot page boundary while falling back init(maxOffset: CGFloat) { self.maxOffset = maxOffset // scrollView.contentSize.width - scrollView.frame.size.width } func scrollViewWillBeginDragging(scrollView: UIScrollView) { draggingOver = false // reset the flags overshoot = false } func scrollViewDidEndDragging(scrollView: UIScrollView,willDecelerate decelerate: Bool) { draggingOver = true // finger dragging is over } func scrollViewDidScroll(scrollView: UIScrollView) { let flipped = scrollView.contentOffset.x >= 0.5 * maxOffset // dealing with left edge or right edge rubber band let currentOffset = flipped ? maxOffset - scrollView.contentOffset.x : scrollView.contentOffset.x // for right edge,flip the values as if screen is folded in half towards the left if(currentOffset <= 0) // if dragging/moving beyond the edge { if(currentOffset <= prevOffset) // if dragging/moving beyond prevIoUs offset { overshoot = draggingOver // is content moving farther away even after dragging is over (caused by fast flick,which can cause overshooting page boundary while falling back) totalDistance += currentOffset - prevOffset // add the "proposed delta" move to total distance prevOffset = round(scaleFactor * totalDistance * reductionFactor) / scaleFactor // set the prevOffset to fraction of total distance scrollView.contentOffset.x = flipped ? maxOffset - prevOffset : prevOffset // set the target offset,though still beyond the edge { totalDistance = currentOffset / reductionFactor // set totalDistance from offset (reverse of prevOffset calculation above) prevOffset = currentOffset // set prevOffset } } else // if dragging/moving inside the edge { if(overshoot) // if this movement is a result of overshooting { scrollView.setContentOffset(CGPointMake(flipped ? maxOffset : 0,scrollView.contentOffset.y),animated: false) // bring it to resting point and stop further scrolling (this is a patch to control overshooting) } totalDistance = 0 // reset the values prevOffset = 0 } } }