├── Read This.doc ├── Navigation Drawer.mov ├── README.md ├── DrawerView.swift ├── DKNavDrawerDelegate.swift └── DrawerView.xib /Read This.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshan2509/DKNavigationDrawer/HEAD/Read This.doc -------------------------------------------------------------------------------- /Navigation Drawer.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshan2509/DKNavigationDrawer/HEAD/Navigation Drawer.mov -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DKNavigationDrawer 2 | Navigation Drawer for iOS using Swift. 3 | 4 | ![Screenshot](https://media.giphy.com/media/I45syjhreC0Rq/giphy.gif) 5 | 6 | 1. Add DKNavDrawerDelegate and DrawerView to project. 7 | 2. Assign class DKNavDrawer to your navigation controller 8 | 3. Add a Right Bar Button to your RootViewController connect it to a action. 9 | 4. RootViewController should conform to DKNavDrawerDelegate 10 | 5. Initialize - var rootNav: DKNavDrawer? 11 | 12 | 13 | In viewDidLoad() of RootViewController add 2 lines 14 | 15 | rootNav = (navigationController as? DKNavDrawer) 16 | rootNav?.dkNavDrawerDelegate = self 17 | 18 | The button action code 19 | 20 | @IBAction func btnToggle(_ sender: Any) { 21 | rootNav?.drawerToggle() 22 | } 23 | //Implement this as this is a delegate method 24 | func dkNavDrawerSelection(_ selectionIndex: Int) { 25 | } 26 | -------------------------------------------------------------------------------- /DrawerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DrawerView.swift 3 | // DKNavigationDrawer 4 | // 5 | // Created by Darshan on 5/17/17. 6 | // Copyright © 2017 Darshan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DrawerView: UIView { 12 | @IBOutlet weak var drawerTableView: UITableView! 13 | 14 | /* 15 | // Only override draw() if you perform custom drawing. 16 | // An empty implementation adversely affects performance during animation. 17 | override func draw(_ rect: CGRect) { 18 | // Drawing code 19 | } 20 | */ 21 | 22 | override init(frame: CGRect) { 23 | super.init(frame: frame) 24 | 25 | // Initialization code 26 | //_lblName.text=[[NSUserDefaults standardUserDefaults]objectForKey:@"userName"]; 27 | 28 | } 29 | 30 | required init?(coder aDecoder: NSCoder) { 31 | super.init(coder: aDecoder) } 32 | 33 | /* 34 | // Only override drawRect: if you perform custom drawing. 35 | // An empty implementation adversely affects performance during animation. 36 | 37 | 38 | */ 39 | override func draw(_ rect: CGRect) { 40 | //Drawing code 41 | 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /DKNavDrawerDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DKNavDrawerDelegate.swift 3 | // DKNavigationDrawer 4 | // 5 | // Created by Darshan on 5/17/17. 6 | // Copyright © 2017 Darshan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | protocol DKNavDrawerDelegate: NSObjectProtocol { 13 | //add methods as per requirements 14 | func dkNavDrawerSelection(_ selectionIndex: Int) 15 | 16 | 17 | 18 | } 19 | 20 | 21 | class DKNavDrawer: UINavigationController, UIGestureRecognizerDelegate, UITableViewDataSource, UITableViewDelegate { 22 | var pan_gr: UIPanGestureRecognizer? 23 | weak var dkNavDrawerDelegate: DKNavDrawerDelegate? 24 | 25 | var SHAWDOW_ALPHA:Float = 0.5 26 | var MENU_DURATION:Float = 0.3 27 | let MENU_TRIGGER_VELOCITY = 350 28 | var isOpen: Bool = false 29 | var meunHeight: Float = 0.0 30 | var menuWidth: Float = 0.0 31 | var outFrame = CGRect.zero 32 | var inFrame = CGRect.zero 33 | var shawdowView: UIView? 34 | var drawerView: DrawerView? 35 | 36 | private var menuItems = [Any]() 37 | private var menuImages = [Any]() 38 | 39 | // MARK: - VC lifecycle 40 | 41 | override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: Bundle!) { 42 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 43 | 44 | // Custom initialization 45 | 46 | } 47 | 48 | required init?(coder aDecoder: NSCoder) { 49 | super.init(coder: aDecoder) 50 | //fatalError("init(coder:) has not been implemented") 51 | } 52 | 53 | override func viewDidLoad() { 54 | super.viewDidLoad() 55 | // Do any additional setup after loading the view. 56 | menuItems = [" Profile", "Address", "Orders"] 57 | menuImages = ["avatar", "contacts", "shoppingcart"] 58 | setUpDrawer() 59 | } 60 | 61 | 62 | func setUpDrawer() { 63 | isOpen = false 64 | // load drawer view 65 | drawerView = Bundle.main.loadNibNamed("DrawerView", owner: self, options: nil)?[0] as? DrawerView 66 | let wind = UIWindow(frame: UIScreen.main.bounds) 67 | var width: Float = (Float(wind.frame.size.width)) 68 | width = width * 0.65 69 | // Adjust width here 70 | meunHeight = Float(wind.frame.size.height) 71 | menuWidth = width 72 | outFrame = CGRect(x: CGFloat(-menuWidth), y: CGFloat(0), width: CGFloat(menuWidth), height: CGFloat(meunHeight)) 73 | inFrame = CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(menuWidth), height: CGFloat(meunHeight)) 74 | print("inframe=\(meunHeight)") 75 | // drawer shawdow and assign its gesture 76 | shawdowView = UIView(frame: view.frame) 77 | shawdowView?.backgroundColor = UIColor(red: CGFloat(0.0), green: CGFloat(0.0), blue: CGFloat(0.0), alpha: CGFloat(0.0)) 78 | shawdowView?.isHidden = true 79 | let tapIt = UITapGestureRecognizer(target: self, action: #selector(self.taponShawdow)) 80 | shawdowView?.addGestureRecognizer(tapIt) 81 | shawdowView?.translatesAutoresizingMaskIntoConstraints = false 82 | view.addSubview(shawdowView!) 83 | // add drawer view 84 | drawerView?.frame = outFrame 85 | view.addSubview(drawerView!) 86 | // drawer list 87 | drawerView?.drawerTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0) 88 | // statuesBarHeight+navBarHeight 89 | drawerView?.drawerTableView.dataSource = self 90 | drawerView?.drawerTableView.delegate = self 91 | //seprator cleanup 92 | drawerView?.drawerTableView.tableFooterView = UIView(frame: CGRect.zero) 93 | // gesture on self.view 94 | pan_gr = UIPanGestureRecognizer(target: self, action: #selector(self.moveDrawer)) 95 | pan_gr?.maximumNumberOfTouches = 1 96 | pan_gr?.minimumNumberOfTouches = 1 97 | //self.pan_gr.delegate = self; 98 | view.addGestureRecognizer(pan_gr!) 99 | view.bringSubview(toFront: navigationBar) 100 | // for (id x in self.view.subviews){ 101 | // NSLog(@"%@",NSStringFromClass([x class])); 102 | } 103 | override func didReceiveMemoryWarning() { 104 | super.didReceiveMemoryWarning() 105 | // Dispose of any resources that can be recreated. 106 | } 107 | 108 | // MARK: - push & pop 109 | override func pushViewController(_ viewController: UIViewController, animated: Bool) { 110 | super.pushViewController(viewController, animated: animated) 111 | // disable gesture in next vc 112 | pan_gr?.isEnabled = false 113 | } 114 | 115 | override func popViewController(animated: Bool) -> UIViewController { 116 | let vc: UIViewController? = super.popViewController(animated: animated) 117 | // enable gesture in root vc 118 | if viewControllers.count == 1 { 119 | pan_gr?.isEnabled = true 120 | } 121 | return vc! 122 | } 123 | 124 | // MARK: - drawer 125 | func drawerToggle() { 126 | if !isOpen { 127 | openNavigationDrawer() 128 | } 129 | else { 130 | closeNavigationDrawer() 131 | } 132 | } 133 | 134 | //open and close action 135 | func openNavigationDrawer() { 136 | // NSLog(@"open x=%f",self.menuView.center.x); 137 | 138 | let duration: Float = MENU_DURATION / menuWidth * fabs(Float(drawerView!.center.x)) + MENU_DURATION / 2 139 | // y=mx+c 140 | // shawdow 141 | shawdowView?.isHidden = false 142 | UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: .curveEaseInOut, animations: {() -> Void in 143 | self.shawdowView?.backgroundColor = UIColor(red: CGFloat(0.0), green: CGFloat(0.0), blue: CGFloat(0.0), alpha: CGFloat(self.SHAWDOW_ALPHA)) 144 | }, completion: { _ in }) 145 | // drawer 146 | UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: .beginFromCurrentState, animations: {() -> Void in 147 | self.drawerView?.frame = self.inFrame 148 | }, completion: { _ in }) 149 | isOpen = true 150 | } 151 | 152 | func closeNavigationDrawer() { 153 | // NSLog(@"close x=%f",self.menuView.center.x); 154 | let duration: Float = MENU_DURATION / menuWidth * fabs(Float(drawerView!.center.x)) + MENU_DURATION / 2 155 | // y=mx+c 156 | // shawdow 157 | UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: .curveEaseInOut, animations: {() -> Void in 158 | self.shawdowView?.backgroundColor = UIColor(red: CGFloat(0.0), green: CGFloat(0.0), blue: CGFloat(0.0), alpha: CGFloat(0.0)) 159 | }, completion: {(_ finished: Bool) -> Void in 160 | self.shawdowView?.isHidden = true 161 | }) 162 | // drawer 163 | UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: .beginFromCurrentState, animations: {() -> Void in 164 | self.drawerView?.frame = self.outFrame 165 | }, completion: { _ in }) 166 | isOpen = false 167 | } 168 | 169 | 170 | func taponShawdow(recognizer: UITapGestureRecognizer) { 171 | closeNavigationDrawer() 172 | } 173 | 174 | func moveDrawer(_ recognizer: UIPanGestureRecognizer) { 175 | let translation: CGPoint = recognizer.translation(in: view) 176 | let velocity: CGPoint? = (recognizer as UIPanGestureRecognizer).velocity(in: view) 177 | // NSLog(@"velocity x=%f",velocity.x); 178 | if (recognizer as UIPanGestureRecognizer).state == .began { 179 | // NSLog(@"start"); 180 | 181 | let x:Int = Int((velocity?.x)!) 182 | 183 | 184 | if x > MENU_TRIGGER_VELOCITY && !isOpen { 185 | openNavigationDrawer() 186 | } 187 | else if x < -MENU_TRIGGER_VELOCITY && isOpen { 188 | closeNavigationDrawer() 189 | } 190 | } 191 | if (recognizer as UIPanGestureRecognizer).state == .changed { 192 | // NSLog(@"changing"); 193 | let movingx: Float = Float(drawerView!.center.x + translation.x) 194 | print("menuWidth== \(menuWidth / 2)") 195 | if movingx > -menuWidth / 2 && movingx < menuWidth / 2 { 196 | drawerView?.center = CGPoint(x: CGFloat(movingx), y: CGFloat((drawerView?.center.y)!)) 197 | recognizer.setTranslation(CGPoint(x: CGFloat(0), y: CGFloat(0)), in: view) 198 | let changingAlpha: Float = SHAWDOW_ALPHA / menuWidth * movingx + SHAWDOW_ALPHA / 2 199 | // y=mx+c 200 | shawdowView?.isHidden = false 201 | shawdowView?.backgroundColor = UIColor(red: CGFloat(0.0), green: CGFloat(0.0), blue: CGFloat(0.0), alpha: CGFloat(changingAlpha)) 202 | } 203 | } 204 | if (recognizer as UIPanGestureRecognizer).state == .ended { 205 | // NSLog(@"end"); 206 | if Int((drawerView?.center.x)!) > 0 { 207 | openNavigationDrawer() 208 | } 209 | else if Int((drawerView?.center.x)!) < 0 { 210 | closeNavigationDrawer() 211 | } 212 | } 213 | } 214 | func numberOfSections(in tableView: UITableView) -> Int { 215 | // Return the number of sections. 216 | return 1 217 | } 218 | 219 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 220 | // Return the number of rows in the section. 221 | return menuItems.count 222 | } 223 | 224 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 225 | let CellIdentifier: String = "Cell" 226 | var cell: UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) 227 | if cell == nil { 228 | cell = UITableViewCell(style: .subtitle, reuseIdentifier: CellIdentifier) 229 | } 230 | // Configure the cell... 231 | cell?.textLabel?.text = "\(menuItems[indexPath.row])" 232 | cell?.textLabel?.textColor = UIColor(red: CGFloat(240 / 255.0), green: CGFloat(128 / 255.0), blue: CGFloat(50 / 255.0), alpha: CGFloat(1)) 233 | cell?.textLabel?.font = UIFont(name: "HelveticaNeue", size: CGFloat(14)) 234 | cell?.imageView?.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(30), height: CGFloat(30)) 235 | // cell.imageView.backgroundColor=[UIColor redColor]; 236 | cell?.imageView?.image = UIImage(named: "\(menuImages[indexPath.row])") 237 | cell?.textLabel?.text = "\(menuItems[indexPath.row])" 238 | // if (indexPath.row==1 || indexPath.row==0 ||indexPath.row==2 || indexPath.row==3 || indexPath.row==5 ||indexPath.row==9) { 239 | //cell.layoutMargins = UIEdgeInsetsZero; 240 | // cell.separatorInset = UIEdgeInsetsMake(1.0f, 1.0f, 0.0f, cell.bounds.size.width) ; 241 | //} 242 | return cell! 243 | } 244 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 245 | return 50 246 | } 247 | 248 | // MARK: - Table view delegate 249 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 250 | self.dkNavDrawerDelegate?.dkNavDrawerSelection(indexPath.row) 251 | closeNavigationDrawer() 252 | } 253 | 254 | } 255 | -------------------------------------------------------------------------------- /DrawerView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 36 | 46 | 47 | 48 | 49 | 50 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | --------------------------------------------------------------------------------