Horizontal scrolling with parallax background for ios

前端 未结 2 1155
小蘑菇
小蘑菇 2020-12-28 09:28

I\'m facing a challenge of creating an introduction view, something like the \"Cleanio\" app (https://itunes.apple.com/fr/app/cleanio-pressing-la-demande/id885856031?mt=8).<

相关标签:
2条回答
  • 2020-12-28 09:56

    Yep.

    What you need is two UIScrollViews. These should both be subviews of the main view (not contained in each other.

    The bottom one has your image in it and the top one has the content.

    Call them imageScrollView and contentScrollView.

    Become the delegate of contentScrollView.

    The contents will look something like this...

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

    Key is that image is smaller than all the pages and bigger than the screen.

    The frames of the scrollviews are the same width as the screen. This diagram is just to show the content widths not the frame widths.

    So, the screen stays where it is and the two scroll views move over it.

    Now the parallax part...

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

    This takes the percentage offset from the content view and offsets the image view by the same percentage offset.

    The result is a parallax effect. You can make it faster or slower by changing the relative sizes of the image and the content. More pages (or smaller image) = slower parallax.

    0 讨论(0)
  • 2020-12-28 10:12

    I had been struggling with this parallax effect for a little while. I wouldn't have done it without @Fogmeister instructions, though I still had to figure out a couple of things by myself. Anyway, here is a Swift 2.0 version, (hopefully a bit more complete):

    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)
        }
    }
    
    0 讨论(0)
提交回复
热议问题