【问题标题】:Parallax view scrolling (Yahoo weather like)视差视图滚动(雅虎天气之类)
【发布时间】:2013-07-31 19:47:02
【问题描述】:

这不是严格意义上的编程问题,而是更多“如何完成这个”问题。

我很好奇(并且正在开发可能需要此功能的应用程序)左右视差滚动是如何实现的。要确切了解我的意思,请查看 Yahoo Weather 应用程序(它是免费的 - 不用担心)。

他们是只使用一个视图控制器,还是为那里显示的每个视图使用一个单独的控制器?
实现这一点的最简单方法是什么?我找到了this topic here,这有点解释了,但是他们什么时候从他们的服务器获取信息?是在视图更改时还是在应用启动时?

任何关于如何实现这种滚动的信息将不胜感激。

【问题讨论】:

    标签: ios graphics parallax


    【解决方案1】:

    其实很简单:

    • 子类 UIScrollView
    • 添加一个 UIView *parallaxView;作为@property
    • 添加一个 CGFloat parallaxFactor 作为@property
    • 覆盖 layoutSubviews
    • 调用super,然后使用self.scrollOffset*parallaxFactor定位视差视图

    就是这样!

    我自己制作了一个多功能 UIScrollView 子类,使用起来非常简单,非常适合这种情况!在 GitHub 上获取:https://github.com/LeonardPauli/LPParallaxScrollView

    祝你好运!

    【讨论】:

    • 是的,这确实处理了可见部分。但是功能呢?例如,如果用户想要更新天气,他将视图拉下并使用最新的天气信息刷新。我怀疑他们使用ifs 来确定呈现哪个视图。有什么想法吗?
    • 我开源了我不久前做的东西! github.com/LeonardPauli/MYParallaxScrollView 只需使用 parallaxView.currentPageIndex :) 但更好的是,为每个页面使用不同的垂直(简单块的视差)滚动视图,并在那里重新加载。 (不要忘记让手势识别器相互阻挡):D
    • 我今天试着让它打勾,但你忘了包括UIView+myExt.h。你也可以发一下吗?
    • 哦,对不起!马上添加!
    • 看起来像一个很棒的图书馆。希望能在 cocoapods 上使用它;)
    【解决方案2】:

    我实现了一个基于标准 UIPageViewController 子类的小型原型,以及用于视差效果的自动布局约束。 如果您想看一下,它的文档非常完整:TestParallax

    简而言之,视差的核心是在scrollViewDidScroll委托方法中完成的:

    extension PageViewController: UIScrollViewDelegate {
    
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            let screenWidth = scrollView.bounds.width
            /*
             In a UIPageViewController, the initial contentOffset.x is not 0, but equal to the screen width
             (so that the offset goes between (1 * screenWidth) and 0 when going to the previous view controller, 
             and from (1 * screenWidth) to (2 * screenWidth) when going to the next view controller).
             Also, it's reset to the screenWidth when the scroll to a previous or next view controller is complete.
             Therefore, we calculate a new 'horizontalOffset' starting at 0, and going:
             - negative from 0 to (-screenWidth/2) when scrolling to the next view controller,
             - and from 0 to (screenWidth/2) when scrolling to the previous view controller.
             */
            let horizontalOffset = (scrollView.contentOffset.x - screenWidth)/2
    
            // Special case: initial situation, or when the horizontalOffset is reset to 0 by the UIPageViewController.
            guard horizontalOffset != 0 else {
                previousPageController?.offsetBackgroundImage(by: screenWidth/2)
                currentPageController?.offsetBackgroundImage(by: 0)
                nextPageController?.offsetBackgroundImage(by: -screenWidth/2)
                return
            }
    
            // The background image of the current page controller should always be offset by the horizontalOffset (which may be positive or negative)
            guard let currentPageController = currentPageController else { return }
            currentPageController.offsetBackgroundImage(by: horizontalOffset)
    
            if horizontalOffset > 0 { // swiping left, to the next page controller
    
                // The background image of the next page controller starts with an initial offset of (-screenWidth/2), then we apply the (positive) horizontalOffset
                if let nextPageController = nextPageController {
                    let nextOffset = -screenWidth/2 + horizontalOffset
                    nextPageController.offsetBackgroundImage(by: nextOffset)
                }
            } else { // swiping right, to the previous page controller
    
                // The background image of the previous page controller starts with an initial offset of (+screenWidth/2), then we apply the (negative) horizontalOffset
                if let previousPageController = previousPageController {
                    let previousOffset = screenWidth/2 + horizontalOffset
                    previousPageController.offsetBackgroundImage(by: previousOffset)
                }
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      您不应该更改页面视图控制器的滚动视图的委托。它可能会破坏其正常行为。

      相反,您可以:

      1. 向页面视图控制器的视图添加平移手势:

        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panRecognized(gesture:)))
        view.addGestureRecognizer(panGesture)
        panGesture.delegate = self
        
      2. 添加新函数以了解视图是如何滚动的。

        @objc func panRecognized(gesture: UIPanGestureRecognizer) {
            // Do whatever you need with the gesture.translation(in: view)
        }
        
      3. 将您的 ViewController 声明为 UIGestureRecognizerDelegate

      4. 实现这个功能:

        func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return true
        }
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-06
        • 2011-07-23
        • 1970-01-01
        • 1970-01-01
        • 2012-08-16
        • 2013-02-09
        • 2014-11-20
        • 1970-01-01
        相关资源
        最近更新 更多