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)
}
}
网友评论