博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Swift封装 滑出式导航栏
阅读量:6717 次
发布时间:2019-06-25

本文共 8580 字,大约阅读时间需要 28 分钟。

前言: 本文将会创建以下几个主类:

DWContainerViewController:这包含了左视图,中视图和右视图控制器的视图,并处理动画和滑动等操作。 DWCenterViewController:中央面板。 DWSidePanelViewController:用于左侧和右侧面板。

创建storyboard,如图:

并且创建DWCenterViewControllerDWStarCellDWSidePanelViewController,关联上图中的storyboard

DWCenterViewController为滑出式导航的类,代码:

class DWCenterViewController: UIViewController {    var delegate: DWCenterViewControllerDelegate?        @IBOutlet weak var imageView: UIImageView!    @IBOutlet weak var titleLabel: UILabel!    @IBOutlet weak var creatorLabel: UILabel!        @IBAction func actorsTapped(_ sender: Any) {        //左边点击事件       }}复制代码

DWStarCell代码:

class DWStarCell: UITableViewCell {        @IBOutlet weak var animalImageView: UIView!    @IBOutlet weak var imageNameLabel: UILabel!    @IBOutlet weak var imageCreatorLabel: UILabel!}复制代码

创建DWStar.swift模型,并且初始化cell显示的数据,代码如下:

//结构体struct DWStar {    let title: String    let creator: String    let image: UIImage?   //重写init方法    init(title: String, creator: String, image:UIImage?) {        self.title = title        self.creator = creator        self.image = image    }        static func allActors() -> [DWStar] {        return [            DWStar(title: "林志玲", creator: "Dwyane", image: UIImage(named: "ID-100113060")),            DWStar(title: "张歆艺", creator: "Dwyane", image: UIImage(named: "ID-10022760")),            DWStar(title: "李连杰", creator: "Dwyane", image: UIImage(named: "ID-10091065")),            DWStar(title: "周润发", creator: "Dwyane", image: UIImage(named: "ID-10047796")),            DWStar(title: "舒淇", creator: "Dwyane", image: UIImage(named: "ID-10092572")),            DWStar(title: "鹿晗", creator: "Dwyane", image: UIImage(named: "ID-10041194")),            DWStar(title: "黄晓明", creator: "Dwyane", image: UIImage(named: "ID-10017782")),            DWStar(title: "李赛凤", creator: "Dwyane", image: UIImage(named: "ID-10091745")),            DWStar(title: "赵丽颖", creator: "Dwyane Ratcliff", image: UIImage(named: "ID-10056941")),            DWStar(title: "周星驰", creator: "Dwyane", image: UIImage(named: "ID-10019208")),            DWStar(title: "杜海涛", creator: "Dwyane", image: UIImage(named: "ID-10011404"))        ]    }   复制代码

创建DWCenterViewControllerDelegate,并且创建协议方法:

//创建协议 optional:类似oc的可选@objcprotocol DWCenterViewControllerDelegate {    @objc optional func toggleLeftPanel()  //切换左边的容器    @objc optional func collapseSidePanels() //折叠侧边的容器}复制代码

DWCenterViewController.swiftactorsTapped点击方法调用协议方法toggleLeftPanel,如下:

@IBAction func actorsTapped(_ sender: Any) {    //左边点击事件    delegate?.toggleLeftPanel?()}复制代码

创建DWSidePanelViewControllerDelegate.swift,并创一个协议

protocol DWSidePanelViewControllerDelegate {    func didSelectAnimal(_ animal: DWStar)  //选择的动物}复制代码

DWCenterViewController.swift实现DWSidePanelViewControllerDelegate的协议方法:

// MARK: - DWCenterViewController delegate//在该类实现delegate的方法extension DWCenterViewController: DWSidePanelViewControllerDelegate {    func didSelectAnimal(_ animal: DWStar) { //实现协议方法        imageView.image = animal.image        titleLabel.text = animal.title        creatorLabel.text = animal.creator                delegate?.collapseSidePanels?() //折叠侧容器    }  }复制代码

创建DWContainerViewController.swift,并定义一些属性:

//枚举  滑动状态enum SlideOutState {    case bothCollapsed  //侧容器折叠    case leftPanelExpanded   //左容器展开    case rightPanelExpanded  //右容器展开}//定义属性var centerNavigationController: UINavigationController!var centerViewController: DWCenterViewController!//当前状态var currentState: SlideOutState = .bothCollapsed {    didSet { //在属性值改变后触发didSet        let shoulShowShadow = currentState != .bothCollapsed    }}var leftViewController: DWSidePanelViewController?var centerPanelExpandedOffset: CGFloat = 60 //该值是中央视图控制器在屏幕外动画显示后左侧可见的宽度(以点为单位)复制代码

扩展UIStoryboard,方便取得VC,代码如下:

private extension UIStoryboard {    static func mainStoryboard() -> UIStoryboard {        return UIStoryboard(name: "Main", bundle: Bundle.main)    }        static func centerViewController() -> DWCenterViewController? {        return mainStoryboard().instantiateViewController(withIdentifier: "DWCenterViewController") as? DWCenterViewController    }        static func leftViewController() -> DWSidePanelViewController? {        return mainStoryboard().instantiateViewController(withIdentifier: "LeftViewController") as? DWSidePanelViewController    }    }复制代码

viewDidLoad添加如下:

//添加中间控制器并显示centerViewController = UIStoryboard.centerViewController()centerViewController.delegate = self//将centerViewController包装在导航控制器中centerNavigationController = UINavigationController(rootViewController: centerViewController)//加入centerViewcontroller的视图view.addSubview(centerNavigationController.view)//加入centerViewcontroller的视图控制器addChildViewController(centerNavigationController)centerNavigationController.didMove(toParentViewController: self)复制代码

实现协议方法(添加左侧容器一起动画的发生代码):

extension DWContainerViewController: DWCenterViewControllerDelegate { }复制代码

在协议方法中,添加

func toggleLeftPanel() {    //如果当前状态:左边为展开    let notAlreadyExpanded = (currentState != .leftPanelExpanded)        if notAlreadyExpanded {        addLeftPanelViewController() //添加左边容器    }    //左边容器展开的动画    animateLeftPanel(shouldExpand: notAlreadyExpanded)}//折叠侧边容器func collapseSidePanels() {    switch currentState {    case .leftPanelExpanded:        toggleLeftPanel()    default:        break    }}//左边的VCfunc addLeftPanelViewController() {//guard语句判断其后的表达式布尔值为false时,才会执行之后代码块里的代码,如果为true,则跳过整个guard语句    guard leftViewController == nil else { return }        if let vc = UIStoryboard.leftViewController() {        vc.animals = DWStar.allActors()        addChildSidePanelController(vc)        leftViewController = vc    }}func addChildSidePanelController(_ sidePanelController: DWSidePanelViewController) {    sidePanelController.delegate = centerViewController    view.insertSubview(sidePanelController.view, at: 0)        addChildViewController(sidePanelController)    sidePanelController.didMove(toParentViewController: self)}//右边的VCfunc addRightPanelViewController() {    }func animateLeftPanel(shouldExpand: Bool) {    if shouldExpand {        currentState = .leftPanelExpanded        animateCenterPanelXPosition(targetPosition: centerNavigationController.view.frame.width - centerPanelExpandedOffset)    } else {        animateCenterPanelXPosition(targetPosition: 0, completion: { (_) in            self.currentState = .bothCollapsed            self.leftViewController?.view.removeFromSuperview()            self.leftViewController = nil        })    }}//检查是否被告知展开或折叠侧面板。如果它应该展开,那么它将设置当前状态以指示左侧面板展开,然后为中央面板设置动画,以便打开。否则,它将关闭中央面板,然后移除其视图,并设置当前状态以指示其关闭。func animateCenterPanelXPosition(targetPosition: CGFloat, completion: ((Bool) -> Void)? = nil) {    UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: {        self.centerNavigationController.view.frame.origin.x = targetPosition    }, completion: completion)}func showShadowForCenterViewController(_ shouldShowShadow: Bool) {    if shouldShowShadow {        centerNavigationController.view.layer.shadowOpacity = 0.8    } else {        centerNavigationController.view.layer.shadowOpacity = 0.0    }}}复制代码

添加手势,更改DWCenterViewController的导航栏x坐标

// 手势// MARK: Gesture recognizerextension DWContainerViewController: UIGestureRecognizerDelegate {    @objc func handlePanGesture(_ recognize: UIPanGestureRecognizer) {        let gestureIsDraggingFromLeftToRight = (recognize.velocity(in: view).x > 0)                switch recognize.state {        case .began:            if currentState == .bothCollapsed {                if gestureIsDraggingFromLeftToRight {                    //左边                    addLeftPanelViewController()                } else {                    //右边                    addRightPanelViewController()                }                showShadowForCenterViewController(true)            }        case .changed:            if let rview = recognize.view {                rview.center.x = rview.center.x + recognize.translation(in: view).x                recognize.setTranslation(CGPoint.zero, in: view)                //translationInView:方法获取View的偏移量  setTranslation:方法设置手势的偏移量            }        case .ended: //根据不同的方向移动左或右            if let _ = leftViewController,                let rview = recognize.view {                let hasMovedGreaterThanHalfway = rview.center.x > view.bounds.size.width                animateLeftPanel(shouldExpand: hasMovedGreaterThanHalfway)            }                    default:            break        }            }}复制代码

注意:

1、自己添加tableView,需要手动添加dataSource 和 delegate 2、调节tableView的row height

转载地址:http://yjumo.baihongyu.com/

你可能感兴趣的文章
java删除文件夹
查看>>
delphi 学生管理系统总结
查看>>
HTML5
查看>>
SQL Server事务日志分析
查看>>
redis演练(9) redis Cluster 集群快速部署&failover情况
查看>>
通配符证书解决内部连接证书错提示问题
查看>>
触发器在oracle和mysql的不同写法细节
查看>>
Windows Server入门系列之七 制作系统工具优盘并安装系统
查看>>
rsync+inotify 文件同步系统
查看>>
四格漫画《MUXing》——龙年大吉
查看>>
SQL教学思路《图书管理系统》习题二:插入数据
查看>>
SAP R3 采购申请相关简单操作 :附Oracle后台数据库对应表明细。
查看>>
UGUI表情系统解决方案
查看>>
Provisioning Services 7.8 入门系列教程之四 目标设备安装
查看>>
求助:部分电脑无法使用VBScript.RegExp提供的功能
查看>>
pxe网络安装centos6
查看>>
microsoft office 2007 完全 卸载 工具 来自微软官方
查看>>
使用Extended Events收集错误信息
查看>>
前端开发中的MCRV模式
查看>>
Lync Server 2013音视频网络流量带宽优化
查看>>