UIPresentationController使用 -- 仿UIAlertController

吐槽模式

最近看了很多关于UIPresentationController的文章,个人表示太难看懂了,他们的自己封装的太多了,不利于快速学习,对于这类知识不需要太多的写封装,又不是专门教架构和封装,跳来跳去的眼睛都花了,真是蛋疼!

教授模式

当父UIViewController调用present(_:animated:completion:)来呈现子UIViewController过程中使用UIPresentationController来控制转场的,所以我把所有的自定义UIPresentationController的都放在了子UIViewController中。

直接看我写的子UIViewController,

//此视图控制器是将要 被 呈现的

class TestViewController: UIViewController, UIViewControllerTransitioningDelegate {//这个代理是必须的,用来控制转场动画,个人觉得TestViewController的呈现动画由TestViewController自己去实现是最好的,所以我用TestViewController继承了UIViewControllerTransitioningDelegate代理

init() {

super.init(nibName: nil, bundle: nil)

//自定义呈现,这两个操作必须放在init方法中

modalPresentationStyle = .custom  //这个很重要

transitioningDelegate = self //UIViewControllerTransitioningDelegate的代理

}

required init?(coder aDecoder: NSCoder) {

super.init(coder: aDecoder)

fatalError("init(coder:) has not been implemented")

}

deinit {

print("TestViewController -- 释放")

}

override func viewDidLoad() {

super.viewDidLoad()

view.layer.cornerRadius = 10    //只设置这一个,自己会有剪切,子视图不会被剪切

}

@IBAction func dismissAction(_ sender: Any) {

dismiss(animated: true)

}

//这个是UIViewControllerTransitioningDelegate中的方法

public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {

let pc = XMAlertPresentationController(presentedViewController: presented, presenting: presenting)

return pc//返回自定义的UIPresentationController

}

}

然后在看自定义的UIPresentationController

//present or dismiss 两个过程实现

class XMAlertPresentationController: UIPresentationController {

var view: UIView?      //此试图包含一个点击手势

var bgView: UIView?    //不能交互的视图

deinit {

print("XMAlertSheetPresentationController -- 释放")

}

//呈现动画将要开始

override func presentationTransitionWillBegin() {

//

view = UIView(frame: (containerView?.bounds)!)

view?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dismissAction)))

view?.backgroundColor = UIColor(white: 0, alpha: 0)    //这个一定要的,不然下面的动画就没效果了

containerView?.addSubview(view!)

bgView = UIView(frame: (containerView?.bounds)!)

bgView?.isUserInteractionEnabled = false

containerView?.addSubview(bgView!)

//通过使用「负责呈现」的 controller 的 UIViewControllerTransitionCoordinator,我们可以确保我们的动画与其他动画一道儿播放。

//背景色变动画,使用present or dismiss默认的动画实现

guard let transitionCoordinator = presentingViewController.transitionCoordinator else {

return

}

transitionCoordinator.animate(alongsideTransition: {(context: UIViewControllerTransitionCoordinatorContext!) -> Void in//动画0.4秒

self.view?.backgroundColor = UIColor(white: 0, alpha: 0.4)

})

}

//呈现动画已结束

override func presentationTransitionDidEnd(_ completed: Bool) {

// 如果呈现没有完成,那就移除背景 View,没有完成就是出了错误

if !completed {

view?.removeFromSuperview()

bgView?.removeFromSuperview()

}

}

//消失动画将要开始

override func dismissalTransitionWillBegin() {

//背景色变动画,使用present or dismiss默认的动画实现

guard let transitionCoordinator = presentingViewController.transitionCoordinator else {

self.view?.backgroundColor = UIColor(white: 0, alpha: 0.0)

return

}

transitionCoordinator.animate(alongsideTransition: {(context: UIViewControllerTransitionCoordinatorContext!) -> Void in

self.view?.backgroundColor = UIColor(white: 0, alpha: 0.0)

})

}

//消失动画已结束

override func dismissalTransitionDidEnd(_ completed: Bool) {

if completed {

view?.removeFromSuperview()

bgView?.removeFromSuperview()

}

}

//计算presentedView的frame

override var frameOfPresentedViewInContainerView: CGRect {

let size = containerView!.bounds.size//containerView是转场容器视图的,这里的size相当于mainScreen的size

if presentedViewController.preferredInterfaceOrientationForPresentation.isLandscape {//竖屏

let width = size.height - 20

return CGRect(x: (size.width - width)/2.0, y: size.height - 270, width: width, height: 260)

}

return CGRect(x: 10, y: size.height - 270, width: size.width - 20, height: 260)

}

//当前横竖屏变换时调用,调整自己写的视图

open override func containerViewWillLayoutSubviews() {

view?.frame = containerView!.frame

bgView?.frame = containerView!.frame

//当屏幕旋转后presentedView的frame需要自己调整,所以下面一行是必须的,presentedView == TestViewController.view这就明白了吧

presentedView?.frame = frameOfPresentedViewInContainerView  //这行是必须的

}

func dismissAction() {//点击消失

presentedViewController.dismiss(animated: true)

}

}

如何使用测试:

let vc = TestViewController();

self.present(vc, animated: true)

是不是使用起来很简单?

你可以打印XMAlertPresentationController中的presentedViewController和presentingViewController看看是什么类型

贤者模式

写完了,看着是不是很简单,把上面的两个类直接考到文件里就可使用,这个博客没有语法高亮也是个麻烦事,下面是效果图,源码

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

推荐阅读更多精彩内容