4

我设置了一个无限滚动视图,当它达到 0 内容偏移量时,我将其设置为最大内容偏移量,反之亦然。

IE

[scrollView setContentOffset:CGPointMake(0,0) animated:NO];

这可行,但它会阻止 UIScrollView 减速。

有没有办法做到这一点,但保持 UIScrollView 减速?

我试过这个...

float declerationRate = scrollView.decelerationRate;
[scrollView setContentOffset:CGPointMake(scrollView.frame.size.width, 0) animated:NO];
scrollView.decelerationRate = declerationRate;

但它没有用。

编辑

我刚刚意识到 decelerationRate 是确定减速的慢/快的设置。

我需要的是从滚动视图中获取当前速度。

4

4 回答 4

2

是的,我不得不稍微调整一下这个想法。

事实证明,尝试设置 UIScrollView 的速度很困难……非常困难。

所以无论如何,我有点调整它。

这实际上是一个迷你项目,在回答了别人的 SO 问题并认为我会尝试自己解决之后。

我想创建一个微调器应用程序,我可以滑动它来旋转箭头,使其旋转并减速到一个点。

我所做的是设置一个 UIImageView,箭头指向上方。

然后覆盖UIImageView的是一个UIScrollView。

然后在代码中...

@interface MyViewController () <UIScrollViewDelegate>

@property (nonatomic, weak) IBOutlet UIScrollView *scrollView;
@property (nonatomic, weak) IBOutlet UIImageView *arrowView;

@end

@implementation MyViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    //make the content size really big so that the targetOffset of the deceleration will never be met.
    self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * 100, self.scrollView.frame.size.height);
    //set the contentOffset of the scroll view to a point in the center of the contentSize.
    [self.scrollView setContentOffset:CGPointMake(self.scrollView.frame.size.width * 50, 0) animated:NO];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)rotateImageView
{
    //Calculate the percentage of one "frame" that is the current offset.

    // each percentage of a "frame" equates to a percentage of 2 PI Rads to rotate
    float minOffset = self.scrollView.frame.size.width * 50;
    float maxOffset = self.scrollView.frame.size.width * 51;

    float offsetDiff = maxOffset - minOffset;

    float currentOffset = self.scrollView.contentOffset.x - minOffset;

    float percentage = currentOffset / offsetDiff;

    self.arrowView.transform = CGAffineTransformMakeRotation(M_PI * 2 * percentage);
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    //the scrollView moved so update the rotation of the image
    [self rotateImageView];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //the scrollview stopped moving.
    //set the content offset back to be in the middle
    //but make sure to keep the percentage (used above) the same
    //this ensures the arrow is pointing in the same direction as it ended decelerating

    float diffOffset = scrollView.contentOffset.x;

    while (diffOffset >= scrollView.frame.size.width) {
        diffOffset -= scrollView.frame.size.width;
    }

    [scrollView setContentOffset:CGPointMake(scrollView.frame.size.width * 50 + diffOffset, 0) animated:NO];
}

@end

这给出了像命运之轮一样的旋转器的预期效果,它将在任一方向无休止地旋转。

虽然有一个缺陷。如果用户不停地旋转和旋转而不让它停止,那么它只会在任一方向旋转 50 次,然后才会停止。

于 2013-01-31T19:38:17.720 回答
1

正如我在评论中所说,您正在做的事情是产生预期的结果,做您想做的一种方法是将内容偏移设置为顶部,然后通过使用内容大小高度和减速值,您可以制作动画再次偏移内容,看看这个答案:https ://stackoverflow.com/a/6086521/662605

在感觉正确之前,您将不得不玩一些数学,但我认为这是一个合理的解决方法。

减速度越低,动画(时间)越长,动画越多(距离)。让我知道你的想法。

正如你所说,减速可能不是你唯一需要的。因此,您可以尝试在 contentOffset 上使用 KVO 来计算半秒内的平均速度,或许可以了解速度。

于 2013-01-31T18:45:13.630 回答
0

可能有几种不同的方法可以做到这一点。理想情况下,您不必进行任何类型的计算来模拟剩余的减速物理或完全弄乱UIScrollView的内部结构。它很容易出错,而且不太可能完全符合UIScrollView每个人习惯的物理原理。

相反,对于滚动视图只是手势驱动程序的情况(即,您实际上不需要在其中显示任何内容),我认为最好只有一个非常宽的滚动视图。将其初始内容偏移设置为其内容大小的中心。在scrollViewDidScroll(_:)中,计算遍历屏幕宽度的百分比:

let pageWidth = scrollView.frame.width
let percentage = (scrollView.contentOffset.x % pageWidth) / pageWidth

这将基本上循环从0.01.0(向右移动)或从1.00.0(向左移动)循环。您可以将这些标准化值转发给其他可以响应它的函数,也许是为了驱动动画。只需构建任何响应于此的代码,以便在从0.0to1.0或 from 1.0to跳转时看起来无缝0.0

当然,如果您需要循环播放的速度比正常的滚动视图速度更快或更慢,只需使用屏幕宽度的更小或更大的比例。我就是随便挑的。

如果您担心碰到可滚动内容的边缘,那么当滚动视图完全停止1时,将其内容偏移重置为相同的初始中心值,加上屏幕宽度的任何剩余部分(或任何你想要的使用)滚动视图在它停止滚动时所在的位置。

鉴于上面的重置方法,即使对于托管可见内容的滚动视图,只要您更新任何视图框架/模型值以考虑重置滚动偏移量,您就可以有效地实现无限滚动视图。


1要正确捕获这一点,请实现scrollViewDidEndDecelerating(_:)and scrollViewDidEndDragging(_:willDecelerate:),仅在后一种情况下调用您的“完全休息”函数willDecelerateis false。总是在前一种情况下调用它。

于 2016-12-27T22:09:07.307 回答
0

我发现如果你打电话

[scrollView setContentOffset:CGPointMake(0,0) animated:NO];

在点(0,0),它会触发 UIScrollView 的反弹动作,然后减速将停止。setContentOffset当您调用内容的绑定时,也会发生相同的情况。

因此,您可以调用setContentOffsetpoint(10,10) 或其他地方以轻松保持减速。

于 2017-09-28T03:46:31.703 回答