UIScrollView Reusable Views

时间:2019-04-17 01:19:35

标签: ios swift uiview uiviewcontroller uiscrollview

I would like to create a UIScrollView that cycles between 3 paging views infinitely while I change the subviews to hold different reusable view controllers giving the illusion of infinitely many screen while only allocating the resources for 3 screens at a time similar to a UICollectionView.

Below is an attempt I've made at implementing such a view based on this answer Infinite UIScrollView however my project has not been working as expected.

Ive been trying to use 3 views as the basis for infinite scrolling and many labels as the subviews to be added and removed as the user scrolls.

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

    var scrollView:UIScrollView = {
        let scrollView:UIScrollView = UIScrollView()
        scrollView.backgroundColor = UIColor.orange
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    }()

    var labels:[CustomLabel] = [CustomLabel]()

    var pages:[Page] = [Page]()

    var visiblePages:Set<Page>!{
        didSet{
            print("visible pages count: \(recycledPages.count)")
        }
    }
    var recycledPages:Set<Page>!{
        didSet{
            print("recycled pages count: \(recycledPages.count)")
        }
    }

    var visibleLabels:Set<CustomLabel>!
    var recycledLabels:Set<CustomLabel>!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        recycledPages = Set<Page>()
        visiblePages = Set<Page>()

        recycledLabels = Set<CustomLabel>()
        visibleLabels = Set<CustomLabel>()


        scrollView.contentSize = CGSize(width: view.bounds.width * 3, height: view.bounds.height)
        scrollView.delegate = self
        scrollView.isPagingEnabled = true
        scrollView.indicatorStyle = .white
        view.addSubview(scrollView)


        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: view.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
            ])

        configureLabels()
        setUpPages()

        for i in 0..<pages.count{
            scrollView.addSubview(pages[i])
        }
    }

    func setUpPages(){
        let page1 = Page(),page2 = Page(),page3 = Page()

        page1.backgroundColor = .red
        page2.backgroundColor = .green
        page3.backgroundColor = .blue

        page1.index = 0
        page2.index = 1
        page3.index = 2

        pages = [page1,page2,page3]
        visiblePages = [page1,page2,page3]
        setContentViewFrames()
    }

    func configureLabels(){
        let label1 = CustomLabel(), label2 = CustomLabel(), label3 = CustomLabel()

        label1.text = "label1"
        label2.text = "label2"
        label3.text = "label3"

        label1.backgroundColor = .red
        label2.backgroundColor = .green
        label3.backgroundColor = .blue

        labels = [label1,label2,label3]
        setContentViewFrames()
    }



    //    func dequeueRecycledPage()->CustomLabel?{
    //        let page = recycledPages.first
    //        if let page = page{
    //            recycledPages.remove(page)
    //            return page
    //        }
    //        return nil
    //    }

    var currentIndex = 0
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if (scrollView.contentOffset.x < 0) {
            let newOffset = CGPoint(x: scrollView.bounds.width + scrollView.contentOffset.x, y: 0)
            scrollView.contentOffset.x = newOffset.x
            rotateViewsRight()
        }else if(scrollView.contentOffset.x > scrollView.bounds.size.width*2){
            let newOffset = CGPoint(x: scrollView.contentOffset.x - scrollView.bounds.width, y: 0)
            scrollView.contentOffset.x = newOffset.x
            rotateViewsLeft()
        }
        print("current index: \(currentIndex)")
    }

    lazy var previousOffset:CGPoint = CGPoint()

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        print("currentIndex called")

        if previousOffset.x < scrollView.contentOffset.x{
            currentIndex += 1
        }else if previousOffset.x > scrollView.contentOffset.x{
            currentIndex  -= 1
        }

        previousOffset = scrollView.contentOffset
    }

    func rotateViewsRight(){
        let endView = pages.removeLast()
        pages.insert(endView, at: 0)
        setContentViewFrames()
    }

    func rotateViewsLeft(){
        let endView = pages.removeFirst()
        pages.append(endView)
        setContentViewFrames()
    }

    func setContentViewFrames(){
        for i in 0..<pages.count{
    //            let adjustedIndex = i % pages.count
    //            let view = pages[i]
    //            view.frame = CGRect(origin: CGPoint(x: view.bounds.width * CGFloat(i), y: 0), size: view.bounds.size)
            pages[i].frame = CGRect(x: CGFloat(i)*view.bounds.width, y: 0, width: view.bounds.width, height: view.bounds.height)
            let label = labels[currentIndex%labels.count]
            label.text = "current label: \(currentIndex)"
            label.frame = pages[i].frame
            pages[i].addSubview(label)

        }

    }

    func configurePage(forIndex index:Int){

    }


    func dequeueRecycledPage()->Page?{
        let page = recycledPages.first
        if let page = page{
            recycledPages.remove(page)
            return page
        }
        return nil
    }
}

0 个答案:

没有答案