iOS彈出頁神器Presentation Controllers

原文:A Beginner’s Guide to Presentation Controllers in iOS 8
翻譯:安明哲
修改:安明哲

之前的文章中,我講述了如何使用stack view進(jìn)行自適應(yīng)頁面布局,本文將繼續(xù)探討iOS8下的Adaptive UI內(nèi)的Presentation Controllers。

在閱讀本文之前,當(dāng)你想要在屏幕增加一個彈出頁面的時候(注意我們的所有討論都是圍繞universal app),你可能要不斷地判斷屏幕尺寸去決定你要用如何的方式彈出一個新的頁面。
iOS8中,提供了Presentation Controller之后,你變可以省掉這么多繁多的判斷工作。僅僅需要寫入少量的代碼即可實現(xiàn)新加入頁面的自適應(yīng)布局。

這篇文章我們將介紹UIAlertController如何取代UIAlertView以及如何使用UIPopoverPresentation-Controller去彈出一個頁面。

開始之前依舊是要下載初始項目,在xcode內(nèi)運行這個項目,你將得到如下頁面:

項目初始化界面

請務(wù)必下載初始項目,以確保接下來的操作能夠繼續(xù)下去。我創(chuàng)建了一個靜態(tài)的tableview,并分別把他的兩個cell通過segue指向兩個UIView,兩個UIView中分別有一個按鈕,用于執(zhí)行一些事(比如顯示alert或者彈出頁面)

UIAlertController

iOS8以后,UIAlertController提到了UIAlertView和UIActionSheet。它改進(jìn)了先前的兩個類,自適應(yīng)于各種屏幕,你可以通過改變UIAlertController的Style來決定到底是使用Alert或是ActionSheet。

注意:在iPad下ActionSheet將以popover的形式展現(xiàn)出來,而且當(dāng)Action的Style為cancel的時候,Action按鈕是不會被顯示在iPad上的。

如果你還沒接觸UIController的話,上面的提醒可能看起來有點繞,那么接下來,我們寫一寫代碼,創(chuàng)建一個UIAclertView,然后做一些實驗,你就會明白我說的是什么了。

首先,我們在AlertViewController.swift這個文件內(nèi)綁定好的按鈕事件也就是showAlertWadTapped()內(nèi)添加如下代碼:

Action func showAlertWasTapped(sender: UIButton) {
        
    let alertController = UIAlertController(title: "一點都簡單", message: "來自一點都簡單的Alert", preferredStyle: UIAlertControllerStyle.Alert)
        
    let deleteAction = UIAlertAction(title: "刪除", style: UIAlertActionStyle.Destructive, handler: {(alert :UIAlertAction!) in
        print("Delete button tapped")
    })
    alertController.addAction(deleteAction)
        
    let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: {(alert :UIAlertAction!) in
        print("OK button tapped")
    })
    alertController.addAction(okAction)
        
    presentViewController(alertController, animated: true, completion: nil)

}

這個時候就創(chuàng)建了一個UIAlertController,初始化它的樣式為Alert,并且添加了兩個Action,我們設(shè)置deleteAction的ActionStyle為Destructive默認(rèn)它會使用一種醒目的tink,然后我們把這兩個Action添加到aletController內(nèi),最后再在使用主頁面的presentViewController方法顯示出來;他在iPhone和iPad下具體效果如下:

iPhone
iPad

我們看到,alert在iPhone和iPad下基本沒有什么區(qū)別,這個時候,我們把AlertController的AlertStyle修改成ActionSheet好看一看ActionSheet的顯示效果,修改代碼如下:

let alertController = UIAlertController(title: "一點都簡單", message: "來自一點都簡單的Alert", preferredStyle: UIAlertControllerStyle.ActionSheet)

分別在iPhone和iPad下運行App,你會發(fā)現(xiàn),在iPhone中程序一切正常,但是到了iPad下,程序則會出現(xiàn)錯誤。

現(xiàn)在我們來修復(fù),在iPad下的錯誤,在presentViewController()的前面,添加如下代碼:

alertController.popoverPresentationController?.sourceView = view
alertController.popoverPresentationController?.sourceRect = sender.frame

