LLCtlPageView类分析

作者: 谌文 | 来源:发表于2019-11-12 17:57 被阅读0次

LLCtlPageView分析

LLCtlPageView是用来陈放自控制器view的容器,是继承UIScrollView

open class LLCtlPageView: UIScrollView {

实现的一个类, 功能类似系统的tableview,有协议方法LLCtlPageViewDataSource, 用于获取数据源

实现原理

通过LLCtlPageViewDataSource获取自控制器view数据源
然后通过实现UIScrollViewDelegate代理方法scrollViewDidScroll来刷新和设置(reloadCurrentShowView)子控制器view的frame位置
注意点: 此类由于是UIScrollView类型,在侧滑时会与导航侧滑想冲突,所以为了解决这个问题,该类实现extension LLCtlPageView:UIGestureRecognizerDelegate该代理的

    // 这个方法返回YES,第一个和第二个互斥时,第二个会失效, 解决手势冲突,返回false不处理,系统会默认处理
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool 

的方法

//
//  LLViewControllerContainerView.swift
//  LLScrollerView
//
//  Created by apple on 2019/1/17.
//  Copyright © 2019年 lilin. All rights reserved.
//

import UIKit

// MARK: 获取自控制器view的代理方法
public protocol LLCtlPageViewDataSource:NSObjectProtocol {
    func numberOfItems(in pageView:LLCtlPageView) -> Int
    func pageView(_ pageView: LLCtlPageView, viewForItemAt index: NSInteger) -> UIView
}

// MARK: - 盛放子控制器view的类
open class LLCtlPageView: UIScrollView {
    //预加载范围,当前view前面几个,后面几个
    public var preLoadRange = 0...0
    
    private var itemCount = 0
    internal weak var dataSoure:LLCtlPageViewDataSource!{
        didSet{
            reloadData()
        }
    }
    
    init(frame: CGRect,ctls:[UIViewController]) {
        super.init(frame: frame)
        initSubViews()
    }
    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    fileprivate func initSubViews() {
        self.delegate = self
        self.backgroundColor = UIColor.clear
        /// 整页滚动
        self.isPagingEnabled = true
        /// 不需要弹性
        self.bounces = false
        /// 内边距为0
        self.contentInset = UIEdgeInsets.zero
        /// 不展示横竖滑动条
        self.showsHorizontalScrollIndicator = false
        self.showsVerticalScrollIndicator = false
        self.isDirectionalLockEnabled = true
        if #available(iOS 11.0, *) {
            self.contentInsetAdjustmentBehavior = .never
        }
    }
}

// MARK: - 盛放子控制器view的类,扩展方法
extension LLCtlPageView{
    /// 展示那个子控制器view
    internal func reloadCurrentIndex(index:NSInteger){
        self.contentOffset = CGPoint.init(x: CGFloat(index)*self.bounds.width, y: 0)
    }
    
    /// 刷新(如添加或者减少啦一个自控制器view)
    internal func reloadData() {
        /// 获取代理实现的自控制器的数量
        itemCount = dataSoure.numberOfItems(in: self)
        self.contentSize = CGSize.init(width: CGFloat(itemCount)*self.bounds.width, height: self.bounds.height)
        /// 刷新当前展示的自控制器view
        reloadCurrentShowView()
    }
    
    /// 刷新当前展示的自控制器view和pageview
    fileprivate func reloadCurrentShowView() {
        guard itemCount > 0 else { return }
        
        let showPages = getShowPageIndex(maxCount: itemCount - 1)
        var pages = [NSInteger]()
        let left = showPages.leftIndex - preLoadRange.lowerBound
        let right = showPages.rightIndex + preLoadRange.upperBound
        for index in left...right {
            if (0...itemCount-1).contains(index){
                pages.append(index)
            }
        }
        
        for index in pages {
            let showView = dataSoure.pageView(self, viewForItemAt: index)
            showView.frame = CGRect.init(x: CGFloat(index)*bounds.width, y: 0, width: bounds.width, height: bounds.height)
            if !subviews.contains(showView){
                addSubview(showView)
            }
        }
    }
}

// MARK: - 实现手势代理
extension LLCtlPageView:UIGestureRecognizerDelegate{
    // 这个方法返回YES,第一个和第二个互斥时,第二个会失效, 解决手势冲突,返回false不处理,系统会默认处理
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        if !gestureRecognizer.isKind(of: UIPanGestureRecognizer.classForCoder()) || !otherGestureRecognizer.isKind(of: UIPanGestureRecognizer.classForCoder()){
            return false
        }
        
        guard let gestureView = gestureRecognizer.view as? LLCtlPageView else{
            return false
        }
        
        guard let otherGestureView = otherGestureRecognizer.view as? LLCtlPageView else{
            return false
        }

        if gestureView != self {
            return false
        }
        
        let currentIndex = Int(gestureView.contentOffset.x / gestureView.bounds.width)
        let subIndex = Int(otherGestureView.contentOffset.x / otherGestureView.bounds.width)
        if subIndex > 0 {
            return false
        }else if subIndex == 0 {
            if currentIndex == gestureView.itemCount - 1 {
                return true
            }
            return false
        }
        return false
    }
}

extension LLCtlPageView:UIScrollViewDelegate{
    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
        reloadCurrentShowView()
    }
}

extension UIScrollView{
    fileprivate func getShowPageIndex(maxCount:NSInteger) -> (leftIndex:NSInteger,rightIndex:NSInteger) {
        let index = self.contentOffset.x/self.bounds.width
        let leftItemIndex = max(0, min(maxCount, Int((index))))
        let rightItemIndex = max(0, min(maxCount, Int(ceil(index))))
        return (leftItemIndex,rightItemIndex)
    }
}

相关文章

  • LLCtlPageView类分析

    LLCtlPageView分析 LLCtlPageView是用来陈放自控制器view的容器,是继承UIScroll...

  • ios 底层原理 : 类与类结构分析

    本文主要分析类与类结构 类的分析 类的分析主要是分析 isa 的走向与继承关系 准备 创建两个类 1.继承自 NS...

  • OC底层原理 07:类 & 类结构分析

    本文的主要目的是分析 类 & 类的结构,整篇都是围绕一个类展开的一些探索 类 的分析 类的分析 主要是分析 isa...

  • iOS底层原理07:类 & 类结构分析

    本文的主要目的是分析 类 & 类的结构,整篇都是围绕一个类展开的一些探索 类的分析 类的分析主要是分析 isa的走...

  • iOS底层类结构分析

    类 的分析 类的分析 主要是分析 isa的走向 以及 继承关系 定义两个类 继承自NSObject的类LGPers...

  • iOS 类的结构分析

    类 的分析 类的分析 主要是分析 isa的走向 以及 继承关系 准备工作 定义两个类 继承自NSObject的类C...

  • iOS 类原理探索:类的结构分析

    OC 类原理探索 系列文章 OC 类原理探索:类的结构分析 OC 类原理探索:类结构分析补充[https://ju...

  • 类,类结构分析

    忙不是不学习的借口 在isa和类的关联[https://www.jianshu.com/p/079a6ad90f1...

  • 8、面向对象

    分析面向对象 先分析类,分析静态的属性和动态的方法 创建对象:类名 对象名=new 类名(); 为对象的属性赋值:...

  • Jun_25.md

    今日任务 以主类为目标尝试新的分析方式 Que 0x01 整理分析的主类 当前分析主类: com.samsung....

网友评论

    本文标题:LLCtlPageView类分析

    本文链接:https://www.haomeiwen.com/subject/tjrqictx.html