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

效果展示:


新建工程和对应文件

首先建立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()
    }

以上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容