UIPresentationController使用 -- 仿UIAlertController

吐槽模式

最近看了很多關(guān)于UIPresentationController的文章演侯,個人表示太難看懂了憔四,他們的自己封裝的太多了,不利于快速學(xué)習(xí)措拇,對于這類知識不需要太多的寫封裝洛口,又不是專門教架構(gòu)和封裝问拘,跳來跳去的眼睛都花了蒸矛,真是蛋疼柿汛!

教授模式

當(dāng)父UIViewController調(diào)用present(_:animated:completion:)來呈現(xiàn)子UIViewController過程中使用UIPresentationController來控制轉(zhuǎn)場的,所以我把所有的自定義UIPresentationController的都放在了子UIViewController中券犁。

直接看我寫的子UIViewController术健,

//此視圖控制器是將要 被 呈現(xiàn)的

class TestViewController: UIViewController, UIViewControllerTransitioningDelegate {//這個代理是必須的,用來控制轉(zhuǎn)場動畫粘衬,個人覺得TestViewController的呈現(xiàn)動畫由TestViewController自己去實現(xiàn)是最好的荞估,所以我用TestViewController繼承了UIViewControllerTransitioningDelegate代理

init() {

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

//自定義呈現(xiàn),這兩個操作必須放在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? ? //只設(shè)置這一個稚新,自己會有剪切勘伺,子視圖不會被剪切

}

@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 兩個過程實現(xiàn)

class XMAlertPresentationController: UIPresentationController {

var view: UIView?? ? ? //此試圖包含一個點擊手勢

var bgView: UIView?? ? //不能交互的視圖

deinit {

print("XMAlertSheetPresentationController -- 釋放")

}

//呈現(xiàn)動畫將要開始

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!)

//通過使用「負(fù)責(zé)呈現(xiàn)」的 controller 的 UIViewControllerTransitionCoordinator褂删,我們可以確保我們的動畫與其他動畫一道兒播放娇昙。

//背景色變動畫,使用present or dismiss默認(rèn)的動畫實現(xiàn)

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)

})

}

//呈現(xiàn)動畫已結(jié)束

override func presentationTransitionDidEnd(_ completed: Bool) {

// 如果呈現(xiàn)沒有完成笤妙,那就移除背景 View,沒有完成就是出了錯誤

if !completed {

view?.removeFromSuperview()

bgView?.removeFromSuperview()

}

}

//消失動畫將要開始

override func dismissalTransitionWillBegin() {

//背景色變動畫噪裕,使用present or dismiss默認(rèn)的動畫實現(xiàn)

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)

})

}

//消失動畫已結(jié)束

override func dismissalTransitionDidEnd(_ completed: Bool) {

if completed {

view?.removeFromSuperview()

bgView?.removeFromSuperview()

}

}

//計算presentedView的frame

override var frameOfPresentedViewInContainerView: CGRect {

let size = containerView!.bounds.size//containerView是轉(zhuǎn)場容器視圖的蹲盘,這里的size相當(dāng)于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)

}

//當(dāng)前橫豎屏變換時調(diào)用,調(diào)整自己寫的視圖

open override func containerViewWillLayoutSubviews() {

view?.frame = containerView!.frame

bgView?.frame = containerView!.frame

//當(dāng)屏幕旋轉(zhuǎn)后presentedView的frame需要自己調(diào)整膳音,所以下面一行是必須的召衔,presentedView == TestViewController.view這就明白了吧

presentedView?.frame = frameOfPresentedViewInContainerView? //這行是必須的

}

func dismissAction() {//點擊消失

presentedViewController.dismiss(animated: true)

}

}

如何使用測試:

let vc = TestViewController();

self.present(vc, animated: true)

是不是使用起來很簡單?

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

賢者模式

寫完了祭陷,看著是不是很簡單苍凛,把上面的兩個類直接考到文件里就可使用,這個博客沒有語法高亮也是個麻煩事兵志,下面是效果圖醇蝴,源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市想罕,隨后出現(xiàn)的幾起案子悠栓,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惭适,死亡現(xiàn)場離奇詭異笙瑟,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)癞志,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門往枷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凄杯,你說我怎么就攤上這事错洁。” “怎么了盾舌?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵墓臭,是天一觀的道長。 經(jīng)常有香客問我妖谴,道長窿锉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任膝舅,我火速辦了婚禮嗡载,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘仍稀。我一直安慰自己洼滚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布技潘。 她就那樣靜靜地躺著遥巴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪享幽。 梳的紋絲不亂的頭發(fā)上铲掐,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機(jī)與錄音值桩,去河邊找鬼摆霉。 笑死,一個胖子當(dāng)著我的面吹牛奔坟,可吹牛的內(nèi)容都是我干的携栋。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼咳秉,長吁一口氣:“原來是場噩夢啊……” “哼婉支!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起澜建,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤磅摹,失蹤者是張志新(化名)和其女友劉穎滋迈,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體户誓,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡饼灿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了帝美。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碍彭。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖悼潭,靈堂內(nèi)的尸體忽然破棺而出庇忌,到底是詐尸還是另有隱情,我是刑警寧澤舰褪,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布皆疹,位于F島的核電站,受9級特大地震影響占拍,放射性物質(zhì)發(fā)生泄漏略就。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一晃酒、第九天 我趴在偏房一處隱蔽的房頂上張望表牢。 院中可真熱鬧,春花似錦贝次、人聲如沸崔兴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敲茄。三九已至,卻和暖如春山析,著一層夾襖步出監(jiān)牢的瞬間折汞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工盖腿, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人损同。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓翩腐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親膏燃。 傳聞我的和親對象是個殘疾皇子茂卦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容