美文网首页Swift编程首页投稿(暂停使用,暂停投稿)
[iOS][Swift]自己写一个带有回弹效果的抽屉

[iOS][Swift]自己写一个带有回弹效果的抽屉

作者: 彼蓝 | 来源:发表于2016-07-11 15:56 被阅读874次

    效果展示:


    新建工程和对应文件

    首先建立iOS工程,工程名随意,选择Single View Application即可。
    新建三个swift文件:

    • 用于显示主页面的mainViewController.swift,继承UIViewController
    • 用于显示左菜单的leftTableViewController.swift,继承UITableViewController
    • 用于显示右菜单的rightTableViewController.swift,继承UITableViewController
      那么现在我们左边的文件列表中有4个ViewController了:
      ViewController.swiftmainViewController.swiftleftTableViewController.swiftrightTableViewController.swift
      第一步完成~

    打造抽屉效果

    首先在ViewController类中建立其他三个要显示VC的对象:

    var mainViewController:UINavigationController?
    var leftViewController:LeftTableViewController?
    var rightViewController:RightTableViewController?
    

    viewDidload方法中加入:

    //视图加载
    self.leftViewController = LeftTableViewController()
    self.view.addSubview((leftViewController?.view)!)
            
    self.rightViewController = RightTableViewController()
    self.view.addSubview((rightViewController?.view)!)
            
    self.mainViewController = UINavigationController(rootViewController: MainViewController())
    self.view.addSubview((mainViewController?.view)!)
    

    为了方便和显示,mainViewController我选择继承于NavigationController
    至于为什么要先将左右VC加载到根视图后加载mainVC,后面我会说道。
    然后在刚刚加入的代码下继续加入:

    //隐藏左右视图
    self.leftViewController?.view.hidden = true
    self.rightViewController?.view.hidden = true
    

    首先隐藏左右的视图。因为主视图始终显示在最上面,而左右的菜单显示在下面,难免出现叠加遮挡额度结果。为了不使两个菜单视图互相遮挡,我们选择显示哪个菜单的时候将哪个视图显示出来的方法。
    为方便显示,给三个视图分别添加一个背景色。
    这里我设置的:
    mainViewControllerviewDIdLoad中:

    self.view.backgroundColor = UIColor.whiteColor()
    

    leftViewControllerviewDIdLoad中:

    self.view.backgroundColor = UIColor.redColor()
    

    rightViewControllerviewDIdLoad中:

    self.view.backgroundColor = UIColor.blackColor()
    

    然后我们回到ViewController类。
    在刚刚//隐藏左右视图的代码下添加一个手势:

    //添加滑动手势
     let pan = UIPanGestureRecognizer(target: self, action: #selector(ViewController.panAction(_:)))
    self.mainViewController?.view.addGestureRecognizer(pan)
    

    并在ViewController类中新建一个panAction方法:

    func panAction(sender: UIPanGestureRecognizer){}
    

    下面我们让屏幕获得手指的位置:

    //获取手指位置
    let point = sender.translationInView(sender.view)
    

    这里我们的sender.view其实就是我们的MainView
    然后判断是左滑还是右滑。正常情况下,sender.view?.frame.origin.x=0。
    如果sender.view?.frame.origin.x <= 0,那么我们就是向左滑,反之向右:

    if sender.view?.frame.origin.x <= 0{
            //向左滑
    }else{
            //向右滑    
    }
    

    为了显示效果比较好,我们在ViewController类中增加一个变量:

    var speed_f:CGFloat?//滑动速率
    

    并且在viewDidLoad方法中给它赋值:

    self.speed_f = 0.5//滑动速率
    

    向左滑的时候,显示右边的菜单,左边的菜单不显示,并且mainView向左移动;向右滑的时候,显示左边的菜单,右边的菜单不显示,兵器mainView向右移动。
    //向左滑下面添加:

    sender.view?.center = CGPointMake((sender.view?.center.x)! + point.x * speed_f!, (sender.view?.center.y)!)//计算新的view的center位置
    sender.setTranslation(CGPointMake(0, 0), inView: self.view)//矫正手指位置
    self.leftViewController?.view.hidden = true
    self.rightViewController?.view.hidden = false
    

    //向右滑下面添加:

    sender.view?.center = CGPointMake((sender.view?.center.x)! + point.x * speed_f!, (sender.view?.center.y)!)
    sender.setTranslation(CGPointMake(0, 0), inView: self.view)//矫正手指位置
    self.leftViewController?.view.hidden = false
    self.rightViewController?.view.hidden = true
    

    运行一下试试吧。两个抽屉都已经构建好了。
    试试滑动一下,发现一个问题:这抽屉没有极限的,可以无限滑动。
    下面我们来解决这个问题。


    抽屉的滑动极限和回弹效果

    我们的抽屉肯定是不能一直滑的,那么我们就需要给抽屉一个界限。
    首先在ViewController类中增加一个常量来表示界限值:

    let mainVC_offset:CGFloat = 120//屏幕偏移极限
    
    • 我这里设定的偏移是120。大家也可以自己更改一下这个数值看一下有什么效果~
      然后我们在滑动方法中,判断一下手指离开屏幕的时候几个View的操作。
      sender.state == .Ended,即手指离开屏幕的时候,我们判断离开的这个位置相对屏幕中的偏移量,如果偏移小就返回原来的位置,大于一定的界限就移动到下一个位置。
      当然,我们需要在ViewController类里增加一个变量:
    var condition_f:CGFloat?//三视图显示条件
    

    用于显示这个条件。并且在viewDidLoad方法中给它赋值:

    condition_f = 0//三视图显示条件
    

    从屏幕中间线到我们设定的滑动极限位置,这个宽度就是MainView的移动距离。当低于这个距离的一半的时候我们认为滑动量少,返回原位置;大于这个值我们就认为滑动量大,可以移动到下一个位置。


    在滑动方法panAction继续加入如下代码:
    //手指离开屏幕
    if sender.state == .Ended{
            if self.condition_f > UIScreen.mainScreen().bounds.size.width * 0.5 * speed_f!{//右滑超过界限
                    self.showLeftView()
            }else if self.condition_f < UIScreen.mainScreen().bounds.size.width * -0.5 * speed_f!{//左滑超过界限
                    self.showRightView()
            }else{
                    self.showMainView()
            }
      }
    

    并且在ViewController类中增加这三个对应的方法:

    //显示主View
    func showMainView(){}
    //显示左边菜单
    func showLeftView(){}
    //显示右边菜单
    func showRightView(){}
    

    在这三个方法里我们无非要做计算屏幕的偏移量,并且加上对应的动画效果使显示更加完善。
    完善这三个方法:

    func showMainView(){
            //动画显示
            UIView.beginAnimations(nil, context: nil)
            //屏幕偏移计算
            self.mainViewController?.view.center = CGPointMake(UIScreen.mainScreen().bounds.size.width / 2, UIScreen.mainScreen().bounds.size.height / 2)
            //提交动画
            UIView.commitAnimations()
        }
    func showLeftView(){
            UIView.beginAnimations(nil, context: nil)
            self.mainViewController?.view.center = CGPointMake(UIScreen.mainScreen().bounds.size.width * 1.5 - mainVC_offset, UIScreen.mainScreen().bounds.size.height / 2)
            UIView.commitAnimations()
        }
    func showRightView(){
            UIView.beginAnimations(nil, context: nil)
            self.mainViewController?.view.center = CGPointMake(mainVC_offset - UIScreen.mainScreen().bounds.size.width / 2, UIScreen.mainScreen().bounds.size.height / 2)
            UIView.commitAnimations()
        }
    

    以上。

    相关文章

      网友评论

        本文标题:[iOS][Swift]自己写一个带有回弹效果的抽屉

        本文链接:https://www.haomeiwen.com/subject/luhjjttx.html