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

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: Stringlet creator: Stringlet image: UIImage?//重写init方法init(title: String, creator: String, image:UIImage?) {self.title = titleself.creator = creatorself.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的可选
@objc
protocol 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.imagetitleLabel.text = animal.titlecreatorLabel.text = animal.creatordelegate?.collapseSidePanels?() //折叠侧容器}
}
复制代码

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

//枚举  滑动状态
enum SlideOutState {case bothCollapsed  //侧容器折叠case leftPanelExpanded   //左容器展开case rightPanelExpanded  //右容器展开
}//定义属性
var centerNavigationController: UINavigationController!
var centerViewController: DWCenterViewController!
//当前状态
var currentState: SlideOutState = .bothCollapsed {didSet { //在属性值改变后触发didSetlet 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}
}//左边的VC
func 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 = centerViewControllerview.insertSubview(sidePanelController.view, at: 0)addChildViewController(sidePanelController)sidePanelController.didMove(toParentViewController: self)
}//右边的VC
func addRightPanelViewController() {}func animateLeftPanel(shouldExpand: Bool) {if shouldExpand {currentState = .leftPanelExpandedanimateCenterPanelXPosition(targetPosition: centerNavigationController.view.frame.width - centerPanelExpandedOffset)} else {animateCenterPanelXPosition(targetPosition: 0, completion: { (_) inself.currentState = .bothCollapsedself.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 recognizer
extension 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).xrecognize.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.widthanimateLeftPanel(shouldExpand: hasMovedGreaterThanHalfway)}default:break}}
}
复制代码

代码传送门 注意:

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

Swift封装 滑出式导航栏相关推荐

  1. 如何用 Swift 编写滑出式导航面板

    原文:How to Create Your Own Slide-Out Navigation Panel in Swift 作者:Nicholas Sakaimbo 译者:kmyhy 更新说明:本教程 ...

  2. 微信小程序——沉浸式导航栏实现(含iphoneX适配和组件封装)

    文章目录 前言 正文 JSON navBar.js navBar.wxml navBar.wxss test1.wxml 展示效果 总结 前言 微信小程序中导航栏一般来说是默认的展示标题等等,可以做的 ...

  3. Android开发笔记(一百零一)滑出式菜单

    可移动页面MoveActivity 滑出式菜单从界面上看,像极了一个水平滚动视图HorizontalScrollView,当然也可以使用HorizontalScrollView来实现侧滑菜单.不过今天 ...

  4. Android肝帝战纪之基于上篇单Activity+多Fragment框架,开发电商式导航栏,多Fragment切换

    电商式导航栏,多Fragment切换 本文默认在已经搭建好的框架上进行开发 点此链接到上一篇基础框架的搭建 界面构思示意图 设计思路 在底部的LinearLayout中添加相应的图标,然后设置tag绑 ...

  5. android 4.4 以上沉浸式状态栏和沉浸式导航栏管理,一句代码轻松实现

    ImmersionBar 项目地址:gyf-dev/ImmersionBar  简介:android 4.4 以上沉浸式状态栏和沉浸式导航栏管理,一句代码轻松实现,以及对 bar 的其他设置,详见 R ...

  6. android沉浸式导航栏与键盘的冲突

    最近项目搞了沉浸式导航栏,但是与软键盘弹出冲突,布局不往上面顶,折腾几番之后,网上找到个方法但是不兼容华为 部分机型,于是做了修改,测试机型有限,我手头的机型是没有问题了,于是分享出来,直接用就行了. ...

  7. html响应式导航栏制作,用Sass制作响应式导航栏(原创)

    插件描述:用Sass制作响应式导航栏 更新时间:2017/12/29 下午8:33:04 更新说明:细节优化data-stop='true' : 在手机版上禁止跳转页面// 插入js代码 $(docu ...

  8. 仿人人客户端向右滑出式菜单

    人人客户端向右滑出式菜单: 试着实现了一个,先上效果图: 下面简单说明一下实现原理: 有两个activity,MainActivity和SettingActivity,实现这个效果两个步骤: 1.点击 ...

  9. uniapp设置导航栏、沉浸式导航栏以及获取屏幕尺寸

    页面上往往会有一些需要随着屏幕的大小变化而变化的样式,这时,我们就需要获取到屏幕的宽度和高度. 当然,一个H5页面或者微信小程序页面的导航栏会有多种形态,可以带有导航栏,也可以设置为沉浸式导航栏(即导 ...

最新文章

  1. 使用Tensorflow操作MNIST数据
  2. java学习面向对象之内部类
  3. 一步快速将Smartform output转成生成PDF文件
  4. 通过Athens搭建go私服
  5. Python中的条件选择和循环语句
  6. C#多线程开发-使用并发集合
  7. Data Poisoning Attacks to Deep Learning Based Recommender Systems论文解读
  8. 一文理解设计模式之--观察者模式(Observer)
  9. 速达软件开发版使用技巧-每页固定行样式报表设计
  10. 一场游戏平台商与游戏大厂的战争
  11. java金字塔显示_java控制台输出数字金字塔示例分享
  12. try catch finally return
  13. SQL Server-【知识与实战VII】存储过程(上)
  14. multism中ui和uo应该怎么表示_第310 这四个常考英语单词,到底表示时间还是地点?...
  15. Java8流List转Map
  16. jquery中的ajax写法
  17. 电机控制-H 桥电路 控制方式简单解析
  18. 手把手教你安装Xposed框架+JustTrustMe抓取手机APP数据
  19. UWB定位系统在工厂中的重要作用
  20. 【Matlab】线性回归之最小二乘法的应用与验证

热门文章

  1. matlab pca和逆pca函数,matlab_PCA,训练集与测试集分开,原理和用法
  2. leetcode15 三数之和
  3. PaperNotes(10)-Maximum Entropy Generators for Energy-Based Models
  4. Python模块(1)-Argparse 简易使用教程
  5. fastText初探
  6. Dapp简单的投票小例子
  7. 线程安全和对应的核心概念
  8. Android Studio 安装ASM插件
  9. v4l打开video设备 ,执行VIDIOC_DQBUF,出现Resource temporarily unavailable 问题
  10. Linphone编译【转载】