使用UIScrollView子视图的视差效果

时间:2014-03-05 15:16:11

标签: ios objective-c uiview uiscrollview parallax

我正在尝试在UIScrollView内的UIView上创建一个Parallax效果。 效果似乎有效,但不太好。

  1. 首先,我将两个UIView子视图添加到UIScrollView并设置UIScrollViews 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);
    
        }
    }
    
  4. 这些代码行确实会产生视差效果,但是当滚动继续时,如果我滚动到原始起始位置,视图不会返回到原始位置。

    我尝试过操作视图图层和框架,所有结果都相同。

    任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:15)

您遇到的问题是您的二次滚动基于偏移量与大小的比率,而不仅仅是当前偏移量。所以当你从99的偏移量增加到100(比如说100)时,你的辅助卷轴增加10,但当你回到99时,你的辅助卷轴只会减少9.9,因此不再是这是你最后一次在99.非线性滚动是可能的,但不是你的方式。

更简单的方法是创建第二个scrollview并将其放在实际的scrollview下面。使它非难以处理(setUserInteractionEnabled:false)并在主滚动委托期间修改它的contentOffset,而不是尝试手动移动UIImageView。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    [scrollView2 setContentOffset:CGPointMake(scrollView.contentOffset.x,scrollView.contentOffset.y * someScalingFactor) animated:NO];
}

但请确保不要为scrollView2设置委托,否则您可能会收到一个循环委托方法调用,这对您来说不会很好。

答案 1 :(得分:4)

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

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

假设2 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)
}

最终效果

Parallax effect

前后两个卷轴每个都包含一个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上找到其他详细信息。