在iPad上,ActionSheet會被以popover的形式顯示出來,它衣服在當(dāng)前頁面的某一個組件上,因為必須指定一個sourceView用于指定ActionSheet的依附點(在這個空間的周圍被彈出),同時還應(yīng)指定一個sourceRect用于指定他被包含在哪一片區(qū)域內(nèi)。這只了這兩個屬性之后,我們再來看看效果:

調(diào)整代碼后iPad的顯示樣式

至于iPhone,因為iOS自適配的關(guān)系,根本不會去care這幾行代碼,依舊照常顯示:

iPhone顯示效果照舊

注意:當(dāng)你把一個Action的ActionStyle設(shè)置為cancel的時候,iPad將不會顯示這個Action。

UIPopoverPresentationController

Alert和AlertSheet可以很好地顯示一些信息,但是很多時候,如果你想要顯示更多的信息。這個時候就可以用到PopoverPresentationController。

你可能會留意到項目的storyboard文件內(nèi),我們還有一個單獨的(沒有被segue連接起來的)ViewController,它里面顯示了幾個label和一個TextAres它的id被設(shè)置為了PopoverViewController,現(xiàn)在我們將要在頁面中顯示它,如果是大屏幕設(shè)備的話,我們還會用popover的方式顯示它。

要實現(xiàn)這個,我們需要打開PopoverViewController.swift文件并且添加如下代碼:

let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("PopoverViewController") 
vc.modalPresentationStyle = UIModalPresentationStyle.Popover
let popover: UIPopoverPresentationController = vc.popoverPresentationController!
popover.barButtonItem = sender
presentViewController(vc, animated: true, completion:nil)

在上面的代碼中,我們獲取到了main stroyboard而后又通過id實例化了一個ViewController(也就是我們設(shè)置label和textview的那個viewController),設(shè)置這個viewController的顯示樣式為Popover,然后,我們創(chuàng)建一個PopoverPresentationController,設(shè)置barButtonItem屬性(barButtonItem決定這個popover頁面依附在哪一個按鈕下),最后,在當(dāng)前的view中顯示這個頁面。

運行app,你將得到如下效果:

在iPad下運行的效果

在iPhone下運行你將得到如下效果:

在iPhone下運行的效果

你肯定會注意到,在iPhone下你沒有辦法去關(guān)閉當(dāng)前這個彈出來的窗口,為了實現(xiàn)這個功能,我們可以設(shè)置一個navigation controller到這個頁面。

修改代碼讓PopViewController類繼承UIPopoverPresentationControllerDelegate協(xié)議:

class PopoverViewController: UIViewController, UIPopoverPresentationControllerDelegate

然后在按鈕事件(actionWasTapped()函數(shù))里面綁定popover的delegate(在presentViewController之前):

popover.delegate = self

添加如下方法到這個類中:

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
    return UIModalPresentationStyle.FullScreen
}
    
func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
    let navigationController = UINavigationController(rootViewController: controller.presentedViewController)
    let btnDone = UIBarButtonItem(title: "Done", style: .Done, target: self, action: "dismiss")
    navigationController.topViewController!.navigationItem.rightBarButtonItem = btnDone
    return navigationController
}
    
func dismiss() {
    self.dismissViewControllerAnimated(true, completion: nil)
}

adapativePresentationStyleForPresentationController()這個方法只會在你 compact-with 的情況下被調(diào)用,也就是在這個例子里這個方法只會在iPhone應(yīng)用里執(zhí)行這個方法。運行app將得到如下效果。同時我們還設(shè)置了一個navagationbar并在他的右邊添加了一個Done按鈕,這個按鈕綁定了一個dissmiss方法用來關(guān)閉整個窗口。

在iPhone下有了一個Done按鈕提供交互
在iPad下 一切照常運行

當(dāng)然,如果你想讓iPhone也能夠以popver的形式顯示這個頁面,你可以設(shè)置他的顯示Style為 None, 修改
adaptivePresentationStyleForPresentationController內(nèi)返回的屬性:

return UIModalPresentationStyle.None
此時iPone下也得到了和iPad下一樣的效果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容