代码之家  ›  专栏  ›  技术社区  ›  Raz

UIScrollView子视图的视差效果

  •  13
  • Raz  · 技术社区  · 12 年前

    我试图在UIScrollView中的UIView上创建视差效果。 这种效果似乎有效,但不是很好。

    1. 首先,我将两个UIView子视图添加到UIScrollView中,并设置UIScrollViews contentSize。
    2. 视图汇总并创建一个contentSize为{320,1000}。
    3. 然后我在scrollViewDidSoll中实现了以下内容:

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

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

    我已经尝试过操纵视图层和框架,结果都是一样的。

    如有任何帮助,将不胜感激。

    2 回复  |  直到 12 年前
        1
  •  16
  •   Putz1103    12 年前

    您的问题是,您的二次滚动基于偏移量与大小的比率,而不仅仅是基于当前偏移量。因此,当你从偏移量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 ,否则您可能会得到一个循环委托方法调用,这对您来说不会很好。

        2
  •  4
  •   SwiftArchitect    9 年前

    缩放因子是关键要素。。。

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

    推荐文章