你好,歡迎來到IOS教程網

 Ios教程網 >> IOS使用技巧 >> IOS7技巧 >> Swift 側滑菜單的主頁向右滑動,露出下方菜單頁實現例子

Swift 側滑菜單的主頁向右滑動,露出下方菜單頁實現例子

編輯:IOS7技巧
本文章來為各位介紹一篇關於Swift 側滑菜單的主頁向右滑動,露出下方菜單頁實現例子,希望這篇教程能夠幫助到各位朋友,有興趣的可以進來看看。

側滑菜單是現在的APP上很常見的功能,其效果是在主界面用手指向右滑動,就可以將菜單展示出來,而主界面會被隱藏大部分,但是仍有左側的一小部分同菜單一起展示。

雖然網上也有很多實現這種slide view效果的第三方庫,但如果想自己寫代碼實現也是很簡單的,效果圖如下:

原文:Swift - 側滑菜單的實現(樣例1:主頁向右滑動,露出下方菜單頁)   原文:Swift - 側滑菜單的實現(樣例1:主頁向右滑動,露出下方菜單頁)   原文:Swift - 側滑菜單的實現(樣例1:主頁向右滑動,露出下方菜單頁)

1,程序頁面結構

   MainViewController:主頁視圖
   MenuViewController:菜單視圖,當主視圖側滑後顯示
   ViewController:頁面容器視圖,將上面兩個視圖加入到這裡面

2,StoryBoard配置

在StoryBoard中添加兩個新的View Controller(Storyoard ID分別是mainView、menuView),同時分別綁定MainViewController和MenuViewController這兩個類。

原文:Swift - 側滑菜單的實現(樣例1:主頁向右滑動,露出下方菜單頁)

3,代碼講解

(1)頁面初始化完畢後我們會先把主頁視圖(MainViewController)添加進來,同時對其設置個拖動手勢(UIPanGestureRecognizer)。
(2)當手指在屏幕從左向右滑動時,創建菜單視圖(MenuViewController)並添加到頁面最底部。同時主頁視圖會隨著手指的移動做線性移動。
(3)手指離開後,根據主頁視圖的位置(是否滑動超過一半),程序自動將主頁視圖完全展開或收起。
(4)菜單完全展開時,手指點擊主頁突出的部分也會自動收起菜單。
(5)menuViewExpandedOffset屬性是設置菜單展示出來後,主頁面在左側露出部分的寬度。
(6)currentState屬性保存菜單的狀態,同時監聽它的didSet事件來設置主頁面陰影(當菜單顯示出來的時候,主頁邊框會添加陰影,這樣有層次感,效果更好些。)

4,ViewController.swift代碼如下

import UIKit
 
class ViewController: UIViewController {
    // 主頁面控制器
    var mainViewController:MainViewController!
    
    // 菜單頁控制器
    var menuViewController:MenuViewController?
    
    // 菜單頁當前狀態
    var currentState = MenuState.Collapsed {
        didSet {
            //菜單展開的時候,給主頁面邊緣添加陰影
            let shouldShowShadow = currentState != .Collapsed
            showShadowForMainViewController(shouldShowShadow)
        }
    }
    
    // 菜單打開後主頁在屏幕右側露出部分的寬度
    let menuViewExpandedOffset: CGFloat = 60
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //添加主頁面
        mainViewController = UIStoryboard(name: "Main", bundle: nil)
            .instantiateViewControllerWithIdentifier("mainView") as! MainViewController
        view.addSubview(mainViewController.view)
        
        //建立父子關系
        addChildViewController(mainViewController)
        mainViewController.didMoveToParentViewController(self)
        
        //添加拖動手勢
        let panGestureRecognizer = UIPanGestureRecognizer(target: self,
            action: "handlePanGesture:")
        mainViewController.view.addGestureRecognizer(panGestureRecognizer)
        
