Swift封装 滑出式导航栏
前言: 本文將會創(chuàng)建以下幾個主類:
DWContainerViewController:這包含了左視圖,中視圖和右視圖控制器的視圖,并處理動畫和滑動等操作。 DWCenterViewController:中央面板。 DWSidePanelViewController:用于左側(cè)和右側(cè)面板。
創(chuàng)建storyboard,如圖:
并且創(chuàng)建DWCenterViewController、DWStarCell、DWSidePanelViewController,關(guān)聯(lián)上圖中的storyboard
DWCenterViewController為滑出式導(dǎo)航的類,代碼:
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) {//左邊點擊事件 } } 復(fù)制代碼DWStarCell代碼:
class DWStarCell: UITableViewCell {@IBOutlet weak var animalImageView: UIView!@IBOutlet weak var imageNameLabel: UILabel!@IBOutlet weak var imageCreatorLabel: UILabel!} 復(fù)制代碼創(chuàng)建DWStar.swift模型,并且初始化cell顯示的數(shù)據(jù),代碼如下:
//結(jié)構(gòu)體 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: "周潤發(fā)", 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"))]}復(fù)制代碼創(chuàng)建DWCenterViewControllerDelegate,并且創(chuàng)建協(xié)議方法:
//創(chuàng)建協(xié)議 optional:類似oc的可選 @objc protocol DWCenterViewControllerDelegate {@objc optional func toggleLeftPanel() //切換左邊的容器@objc optional func collapseSidePanels() //折疊側(cè)邊的容器 } 復(fù)制代碼在DWCenterViewController.swift的actorsTapped點擊方法調(diào)用協(xié)議方法toggleLeftPanel,如下:
@IBAction func actorsTapped(_ sender: Any) {//左邊點擊事件delegate?.toggleLeftPanel?() } 復(fù)制代碼創(chuàng)建DWSidePanelViewControllerDelegate.swift,并創(chuàng)一個協(xié)議
protocol DWSidePanelViewControllerDelegate {func didSelectAnimal(_ animal: DWStar) //選擇的動物 } 復(fù)制代碼在DWCenterViewController.swift實現(xiàn)DWSidePanelViewControllerDelegate的協(xié)議方法:
// MARK: - DWCenterViewController delegate //在該類實現(xiàn)delegate的方法 extension DWCenterViewController: DWSidePanelViewControllerDelegate {func didSelectAnimal(_ animal: DWStar) { //實現(xiàn)協(xié)議方法imageView.image = animal.imagetitleLabel.text = animal.titlecreatorLabel.text = animal.creatordelegate?.collapseSidePanels?() //折疊側(cè)容器} } 復(fù)制代碼創(chuàng)建DWContainerViewController.swift,并定義一些屬性:
//枚舉 滑動狀態(tài) enum SlideOutState {case bothCollapsed //側(cè)容器折疊case leftPanelExpanded //左容器展開case rightPanelExpanded //右容器展開 }//定義屬性 var centerNavigationController: UINavigationController! var centerViewController: DWCenterViewController! //當(dāng)前狀態(tài) var currentState: SlideOutState = .bothCollapsed {didSet { //在屬性值改變后觸發(fā)didSetlet shoulShowShadow = currentState != .bothCollapsed} }var leftViewController: DWSidePanelViewController? var centerPanelExpandedOffset: CGFloat = 60 //該值是中央視圖控制器在屏幕外動畫顯示后左側(cè)可見的寬度(以點為單位) 復(fù)制代碼擴(kuò)展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} } 復(fù)制代碼在viewDidLoad添加如下:
//添加中間控制器并顯示 centerViewController = UIStoryboard.centerViewController() centerViewController.delegate = self//將centerViewController包裝在導(dǎo)航控制器中 centerNavigationController = UINavigationController(rootViewController: centerViewController) //加入centerViewcontroller的視圖 view.addSubview(centerNavigationController.view) //加入centerViewcontroller的視圖控制器 addChildViewController(centerNavigationController) centerNavigationController.didMove(toParentViewController: self) 復(fù)制代碼實現(xiàn)協(xié)議方法(添加左側(cè)容器一起動畫的發(fā)生代碼):
extension DWContainerViewController: DWCenterViewControllerDelegate { } 復(fù)制代碼在協(xié)議方法中,添加
func toggleLeftPanel() {//如果當(dāng)前狀態(tài):左邊為展開let notAlreadyExpanded = (currentState != .leftPanelExpanded)if notAlreadyExpanded {addLeftPanelViewController() //添加左邊容器}//左邊容器展開的動畫animateLeftPanel(shouldExpand: notAlreadyExpanded) }//折疊側(cè)邊容器 func collapseSidePanels() {switch currentState {case .leftPanelExpanded:toggleLeftPanel()default:break} }//左邊的VC func addLeftPanelViewController() {//guard語句判斷其后的表達(dá)式布爾值為false時,才會執(zhí)行之后代碼塊里的代碼,如果為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})} }//檢查是否被告知展開或折疊側(cè)面板。如果它應(yīng)該展開,那么它將設(shè)置當(dāng)前狀態(tài)以指示左側(cè)面板展開,然后為中央面板設(shè)置動畫,以便打開。否則,它將關(guān)閉中央面板,然后移除其視圖,并設(shè)置當(dāng)前狀態(tài)以指示其關(guān)閉。 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} }} 復(fù)制代碼添加手勢,更改DWCenterViewController的導(dǎo)航欄x坐標(biāo)
// 手勢 // 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:方法設(shè)置手勢的偏移量}case .ended: //根據(jù)不同的方向移動左或右if let _ = leftViewController,let rview = recognize.view {let hasMovedGreaterThanHalfway = rview.center.x > view.bounds.size.widthanimateLeftPanel(shouldExpand: hasMovedGreaterThanHalfway)}default:break}} } 復(fù)制代碼代碼傳送門 注意:
1、自己添加tableView,需要手動添加dataSource 和 delegate 2、調(diào)節(jié)tableView的row height
總結(jié)
以上是生活随笔為你收集整理的Swift封装 滑出式导航栏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jfinal连接mysql数据库_JFi
- 下一篇: mysql innodb启动失败_mys