標(biāo)題控件
//
// PageTitleView.swift
// 標(biāo)題頭滑動
//
// Created by Zhangguodong on 17/3/27.
// Copyright ? 2017年 ZGD. All rights reserved.
//
import UIKit
protocol PageTitleViewDelegate {
func pageTitleView(pageTitleView:PageTitleView,selectedIndex index: Int) -> Void
}
// MARK:- 定義常量
private let kScrollLineH : CGFloat = 2
private let kNormalColor : (R:CGFloat, G:CGFloat, B:CGFloat) = (85, 85, 85)
private let kSelectColor : (R:CGFloat, G:CGFloat, B:CGFloat) = (255, 128, 0)
class PageTitleView: UIView {
fileprivate var titles:[String]?
init(frame: CGRect,titles:[String]) {
super.init(frame: frame)
backgroundColor = UIColor.orange
self.titles = titles
addChildView()
}
var delegate: PageTitleViewDelegate?
fileprivate lazy var lables : [UILabel] = [UILabel]()
var index: NSInteger = 0
fileprivate lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView(frame: self.bounds)
scrollView.backgroundColor = UIColor.white
scrollView.showsVerticalScrollIndicator = false
return scrollView
}()
lazy var indicateLabel: UILabel = {
let indicateLabel = UILabel()
indicateLabel.backgroundColor = UIColor.randomColor()
return indicateLabel
}()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension PageTitleView {
func addChildView() -> Void {
addSubview(scrollView)
addLables()
}
//MARK: 添加label和指示控件
func addLables() -> Void {
let labelW = scrollView.frame.size.width / 4.0
let labelH = scrollView.frame.size.height - kScrollLineH
for (index,name) in (titles?.enumerated())! {
let label = UILabel(frame: CGRect(x: labelW * CGFloat(index), y: 0, width: labelW, height: labelH))
label.text = name
label.tag = index
label.isUserInteractionEnabled = true
label.textAlignment = .center
label.backgroundColor = UIColor.white
label.textColor = UIColor(r: kNormalColor.R, g: kNormalColor.G, b: kNormalColor.B)
if index == 0 {
label.textColor = UIColor(r: kSelectColor.R, g: kSelectColor.G, b: kSelectColor.B)
}
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapAction(tap:)))
label.addGestureRecognizer(tapGesture)
self.lables.append(label)
scrollView.addSubview(label)
}
indicateLabel.frame = CGRect(x: 0, y: scrollView.frame.size.height - kScrollLineH, width: labelW, height: kScrollLineH)
scrollView.addSubview(indicateLabel)
}
func tapAction(tap: UITapGestureRecognizer) -> Void {
let currentlabel = tap.view as! UILabel
let currentIndex = currentlabel.tag
if currentIndex == index {
return
}else {
delegate?.pageTitleView(pageTitleView: self, selectedIndex: currentIndex)
currentlabel.textColor = UIColor(r: kSelectColor.R, g: kSelectColor.G, b: kSelectColor.B)
let lastLabel = self.lables[index]
lastLabel.textColor = UIColor(r: kNormalColor.R, g: kNormalColor.G, b: kNormalColor.B)
UIView.animate(withDuration: 0.5, animations: {
self.indicateLabel.frame.origin.x = self.frame.size.width / 4.0 * CGFloat(currentIndex)
})
}
index = currentIndex
}
}
//MARK: 暴露的方法
extension PageTitleView {
func setTitleWithProgress(progress:CGFloat,sourceIndex:Int,targetIndex:Int) -> Void {
//1.取出sourceLabel/targetLabel
let sourceLabel = lables[sourceIndex]
let targetLabel = lables[targetIndex]
// 2.處理滑塊的邏輯
let moveTotalX = targetLabel.frame.origin.x - sourceLabel.frame.origin.x
let moveX = moveTotalX * progress
indicateLabel.frame.origin.x = moveX + sourceLabel.frame.origin.x
//3.顏色漸變
let colorDelta = (kSelectColor.R - kNormalColor.R,kSelectColor.G - kNormalColor.G,kSelectColor.B - kNormalColor.B)
sourceLabel.textColor = UIColor(r: kSelectColor.R - colorDelta.0 * progress, g: kSelectColor.G - colorDelta.1 * progress, b: kSelectColor.B - colorDelta.2 * progress)
targetLabel.textColor = UIColor(r: kNormalColor.0 + colorDelta.0 * progress, g: kNormalColor.1 + colorDelta.1 * progress, b: kNormalColor.2 + colorDelta.2 * progress)
//4.更新下標(biāo)
index = targetIndex
}
}
內(nèi)容控件
//
// PageContentView.swift
// 標(biāo)題頭滑動
//
// Created by Zhangguodong on 17/3/27.
// Copyright ? 2017年 ZGD. All rights reserved.
//
import UIKit
protocol PageContentViewDelegate {
func pageContentView(pageContentView:PageContentView,progress:CGFloat,sourceIndex:Int,targetIndex:Int) -> Void
}
class PageContentView: UIView {
var childVCs:[UIViewController]?
var delegate: PageContentViewDelegate?
//點擊的時候禁止走代理方法(scrollViewDidScroll)
var forbidDelegate = false
init(frame: CGRect,childVCs:[UIViewController]) {
super.init(frame: frame)
backgroundColor = UIColor.randomColor()
self.childVCs = childVCs
addSubview(collectionview)
}
fileprivate var startOffsetX : CGFloat = 0
lazy var collectionview: UICollectionView = {
let layout = FlowLayout()
let collectionview = UICollectionView(frame: self.bounds, collectionViewLayout: layout)
collectionview.dataSource = self
collectionview.delegate = self
collectionview.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
return collectionview
}()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension PageContentView:UICollectionViewDelegate,UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (self.childVCs?.count)!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
let vc = self.childVCs?[indexPath.item]
cell.contentView.addSubview((vc?.view)!)
return cell
}
}
//MARK: 判斷左右
extension PageContentView {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
forbidDelegate = false
startOffsetX = scrollView.contentOffset.x
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if forbidDelegate {
return
}
let currentOffsetX = scrollView.contentOffset.x
var progress: CGFloat = 0
var sourceIndex:Int = 0
var targetIndex:Int = 0
let scrollViewW = CGFloat(frame.size.width)
if startOffsetX > currentOffsetX { //右 小
// 1.計算progress
progress = 1 - (currentOffsetX / scrollViewW - floor(currentOffsetX / scrollViewW))
// 2.計算targetIndex
targetIndex = Int(currentOffsetX / scrollViewW)
// 3.計算sourceIndex
sourceIndex = targetIndex + 1
if sourceIndex >= (childVCs?.count)! {
sourceIndex = (childVCs?.count)! - 1
}
}else {//左大
// 1.計算progress
progress = currentOffsetX / scrollViewW - floor(currentOffsetX / scrollViewW)
// 2.計算sourceIndex
sourceIndex = Int(currentOffsetX / scrollViewW)
// 3.計算targetIndex
targetIndex = sourceIndex + 1
if targetIndex >= (childVCs?.count)! {
targetIndex = (childVCs?.count)! - 1
}
// 4.如果完全劃過去
if currentOffsetX - startOffsetX == scrollViewW {
progress = 1
targetIndex = sourceIndex
}
}
delegate?.pageContentView(pageContentView: self, progress: progress, sourceIndex: sourceIndex, targetIndex: targetIndex)
// print(" progress = \(progress) 開始 \(sourceIndex) 目標(biāo)\(targetIndex)")
}
}
//MARK: 對外暴露的方法
extension PageContentView {
func setCurrentIndex(currentIndex:NSInteger) -> Void {
let indetPath = IndexPath(item: currentIndex, section: 0)
forbidDelegate = true
collectionview.selectItem(at: indetPath, animated: false, scrollPosition: .centeredHorizontally)
}
}