如何使用图像视图制作无限分页滚动视图?

Posted

技术标签:

【中文标题】如何使用图像视图制作无限分页滚动视图?【英文标题】:How do I make an infinite paged scroll view with image views? 【发布时间】:2015-05-29 10:23:51 【问题描述】:

我有一个分页的 UIScrollView,它每 5 秒自动向左滚动 4 个 UIImage 视图。当滚动视图到达第 4 个图像视图时,它会一直滚动回第一个图像视图并重新开始。

创建无限滚动视图错觉的最佳方法是什么?换句话说,我只是希望它继续向前滚动而不是滚动视图,当它到达第 4 个图像视图时,它会向前滚动并且图像视图 #1 就在那里。

我想过当滚动视图到达第四张图片时重新添加图像视图并增加滚动视图的内容大小,但这不是很聪明...... idk

到目前为止,这是我的代码:

我的声明:

var pageImages = [UIImage]()
var pageViews: [UIImageView?] = []
var scrollTimer = NSTimer()
@IBOutlet weak var carousel: UIScrollView!

在 viewDidLoad() 中:

pageImages = [UIImage(named: "featured_1.png")!,
        UIImage(named: "featured_2.png")!,
        UIImage(named: "featured_3.png")!,
        UIImage(named: "featured_4.png")!]
    for _ in 0..<pageImages.count
       pageViews.append(nil)

var pagesScrollViewSize = carousel.frame.size

        carousel.contentSize = CGSize(width: pagesScrollViewSize.width * CGFloat(pageImages.count),
            height: pagesScrollViewSize.height)

loadVisiblePages()

以及定时器每5秒调用一次的函数:

func scrollToImage() 
        let x = carousel.contentOffset.x
        if (x <= (carousel.frame.width * CGFloat(pageImages.count))/2) 
        UIView.animateWithDuration(1, animations: 
            self.carousel.contentOffset = CGPointMake(x+self.carousel.frame.width, 0)
        )
         else 
        UIView.animateWithDuration(1, animations: 
            self.carousel.contentOffset = CGPointMake(self.pageViews[0]!.frame.origin.x, 0)
        )
        
    

最后是完成批量工作的辅助函数:

func loadPage(page: Int) 
        if page < 0 || page >= pageImages.count 
            return
        

        if let pageView = pageViews[page] 

         else 
            var frame = carousel.bounds
            frame.origin.x = frame.size.width * CGFloat(page)
            frame.origin.y = 0.0

            let newPageView = UIImageView(image: pageImages[page])
            newPageView.contentMode = UIViewContentMode.ScaleToFill
            newPageView.frame = frame
            carousel.addSubview(newPageView)
            pageViews[page] = newPageView
        
    

    func loadVisiblePages() 
        let pageWidth = carousel.frame.size.width
        let page = Int(floor((carousel.contentOffset.x * 2.0 + pageWidth) / (pageWidth * 2.0)))

        let firstPage = page
        let lastPage = page + 3

        for index in firstPage...lastPage 
            loadPage(index)
        
    

【问题讨论】:

【参考方案1】:

这个想法是:

当图像在左侧超出框架时,将其移除并重新附加到最右侧图像的右侧。此时您重置内容偏移量

import UIKit

class ViewController: UIViewController 

    var pageViews: [UIImageView] = []
    var scrollTimer = NSTimer()

    @IBOutlet weak var carousel: UIScrollView!

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        pageViews = [
            UIImageView(image:UIImage(named: "featured_1.png")!),
            UIImageView(image:UIImage(named: "featured_2.png")!),
            UIImageView(image:UIImage(named: "featured_3.png")!),
            UIImageView(image:UIImage(named: "featured_4.png")!)
        ]
        var pagesScrollViewSize = carousel.frame.size
        carousel.contentSize = CGSize(width: pagesScrollViewSize.width * CGFloat(pageViews.count),height: pagesScrollViewSize.height)
        println(carousel.contentSize)

        scrollTimer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "moveLeft", userInfo: nil, repeats: true)
    

    override func viewDidAppear(animated: Bool) 
        showPage()
    

    func showPage()
        carousel.setContentOffset(CGPointZero, animated: false)
        for (index, page) in enumerate(pageViews) 
            var frame = page.frame
            frame.origin.x = carousel.frame.size.width * CGFloat(index)
            frame.origin.y = 0.0
            println(frame)
            page.contentMode = UIViewContentMode.ScaleToFill
            page.frame = frame
            carousel.addSubview(page)
        

    

    func moveLeft()
        UIView.animateWithDuration(
            1.0,
            animations: 
                let x = self.carousel.contentOffset.x
                self.carousel.contentOffset = CGPointMake(x + self.carousel.frame.width, 0)
                println(self.carousel.contentOffset)
            , completion: complete in
                self.moveLeftEnd()
            
        );
    

    func moveLeftEnd()
        let first = pageViews.removeAtIndex(0)
        pageViews.append(first)
        showPage()
    

【讨论】:

这个,我建议你看这个WWDC video,它演示了如何实现这个效果。 这实际上不起作用,但感谢您的帮助和您的时间!第一个图像视图滚动到下一个图像,然后滚动视图类型闪烁,我们回到第一个图像视图。这是第一个和第二个图像视图之间的一种不稳定循环 我很抱歉,其中一个功能有错误,我没有看到它,因为我所有的图像看起来都一样。现在可以 100% 工作,检查我所做的编辑,它取代了 moveLeftEnd() 函数。 效果很好!谢谢!您实际上所做的是删除离开屏幕的图像并将其添加到数组的末尾,对吗?这会对CPU产生重大影响吗?我注意到的另一个问题是手动滚动图像会导致图像视图偏移,并且动画的其余部分会混乱。我的旧实现没有发生这种情况。有没有办法解决这个问题?另外我想一个警告是无法向后滚动,嗯 终于想出了一个比上面那个简单得多的方法。一会儿回答问题

以上是关于如何使用图像视图制作无限分页滚动视图?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 的分页滚动视图中缩放图像?

如何在 SwiftUI 或无限列表视图中实现列表分页?

UIScrollView 无限滚动不分页

水平滚动视图不滚动

如何在滚动视图中填充图像以填充屏幕?

使用三个视图的无限循环分页 UIScrollView