        //單擊收起菜單手勢
        let tapGestureRecognizer = UITapGestureRecognizer(target: self,
            action: "handlePanGesture")
        mainViewController.view.addGestureRecognizer(tapGestureRecognizer)
    }
    
    //拖動手勢響應
    func handlePanGesture(recognizer: UIPanGestureRecognizer) {
        
        switch(recognizer.state) {
        // 剛剛開始滑動
        case .Began:
            // 判斷拖動方向
            let dragFromLeftToRight = (recognizer.velocityInView(view).x > 0)
            // 如果剛剛開始滑動的時候還處於主頁面,從左向右滑動加入側面菜單
            if (currentState == .Collapsed && dragFromLeftToRight) {
                currentState = .Expanding
                addMenuViewController()
            }
            
        // 如果是正在滑動,則偏移主視圖的坐標實現跟隨手指位置移動
        case .Changed:
            let positionX = recognizer.view!.frame.origin.x +
                recognizer.translationInView(view).x
            //頁面滑到最左側的話就不許要繼續往左移動
            recognizer.view!.frame.origin.x = positionX < 0 ? 0 : positionX
            recognizer.setTranslation(CGPointZero, inView: view)
            
        // 如果滑動結束
        case .Ended:
            //根據頁面滑動是否過半,判斷後面是自動展開還是收縮
            let hasMovedhanHalfway = recognizer.view!.center.x > view.bounds.size.width
            animateMainView(hasMovedhanHalfway)
        default:
            break
        }
    }
    
    //單擊手勢響應
    func handlePanGesture() {
        //如果菜單是展開的點擊主頁部分則會收起
        if currentState == .Expanded {
            animateMainView(false)
        }
    }
    
    // 添加菜單頁
    func addMenuViewController() {
        if (menuViewController == nil) {
            menuViewController = UIStoryboard(name: "Main", bundle: nil)
                .instantiateViewControllerWithIdentifier("menuView") as? MenuViewController
            
            // 插入當前視圖並置頂
            view.insertSubview(menuViewController!.view, atIndex: 0)
            
            // 建立父子關系
            addChildViewController(menuViewController!)
            menuViewController!.didMoveToParentViewController(self)
        }
    }
    
    //主頁自動展開、收起動畫
    func animateMainView(shouldExpand: Bool) {
        // 如果是用來展開
        if (shouldExpand) {
            // 更新當前狀態
            currentState = .Expanded
            // 動畫
            animateMainViewXPosition(CGRectGetWidth(mainViewController.view.frame) -
                menuViewExpandedOffset)
        }
        // 如果是用於隱藏
        else {
            // 動畫
            animateMainViewXPosition(0) { finished in
                // 動畫結束之後s更新狀態
                self.currentState = .Collapsed
                // 移除左側視圖
                self.menuViewController?.view.removeFromSuperview()
                // 釋放內存
                self.menuViewController = nil;
            }
        }
    }
    
    //主頁移動動畫(在x軸移動)
    func animateMainViewXPosition(targetPosition: CGFloat,
        completion: ((Bool) -> Void)! = nil) {
        //usingSpringWithDamping:1.0表示沒有彈簧震動動畫
        UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 1.0,
            initialSpringVelocity: 0, options: .CurveEaseInOut, animations: {
            self.mainViewController.view.frame.origin.x = targetPosition
            }, completion: completion)
    }
    
    //給主頁面邊緣添加、取消陰影
    func showShadowForMainViewController(shouldShowShadow: Bool) {
        if (shouldShowShadow) {
            mainViewController.view.layer.shadowOpacity = 0.8
        } else {
            mainViewController.view.layer.shadowOpacity = 0.0
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
 
// 菜單狀態枚舉
enum MenuState {
    case Collapsed  // 未顯示(收起)
    case Expanding   // 展開中
    case Expanded   // 展開
}
源碼下載:  hangge_1028.zip

5,功能改進
如果只有左右滑動能調出菜單的話,會顯得把菜單功能隱藏太深,可能用戶使用半天還不知道有這個菜單。
所以通常除了滑動調出菜單,頁面上也會提供個菜單按鈕,一般放置在導航欄上。點擊按鈕同樣可以打開,收起菜單。效果圖如下:
原文:Swift - 側滑菜單的實現(樣例1:主頁向右滑動,露出下方菜單頁)   原文:Swift - 側滑菜單的實現(樣例1:主頁向右滑動,露出下方菜單頁)

(1)在StoryBoard中,點擊首頁面(Main)的Scene,選擇Editor -> Embed In -> Navigation Controller 添加導航控制器
原文:Swift - 側滑菜單的實現(樣例1:主頁向右滑動,露出下方菜單頁)

(2)設置導航控制器的StoryBoard ID為 mainNavigaiton,同時給主頁面的導航欄左側添加一個菜單按鈕。


原文:Swift - 側滑菜單的實現(樣例1:主頁向右滑動,露出下方菜單頁)

(3)ViewController.swift 代碼如下(高亮處為修改過的地方):


import UIKit
 
class ViewController: UIViewController {
    // 主頁導航控制器
    var mainNavigationController:UINavigationController!
    
    // 主頁面控制器
    var mainViewController:MainViewController!
    
    // 菜單頁控制器
    var menuViewController:MenuViewController?
    
    // 菜單頁當前狀態
    var currentState = MenuState.Collapsed {
        didSet {
            //菜單展開的時候,給主頁面邊緣添加陰影
            let shouldShowShadow = currentState != .Collapsed
            showShadowForMainViewController(shouldShowShadow)
        }
    }
    
    // 菜單打開後主頁在屏幕右側露出部分的寬度
    let menuViewExpandedOffset: CGFloat = 60
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //初始化主視圖
        mainNavigationController = UIStoryboard(name: "Main", bundle: nil)
            .instantiateViewControllerWithIdentifier("mainNavigaiton")
            as! UINavigationController
        view.addSubview(mainNavigationController.view)
        
        //指定Navigation Bar左側按鈕的事件
        mainViewController = mainNavigationController.viewControllers.first
            as! MainViewController
        mainViewController.navigationItem.leftBarButtonItem?.action = Selector("showMenu")
        
        //添加拖動手勢
        let panGestureRecognizer = UIPanGestureRecognizer(target: self,
            action: "handlePanGesture:")
        mainNavigationController.view.addGestureRecognizer(panGestureRecognizer)
        
        //單擊收起菜單手勢
        let tapGestureRecognizer = UITapGestureRecognizer(target: self,
            action: "handlePanGesture")
        mainNavigationController.view.addGestureRecognizer(tapGestureRecognizer)
    }
    
    //導航欄左側按鈕事件響應
    func showMenu() {
        //如果菜單是展開的則會收起,否則就展開
        if currentState == .Expanded {
            animateMainView(false)
        }else {
            addMenuViewController()
            animateMainView(true)
        }
    }
    
    //拖動手勢響應
    func handlePanGesture(recognizer: UIPanGestureRecognizer) {
        
        switch(recognizer.state) {
            // 剛剛開始滑動
        case .Began:
            // 判斷拖動方向
            let dragFromLeftToRight = (recognizer.velocityInView(view).x > 0)
            // 如果剛剛開始滑動的時候還處於主頁面,從左向右滑動加入側面菜單
            if (currentState == .Collapsed && dragFromLeftToRight) {
                currentState = .Expanding
                addMenuViewController()
            }
            
            // 如果是正在滑動,則偏移主視圖的坐標實現跟隨手指位置移動
        case .Changed:
            let positionX = recognizer.view!.frame.origin.x +
                recognizer.translationInView(view).x
            //頁面滑到最左側的話就不許要繼續往左移動
            recognizer.view!.frame.origin.x = positionX < 0 ? 0 : positionX
            recognizer.setTranslation(CGPointZero, inView: view)
            
            // 如果滑動結束
        case .Ended:
            //根據頁面滑動是否過半,判斷後面是自動展開還是收縮
            let hasMovedhanHalfway = recognizer.view!.center.x > view.bounds.size.width
            animateMainView(hasMovedhanHalfway)
        default:
            break
        }
    }
    
    //單擊手勢響應
    func handlePanGesture() {
        //如果菜單是展開的點擊主頁部分則會收起
        if currentState == .Expanded {
            animateMainView(false)
        }
    }
    
    // 添加菜單頁
    func addMenuViewController() {
        if (menuViewController == nil) {
            menuViewController = UIStoryboard(name: "Main", bundle: nil)
                .instantiateViewControllerWithIdentifier("menuView") as? MenuViewController
            
            // 插入當前視圖並置頂
            view.insertSubview(menuViewController!.view, atIndex: 0)
            
            // 建立父子關系
            addChildViewController(menuViewController!)
            menuViewController!.didMoveToParentViewController(self)
        }
    }
    
    //主頁自動展開、收起動畫
    func animateMainView(shouldExpand: Bool) {
        // 如果是用來展開
        if (shouldExpand) {
            // 更新當前狀態
            currentState = .Expanded
            // 動畫
            animateMainViewXPosition(CGRectGetWidth(mainNavigationController.view.frame) -
                menuViewExpandedOffset)
        }
            // 如果是用於隱藏
        else {
            // 動畫
            animateMainViewXPosition(0) { finished in
                // 動畫結束之後s更新狀態
                self.currentState = .Collapsed
                // 移除左側視圖
                self.menuViewController?.view.removeFromSuperview()
                // 釋放內存
                self.menuViewController = nil;
            }
        }
    }
    
    //主頁移動動畫(在x軸移動)
    func animateMainViewXPosition(targetPosition: CGFloat,
        completion: ((Bool) -> Void)! = nil) {
            //usingSpringWithDamping:1.0表示沒有彈簧震動動畫
            UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 1.0,
                initialSpringVelocity: 0, options: .CurveEaseInOut, animations: {
                    self.mainNavigationController.view.frame.origin.x = targetPosition
                }, completion: completion)
    }
    
    //給主頁面邊緣添加、取消陰影
    func showShadowForMainViewController(shouldShowShadow: Bool) {
        if (shouldShowShadow) {
            mainNavigationController.view.layer.shadowOpacity = 0.8
        } else {
            mainNavigationController.view.layer.shadowOpacity = 0.0
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
 
// 菜單狀態枚舉
enum MenuState {
    case Collapsed  // 未顯示(收起)
    case Expanding   // 展開中
    case Expanded   // 展開
}

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved