|
//
// FFPageContentView.swift
// FFPage
//
// Created by FFIB on 2017/10/18.
// Copyright © 2017年 FFIB. All rights reserved.
//
import UIKit
protocol FFPageContentViewDataSource {
func pageContentView(pageContentView: FFPageContentView, cellForItemAt index: Int) -> FFPageContentViewCell
func numberOfSections(in pageContentView: FFPageContentView) -> Int
}
protocol FFPageContentViewDelegate {
func pageContentView(pageContentView: FFPageContentView, didSelectItemAt index: Int)
}
@IBDesignable
open class FFPageContentView: UIScrollView, UIScrollViewDelegate {
var dataSource: FFPageContentViewDataSource?
var pageDelegate: FFPageContentViewDelegate?
private var ffConstraints = [NSLayoutConstraint]()
private var nibs = [String: UINib]()
private var cells = [String: AnyClass]()
var needLayout = true
public override init(frame: CGRect) {
super.init(frame: frame)
configuration()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configuration()
}
func configuration() {
isPagingEnabled = true
showsHorizontalScrollIndicator = false
showsVerticalScrollIndicator = false
alwaysBounceVertical = false
bounces = false
alwaysBounceHorizontal = true
addObserver(self, forKeyPath: "contentOffset", options: .new, context: nil)
}
open override func layoutSubviews() {
if needLayout {
reloadData()
}
super.layoutSubviews()
}
func register(nib: UINib, with identifier: String) {
nibs[identifier] = nib
}
func register(cell: AnyClass, with identifier: String) {
cells[identifier] = cell
}
func dequeue(with identifier: String) -> FFPageContentViewCell {
if let nib = nibs[identifier] {
return nib.instantiate(withOwner: self, options: nil).first as! FFPageContentViewCell
}
if let cell = cells[identifier], cell is FFPageContentViewCell.Type {
return (cell as! FFPageContentViewCell.Type).init()
}
fatalError("FFPageContentViewCell and identifier unmatch")
}
func reloadData() {
subviews.forEach { $0.removeFromSuperview() }
NSLayoutConstraint.deactivate(ffConstraints)
contentSize = CGSize(width: 0, height: 0)
ffConstraints.removeAll()
guard let dataSource = dataSource else { return }
contentSize = CGSize(width: frame.width * CGFloat(dataSource.numberOfSections(in: self)), height: frame.height)
var last: FFPageContentViewCell?
for i in 0..<dataSource.numberOfSections(in: self) {
var cell = dataSource.pageContentView(pageContentView: self, cellForItemAt: i)
cell.index = i
cell.translatesAutoresizingMaskIntoConstraints = false
addSubview(cell)
var subConstriants = [NSLayoutConstraint(item: cell,
attribute: .top,
relatedBy: .equal,
toItem: self,
attribute: .top,
multiplier: 1,
constant: 0),
NSLayoutConstraint(item: cell,
attribute: .height,
relatedBy: .equal,
toItem: self,
attribute: .height,
multiplier: 1,
constant: 0),
NSLayoutConstraint(item: cell,
attribute: .width,
relatedBy: .equal,
toItem: self,
attribute: .width,
multiplier: 1,
constant: 0)]
var leadConstriant: NSLayoutConstraint
if last == nil {
leadConstriant = NSLayoutConstraint(item: cell,
attribute: .leading,
relatedBy: .equal,
toItem: self,
attribute: .leading,
multiplier: 1,
constant: 0)
} else {
leadConstriant = NSLayoutConstraint(item: cell,
attribute: .left,
relatedBy: .equal,
toItem: last,
attribute: .right,
multiplier: 1,
constant: 0)
}
subConstriants.append(leadConstriant)
ffConstraints += subConstriants
last = cell
}
NSLayoutConstraint.activate(ffConstraints)
needLayout = false
}
open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
if let point = change?[NSKeyValueChangeKey.newKey] as? CGPoint, (isTracking || isDragging || isDecelerating) {
pageDelegate?.pageContentView(pageContentView: self, didSelectItemAt: Int(point.x / frame.width))
}
}
deinit {
removeObserver(self, forKeyPath: "contentOffset")
}
}
|