【问题标题】:Parallax effect with UIScrollView subviewsUIScrollView 子视图的视差效果
【发布时间】:2014-04-07 17:53:46
【问题描述】:

我正在尝试在 UIScrollView 内的 UIView 上创建视差效果。 效果似乎有效,但效果不是很好。

  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);
    
        }
    }
    

这些代码行确实会产生视差效果,但是随着滚动的继续,如果我滚动到原始起始位置,视图不会返回到它的原始位置。

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

任何帮助将不胜感激。

【问题讨论】:

  • 条件等于百分比 = fabs(percentage);,这似乎是错误的。当你只用 else 块替换条件时,它看起来如何?
  • 我没有尝试过,所以不是答案,但这段代码对我来说看起来更有希望:github.com/ralfbernert/RBParallaxScrolling/blob/master/…
  • @danh,如果我用“else”替换“if”,当我向下滚动(偏移量 = -x)时,视图会慢慢反弹。
  • 我在答案中添加了一个编辑,以数字方式解释您的问题存在的原因。

标签: ios objective-c uiview uiscrollview parallax


【解决方案1】:

您遇到的问题是您的辅助滚动基于偏移量与大小的比率,而不仅仅是当前偏移量。因此,当您从 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 弹跳是创作者的一项练习,但绝对可以。我发现 iPad 上可能出现的弹跳量是屏幕宽度或高度的 37%,仅供本次活动参考。
  • @Putz1103 感谢您的回答。当您说将 scrollView2 放在实际滚动视图下方时,您的意思是给它一个 Z 索引?
  • @Raz 不,只需将它放在视图层次结构中的任何位置即可。您可以在 UIView 中使用bringSubviewToFrontsendSubviewToBack 来获得您想要的最终结果。
  • @Putz1103,很好的解决方案。谢谢!
【解决方案2】:

比例因子是关键因素...

...让我提供一个 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)
}

最终效果

前后两个滚动条都包含一个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 上查找更多详细信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多