iOS中具有视差背景的水平滚动

14

看看这个,一个非常酷的框架。这就是 IFFT 如何建立他们的介绍页面的方式:https://github.com/IFTTT/JazzHands - The dude
谢谢您的评论,我查看了那些资源,但它并没有真正回应我所需要的。 - sazz
你能否给我提供一些示例代码?我发现很难理解。@SofienAzzouz - iOSDeveloper
2个回答

14

没错。

你需要两个UIScrollView,它们都应该是主视图的子视图(不包含在彼此中)。

下面一个包含你的图像,上面一个包含内容。

把它们叫做imageScrollViewcontentScrollView

成为contentScrollView的代理。

内容将看起来像这样...

contents:    [---page 1---][---page 2---][---page 3---][---page 4---]
image:       [------------the image------------]
screen:      [---screen---]

关键在于图像比所有页面都要小,但比屏幕大。

滚动视图的框架宽度与屏幕相同。此图仅显示内容宽度而非框架宽度。

因此,屏幕保持不动,而两个滚动视图在其上移动。

现在是视差部分...

- (CGFloat)maxOffsetForScrollView:(UIScrollView *)scrollView
{
    CGFloat contentWidth = scrollView.contentSize.width;
    CGFloat frameWidth = CGRectGetWidth(scrollView.frame);

    return contentWidth - frameWidth;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    // this is the delegate method for the content scroll view.
    // I'm only doing horizontal stuff here, you can do vertical too if you want

    CGFloat maximumContentOffset = [self maximumOffsetForScrollView:self.contentScrollView];
    CGFloat currentOffset = self.contentScrollView.contentOffset.x;

    CGFloat percentageOffset = currentOffset/maximumContentOffset;

    CGFloat maximumImageOffset = [self maximumContentOffsetForScrollView:self.imageScrollView];
    CGFloat actualImageOffset = maximumImageOffset * percentageOffset;

    [self.imageScrollView setContentOffset:CGPointMake(actualImageOffset, 0)];
}

这会从内容视图中获取百分比偏移量,并将图像视图按相同的百分比偏移。

结果是视差效果。您可以通过改变图像和内容的相对大小来使其更快或更慢。更多页面(或较小的图像)= 较慢的视差。


1
@SofienAzzouz 啊,Safari 中的重构并不是很有帮助 :) 现在已经编辑过了。maximumOffsetForScrollView: 是我回答中定义的一个函数。它返回给定滚动视图的最大偏移量。 - Fogmeister
2
好的,但我仍然不知道如何管理contentScrollView中的不同视图?以及如何将背景图像与imageScrollView相关联?我应该创建一个ImageView并将其放入imageScrollView中吗? - sazz
2
明白了,我需要将这两个scrollView变大才能看到过渡效果。非常感谢你的帮助 :) - sazz
1
请问您能否给我提供一些示例代码?我发现很难理解。@Fogmeister - iOSDeveloper
1
@iOSDeveloper 这是链接 http://www.oliverfoggin.com/controlling-animations-with-a-uiscrollview/ 除了我在这个回答中编写的方法之外,没有其他示例代码。 - Fogmeister
显示剩余2条评论

2

