ios – 增加UIScrollView橡胶条带阻力

我有一个我想要在我的应用程序中实现的场景,当我开始强制它滚动超过其正常的内容界限时,我想使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
        }
    }
}

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...