iOS-Swift分类视图

//
//  PDLinkageView.swift
//  ShenKang
//
//  Created by 裴铎 on 2019/4/29.
//  Copyright © 2019 apple. All rights reserved.
//

import UIKit
import RxSwift
import RxCocoa

class PDLinkageView: UIView {

    ///标题s数组
    var titles : [String] = [String]()
    /** 存放子控制器对象的数组,内部的元素个数必须和标题数组内的一致 */
    var allViewControllers : [UIViewController] = [UIViewController]()
    ///上一次被点击的按钮
    fileprivate var previousClickButton = UIButton()
    ///默认选中的按钮d下标
    fileprivate var defaultButtonIndex : Int = 0
    ///空间标识符
    fileprivate let identifierTag = 2019429 //2019/4/29.
    ///垃圾袋
    fileprivate lazy var bag = DisposeBag()
    ///下划线的默认宽度
    fileprivate let titleUnderlineWidth : CGFloat = 30
    ///标题视图
    lazy var titlesView : UIView = {
        let titlesView = UIView(frame: CGRect(x: 0, y: 0, width: self.pd_width, height: 44))
        titlesView.backgroundColor = .white
        /** 获取应该添加的按钮个数 */
        let buttonCount : CGFloat = CGFloat(self.titles.count);
        /** 循环添加按钮 */
        for (index, title) in self.titles.enumerated() {
            let button = UIButton(type: .custom)
            let buttonWidth = titlesView.pd_width / buttonCount
            button.frame = CGRect(x: CGFloat(index) * buttonWidth, y: 0, width: buttonWidth, height: titlesView.pd_height)
            button.setTitle(title, for: .normal)
            button.setTitleColor(UIColor.black, for: .normal)
            button.setTitleColor(UIColor.blue, for: .selected)
            button.tag = index + self.identifierTag
            button.rx.tap.subscribe(onNext: {[weak self] (_) in
                self?.titleButtonClick(button: button)
            }).disposed(by: self.bag)
            titlesView.addSubview(button)
        }
        return titlesView
    }()
    ///下划线
    lazy var titleUnderline : UIView = {
        let titleUnderline = UIView()
        /** 拿到标题视图上的某一个按钮, 用来获取按钮上的状态信息 */
        guard let button = self.titlesView.subviews.first as? UIButton else {
            return titleUnderline
        }
        titleUnderline.backgroundColor = button.titleColor(for: .selected)
        titleUnderline.pd_height = 2
        titleUnderline.pd_width = button.titleLabel?.pd_width ?? self.titleUnderlineWidth
        titleUnderline.pd_y = button.pd_height - 2
        titleUnderline.pd_centerX = self.titlesView.subviews[self.defaultButtonIndex].pd_centerX
        return titleUnderline
    }()
    ///主体滚动视图
    lazy var mainScrollView : UIScrollView = {
        let mainScrollView = UIScrollView(frame: CGRect(x: 0, y: self.titlesView.pd_bottom, width: self.pd_width, height: self.pd_height - self.titlesView.pd_height))
        mainScrollView.backgroundColor = UIColor.gray
        mainScrollView.contentSize = CGSize(width: self.pd_width * CGFloat(self.titles.count), height: self.pd_height - self.titlesView.pd_height)
        mainScrollView.isPagingEnabled = true
        mainScrollView.delegate = self
        mainScrollView.scrollsToTop = false
        mainScrollView.showsVerticalScrollIndicator = false
        mainScrollView.showsHorizontalScrollIndicator = false
        mainScrollView.contentOffset = CGPoint(x: self.pd_width * CGFloat(self.defaultButtonIndex), y: 0)
        return mainScrollView
    }()
    
    
}
// MARK:- 自定义构造器
extension PDLinkageView {
    
    /// 自定义构造器
    ///
    /// - Parameters:
    ///   - frame: 尺寸位置
    ///   - titles: 标题按钮显示文字数组
    ///   - allViewControllers: 所有的子控制器(和标题数组的元素个数要相同)
    ///   - defaultButtonIndex: 默认选中的按钮下标 默认:0
    convenience init(frame: CGRect, titles : [String], allViewControllers :  [UIViewController], _ defaultButtonIndex : Int = 0) {
        self.init(frame: frame)
        self.titles = titles
        self.allViewControllers = allViewControllers
        self.defaultButtonIndex = defaultButtonIndex
        guard titles.count > 0 else {
            fatalError("titles不能为空")
        }
        guard titles.count == allViewControllers.count else {
            fatalError("标题按钮和s实际的子控制器个数不相同")
        }
        guard defaultButtonIndex < titles.count else {
            fatalError("默认选中的按钮下标越界")
        }
        self.setUI()
    }
}
// MARK:- UI
extension PDLinkageView {
    fileprivate func setUI() {
        self.addSubview(titlesView)
        self.addSubview(titleUnderline)
        self.addSubview(mainScrollView)
        let button = titlesView.subviews[defaultButtonIndex] as! UIButton
        titleButtonClick(button: button)
    }
    ///加载子控制器视图
    fileprivate func setupChildViewController(index : Int){
        guard allViewControllers.count > 0 else {
            return;/** 没有子控制器时不要执行下面的代码 */
        }
        /** 获取到索引对应的子控制器 */
        let childVC = allViewControllers[index]
        
        /** 判断控制器是否被加载过 */
        guard childVC.isViewLoaded == false else {
            return
        }
        /** 获取子控制器的视图 */
        guard let childView = childVC.view else {
            return
        }
        
        /** 判断视图是否被加载过,判断childView是否有父控件,如果有说明被加载过 */
        guard childView.superview == nil else {
            return
        }
        guard childView.window == nil else {
            return
        }
        /** 设置视图的frame */
        childView.frame = mainScrollView.bounds;
        /** 加载到滚动视图上 */
        mainScrollView.addSubview(childView)
        
    }
}
// MARK:- 事件
extension PDLinkageView {
    func titleButtonClick(button : UIButton) {
        /** 取消上一次点击的按钮选中状态 */
        previousClickButton.isSelected = false
        button.isSelected = true
        previousClickButton = button
        let index = button.tag - self.identifierTag
        UIView.animate(withDuration: 0.25, animations: {
            self.titleUnderline.pd_width = button.titleLabel?.pd_width ?? self.titleUnderlineWidth
            self.titleUnderline.pd_centerX = button.pd_centerX
            let offsetX = self.mainScrollView.pd_width * CGFloat(index)
            self.mainScrollView.contentOffset = CGPoint(x: offsetX, y: self.mainScrollView.contentOffset.y)
        }) { (finish) in
            self.setupChildViewController(index: index)
        }
    }
}
// MARK:- 滚动视图代理协议
extension PDLinkageView : UIScrollViewDelegate {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        /** 求出应该点击的按钮的索引 */
        let index = scrollView.contentOffset.x / scrollView.pd_width;
        let button = titlesView.subviews[Int(index)] as! UIButton
        titleButtonClick(button: button)
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容