UIScrollView子视图的视差效果

13

我正在尝试在UIScrollView内部的UIView上创建视差效果。效果似乎可以实现,但不够好。

  1. 首先,我向UIScrollView添加了两个UIView子视图,并设置了UIScrollView的contentSize。
  2. 这些视图的大小相加,创建了一个{320, 1000}的contentSize。
  3. 接着我在scrollViewDidScroll中实现了以下内容:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        CGFloat offsetY = scrollView.contentOffset.y;
    
        CGFloat percentage = offsetY / scrollView.contentSize.height;
    
        NSLog(@"percent = %f", percentage);
    
        if (offsetY < 0) {
    
            firstView.center = CGPointMake(firstView.center.x, firstView.center.y - percentage * 10);
    
        } else if (offsetY > 0){
    
            firstView.center = CGPointMake(firstView.center.x, firstView.center.y + percentage * 10);
    
        }
    }
    

这些代码确实可以创建视差效果,但是当滚动继续时,如果我滚动到原始起始位置,视图不会返回到其原始位置。

我尝试过操作视图的层和框架,但结果都一样。

非常感谢任何帮助。


这个条件语句等于百分比 = fabs(百分比);,看起来不对。如果你只用else块替换条件语句,会是什么样子呢? - danh
我没有尝试过,所以这不是一个答案,但是这段代码对我来说看起来更有前途:https://github.com/ralfbernert/RBParallaxScrolling/blob/master/ParallaxScrolling/RBViewController.m - danh
@danh,如果我将“if”替换为“else”,每当我向下滚动(offset = -x)时,视图都会缓慢弹起。 - Raz
1
我在我的答案中添加了一个编辑,以数字方式解释为什么存在你的问题。 - Putz1103
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
16
你的问题在于你根据偏移量与大小的比例来进行辅助滚动,而不是仅基于当前偏移量。因此,当你从偏移量99增加到100(例如总共有100个偏移量)时,你的辅助滚动增加了10,但是当你回到99时,你的辅助滚动只减少了9.9,并且与上一次在99时所处的位置不同了。非线性滚动是可能的,但不是你现在这样做的方式。 一种可能更简单的方法是创建一个第二个滚动视图并将其放置在实际滚动视图下方。将其设置为不可交互(setUserInteractionEnabled:false),并在主滚动委托中修改其contentOffset,而不是手动移动UIImageView。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    [scrollView2 setContentOffset:CGPointMake(scrollView.contentOffset.x,scrollView.contentOffset.y * someScalingFactor) animated:NO];
}

但是一定要确保不为 scrollView2 设置代理,否则可能会出现循环调用代理方法的情况,这对你来说不会有好结果。


像 Github 的 Ref 但更简单易用 +1。确保 scrollView2 的内容包含前景视图的弹跳区域。 - danh
@danh 反弹是一个对创建者来说很好的练习,但肯定是可以做到的。我发现在iPad上,屏幕宽度或高度可弹跳的量为37%,这只是作为本次事件的参考。 - Putz1103
@Putz1103,感谢您的回答。当您说将scrollView2放置在实际滚动视图下方时,您是指给它一个Z索引吗? - Raz
@Raz 不需要,只需将其放置在视图层次结构中的任何位置即可。您可以在UIView中使用bringSubviewToFrontsendSubviewToBack来获得所需的最终结果。 - Putz1103
@Putz1103,不错的解决方案。谢谢! - Renish Dadhaniya

4

缩放因子是关键元素...

...让我提供一个1:1的计算:

假设有两个UIScrollView,一个在前景,一个在背景,假设前景控制背景,并进一步假设在前景中的全宽度对应于背景中的全宽度,则需要应用前景比例而不是前景偏移量

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let foreSpan = foreScrolView.bounds.width - foreScrolView.contentSize.width
    let foreRatio = scrollView.contentOffset.x / foreSpan
    let rearSpan = rearScrollView.bounds.width - rearScrollView.contentSize.width
    rearScrollView.setContentOffset(
        CGPoint(x: foreRatio * rearSpan, y: 0),
        animated: false)
}

最终效果

视差效果

前后两个滚动视图,各自包含一个 UIImageView,以其全宽显示:

let foreImg = UIImageView.init(image: UIImage(named: "fore"))
foreImg.frame = CGRect(x: 0, y: 0,
                       width: foreImg.frame.width,
                       height: foreScrolView.bounds.height)
foreScrolView.contentSize = foreImg.frame.size
foreScrolView.addSubview(foreImg)

let rearImg = UIImageView.init(image: UIImage(named: "rear"))
rearImg.frame = CGRect(x: 0, y: 0,
                       width: rearImg.frame.width,
                       height: rearScrollView.bounds.height)
rearScrollView.contentSize = rearImg.frame.size
rearScrollView.addSubview(rearImg)

这将以不同的速度滚动两个图像,从边缘到边缘完全覆盖每个图像。


► 在 GitHub 上查找此解决方案,并在 Swift Recipes 上获取更多详细信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,