我一直在苦苦探索这个视差效果。虽然没有@Fogmeister的指导,我可能做不到,但我仍然需要自己解决一些问题。 无论如何,这里是Swift 2.0版本的代码(希望更加完整):

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {


    var backgroundScrollView: UIScrollView!
    var contentScrollView: UIScrollView!
    var imageView: UIImageView!
    var contentView: UIView!
    var maxContentOffset: CGFloat!
    var maxBackgroundOffset: CGFloat!
    var cvbw: CGFloat!
    var page: Int = 1

    override func viewDidLoad() {
        super.viewDidLoad()
        self.createBackground()
        self.createContent()
    }

    func createBackground() {
        self.imageView = UIImageView(image: UIImage(named: "ParalaxMaterial.jpg"))  //ParalaxMaterial.jpg is of size: 2500 x 2668px
        self.imageView.frame = CGRectMake(0, 0, ((self.view.bounds.height/2668) * 2500), self.view.bounds.height)
        self.backgroundScrollView = UIScrollView(frame: view.bounds)
        self.backgroundScrollView.backgroundColor = UIColor.redColor()
        self.backgroundScrollView.contentSize = imageView.bounds.size
        self.backgroundScrollView.addSubview(self.imageView)
        self.view.addSubview(self.backgroundScrollView)
        self.maxBackgroundOffset = self.maxOffsetForScrollView(self.backgroundScrollView)
    }

    func createContent() {
        self.contentView = UIView(frame: CGRectMake(0, 0, (self.view.bounds.width * 3), self.view.bounds.height))
        self.contentScrollView = UIScrollView(frame: view.bounds)
        self.contentScrollView.backgroundColor = UIColor.clearColor()
        self.contentScrollView.contentSize = self.contentView.bounds.size
        self.contentScrollView.delegate = self
        let firstButton = UIButton()
        firstButton.frame = CGRectMake(((self.contentView.bounds.width / 6) - 150), 300, 300, 100)
        firstButton.setTitle("START", forState: UIControlState.Normal)
        firstButton.titleLabel?.font = UIFont(name: "Arial", size: 18)
        firstButton.addTarget(self, action: "firstAction:", forControlEvents: UIControlEvents.TouchUpInside)
        self.contentView.addSubview(firstButton)
        let firstLabel = UILabel()
        firstLabel.frame = CGRectMake(((self.contentView.bounds.width / 6) - 100), 0, 200, 200)
        firstLabel.text = "#BrusselsLockDown"
        firstLabel.textAlignment = NSTextAlignment.Center
        self.contentView.addSubview(firstLabel)
        let secondLabel = UILabel()
        secondLabel.frame = CGRectMake(((self.contentView.bounds.width / 2) - 100), 0, 200, 200)
        secondLabel.text = "#LolCats"
        secondLabel.textAlignment = NSTextAlignment.Center
        self.contentView.addSubview(secondLabel)
        let thirdLabel = UILabel()
        thirdLabel.frame = CGRectMake((((self.contentView.bounds.width / 6) * 5) - 100), 0, 200, 200)
        thirdLabel.text = "#Final"
        thirdLabel.textAlignment = NSTextAlignment.Center
        self.contentView.addSubview(thirdLabel)
        self.contentScrollView.addSubview(self.contentView)
        self.view.addSubview(self.contentScrollView)
        self.maxContentOffset = self.maxOffsetForScrollView(self.contentScrollView)
        self.cvbw = self.contentView.bounds.width
    }

    func scrollViewWillBeginDecelerating(scrollView: UIScrollView) {
        if self.page == 1 {
            if scrollView.contentOffset.x > 0 {
                scrollView.setContentOffset(CGPointMake((self.cvbw / 3), 0), animated: true)
            }
        } else if self.page == 2 {
            if scrollView.contentOffset.x < (self.cvbw * 4/12) {
                scrollView.setContentOffset(CGPointMake(0, 0), animated: true)
            } else if scrollView.contentOffset.x > (self.cvbw * 4/12) {
                scrollView.setContentOffset(CGPointMake(((self.cvbw / 3) * 2), 0), animated: true)
            }
        } else if self.page == 3 {
            if scrollView.contentOffset.x < (self.cvbw * 8/12) {
                scrollView.setContentOffset(CGPointMake((self.cvbw / 3), 0), animated: true)
            }
        } else {
            print("self.page messed up")
        }
    }


    func scrollViewDidScroll(scrollView: UIScrollView) {
        if scrollView == self.contentScrollView {
            let percentageOffset: CGFloat = self.contentScrollView.contentOffset.x / self.maxContentOffset
            let currentBackgroundOffsetPoint: CGPoint = CGPointMake(((self.maxBackgroundOffset * percentageOffset) + 50), 0)                self.backgroundScrollView.setContentOffset(currentBackgroundOffsetPoint, animated: false)
        }

        if self.contentScrollView.contentOffset.x == 0 {
            print("page 1")
            self.page = 1
        } else if self.contentScrollView.contentOffset.x == 320 {
            print("page 2")
            self.page = 2
        } else if self.contentScrollView.contentOffset.x == 640 {
            print("page 3")
            self.page = 3
        }
    }


    func maxOffsetForScrollView(scrollView: UIScrollView) -> CGFloat {
        let contentWidth: CGFloat = scrollView.contentSize.width - 100
        let frameWidth: CGFloat = CGRectGetWidth(scrollView.frame)
        return contentWidth - frameWidth
    }


    func firstAction (sender: UIButton) {
        print("firstAction")
        self.contentScrollView.setContentOffset(CGPointMake((self.cvbw / 3), 0), animated: true)
    }
}

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