版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2019.12.28 星期六 |
前言
iOS中有關(guān)視圖控件用戶能看到的都在UIKit框架里面萧豆,用戶交互也是通過(guò)UIKit進(jìn)行的臼朗。感興趣的參考上面幾篇文章邻寿。
1. UIKit框架(一) —— UIKit動(dòng)力學(xué)和移動(dòng)效果(一)
2. UIKit框架(二) —— UIKit動(dòng)力學(xué)和移動(dòng)效果(二)
3. UIKit框架(三) —— UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)(一)
4. UIKit框架(四) —— UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)(二)
5. UIKit框架(五) —— 自定義控件:可重復(fù)使用的滑塊(一)
6. UIKit框架(六) —— 自定義控件:可重復(fù)使用的滑塊(二)
7. UIKit框架(七) —— 動(dòng)態(tài)尺寸UITableViewCell的實(shí)現(xiàn)(一)
8. UIKit框架(八) —— 動(dòng)態(tài)尺寸UITableViewCell的實(shí)現(xiàn)(二)
9. UIKit框架(九) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(一)
10. UIKit框架(十) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(二)
11. UIKit框架(十一) —— UICollectionView的重用蝎土、選擇和重排序(一)
12. UIKit框架(十二) —— UICollectionView的重用视哑、選擇和重排序(二)
13. UIKit框架(十三) —— 如何創(chuàng)建自己的側(cè)滑式面板導(dǎo)航(一)
14. UIKit框架(十四) —— 如何創(chuàng)建自己的側(cè)滑式面板導(dǎo)航(二)
15. UIKit框架(十五) —— 基于自定義UICollectionViewLayout布局的簡(jiǎn)單示例(一)
16. UIKit框架(十六) —— 基于自定義UICollectionViewLayout布局的簡(jiǎn)單示例(二)
17. UIKit框架(十七) —— 基于自定義UICollectionViewLayout布局的簡(jiǎn)單示例(三)
18. UIKit框架(十八) —— 基于CALayer屬性的一種3D邊欄動(dòng)畫(huà)的實(shí)現(xiàn)(一)
19. UIKit框架(十九) —— 基于CALayer屬性的一種3D邊欄動(dòng)畫(huà)的實(shí)現(xiàn)(二)
20. UIKit框架(二十) —— 基于UILabel跑馬燈類似效果的實(shí)現(xiàn)(一)
21. UIKit框架(二十一) —— UIStackView的使用(一)
22. UIKit框架(二十二) —— 基于UIPresentationController的自定義viewController的轉(zhuǎn)場(chǎng)和展示(一)
23. UIKit框架(二十三) —— 基于UIPresentationController的自定義viewController的轉(zhuǎn)場(chǎng)和展示(二)
24. UIKit框架(二十四) —— 基于UICollectionViews和Drag-Drop在兩個(gè)APP間的使用示例 (一)
25. UIKit框架(二十五) —— 基于UICollectionViews和Drag-Drop在兩個(gè)APP間的使用示例 (二)
26. UIKit框架(二十六) —— UICollectionView的自定義布局 (一)
27. UIKit框架(二十七) —— UICollectionView的自定義布局 (二)
28. UIKit框架(二十八) —— 一個(gè)UISplitViewController的簡(jiǎn)單實(shí)用示例 (一)
29. UIKit框架(二十九) —— 一個(gè)UISplitViewController的簡(jiǎn)單實(shí)用示例 (二)
30. UIKit框架(三十) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的簡(jiǎn)單示例(一)
31. UIKit框架(三十一) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的簡(jiǎn)單示例(二)
開(kāi)始
首先看下主要內(nèi)容
通過(guò)上下文菜單
(context menus)
學(xué)習(xí)增強(qiáng)您的應(yīng)用程序,包括配置操作誊涯,添加圖像挡毅,嵌套子菜單,添加自定義預(yù)覽等暴构。
下面看下寫(xiě)作環(huán)境
Swift 5, iOS 13, Xcode 11
接著就是正文了跪呈。
隨著iOS 13
的正式發(fā)布段磨,我們獲得了一個(gè)新的,簡(jiǎn)單耗绿,功能強(qiáng)大且簡(jiǎn)潔的用戶界面范例-上下文菜單(context menus)苹支。 上下文菜單取代了iOS 12之前使用的標(biāo)準(zhǔn)Peek and Pop
交互,并將其進(jìn)一步發(fā)展误阻。 當(dāng)您點(diǎn)擊并按住受支持的視圖時(shí)债蜜,上下文菜單會(huì)提供一些內(nèi)容的預(yù)覽以及操作列表。 它們?cè)谡麄€(gè)iOS中得到了廣泛使用究反,例如在Photos
應(yīng)用中寻定。 點(diǎn)按并按住照片會(huì)顯示一個(gè)上下文菜單,如下所示:
動(dòng)作列表和預(yù)覽都是可自定義的精耐。 點(diǎn)擊預(yù)覽將打開(kāi)照片狼速。 您可以自定義在上下文菜單中點(diǎn)擊預(yù)覽時(shí)發(fā)生的情況。
在本教程中卦停,您將構(gòu)建上下文菜單向胡,并通過(guò)以下方法將其推至極限:
- 配置動(dòng)作。
- 使用新的
SF Symbols
集合為操作設(shè)置圖像沫浆。 - 帶有嵌套和嵌入式子菜單的簡(jiǎn)化菜單捷枯。
- 使用相關(guān)信息構(gòu)建更好的自定義預(yù)覽。
- 將上下文菜單添加到表視圖中的每個(gè)項(xiàng)目专执。
Exploring Vacation Spots
上下文菜單旨在使現(xiàn)有內(nèi)容引人注目且易于訪問(wèn)淮捆。 您將菜單添加到現(xiàn)有應(yīng)用程序Vacation Spots
中。
在Xcode中打開(kāi)準(zhǔn)備好的項(xiàng)目本股,運(yùn)行應(yīng)用程序并開(kāi)始計(jì)劃下一個(gè)假期攀痊。
打開(kāi)應(yīng)用程序時(shí),您會(huì)看到一個(gè)表格視圖拄显,其中包含不同的目的地苟径。
輕按一個(gè)度假勝地可顯示有關(guān)目的地的重要信息。 您還可以添加景點(diǎn)評(píng)級(jí)躬审,在地圖上查看或進(jìn)入其Wikipedia
頁(yè)面棘街。
Your First Context Menu
查看度假勝地時(shí),點(diǎn)擊Submit Rating按鈕承边。
該應(yīng)用程序顯示代表1-5
星的幾個(gè)不同按鈕遭殉。 點(diǎn)擊您的選擇,然后Submit Your Rating
博助。 現(xiàn)在险污,Submit Rating
按鈕以及您選擇的分?jǐn)?shù)將變?yōu)?code>Update Rating。 再次點(diǎn)擊它可以更改或查看您的評(píng)分。
使用我們的應(yīng)用程序蛔糯,對(duì)于某些急切的世界旅行者而言拯腮,這可能會(huì)成為一個(gè)繁瑣的過(guò)程。 這是您第一個(gè)上下文菜單的理想選擇蚁飒。
返回Xcode
动壤,打開(kāi)SpotInfoViewController.swift
,在其中添加上下文菜單淮逻。
在文件底部狼电,添加以下擴(kuò)展:
// MARK: - UIContextMenuInteractionDelegate
extension SpotInfoViewController: UIContextMenuInteractionDelegate {
func contextMenuInteraction(
_ interaction: UIContextMenuInteraction,
configurationForMenuAtLocation location: CGPoint)
-> UIContextMenuConfiguration? {
return UIContextMenuConfiguration(
identifier: nil,
previewProvider: nil,
actionProvider: { _ in
let children: [UIMenuElement] = []
return UIMenu(title: "", children: children)
})
}
}
UIContextMenuInteractionDelegate
協(xié)議是構(gòu)建上下文菜單的關(guān)鍵。它帶有一個(gè)必需required
的方法-contextMenuInteraction(_:configurationForMenuAtLocation :)
弦蹂,您剛剛通過(guò)創(chuàng)建并返回一個(gè)新的UIContextMenuConfiguration
對(duì)象來(lái)實(shí)現(xiàn)該方法肩碟。
有很多事情要做,但是一旦完成凸椿,您將了解iOS中上下文菜單的基礎(chǔ)削祈。 UIContextMenuConfiguration
初始化程序采用三個(gè)參數(shù):
- 1) identifier - 標(biāo)識(shí)符:使用標(biāo)識(shí)符來(lái)跟蹤多個(gè)上下文菜單。
- 2) PreviewProvider:返回
UIViewController
的閉包脑漫。如果將其設(shè)置為nil
髓抑,則菜單的默認(rèn)預(yù)覽將顯示,這只是您點(diǎn)擊的視圖优幸。稍后您將使用它來(lái)顯示更吸引人的預(yù)覽吨拍。 - 3) actionProvider:上下文菜單中的每個(gè)項(xiàng)目都是一個(gè)動(dòng)作。此閉包實(shí)際上是您構(gòu)建菜單的地方网杆。您可以使用
UIActions
和嵌套的UIMenus
構(gòu)建UIMenu
羹饰。該閉包采用UIKit
提供的建議操作數(shù)組作為參數(shù)。這次碳却,您將忽略它队秩,因?yàn)槟牟藛螌⒕哂心约旱淖远x項(xiàng)目。
注意:上下文菜單使用現(xiàn)代的
Swift
界面昼浦,其閉包比UIKit的閉包要多得多馍资。 您將在本教程中編寫(xiě)的大多數(shù)代碼都大量使用了閉包。 這也是一種正常的Swift風(fēng)格关噪,即使用尾隨閉包語(yǔ)法(trailing closure syntax)
鸟蟹,而忽略了調(diào)用中的最終參數(shù)名稱。 在本教程中使兔,您將看到其余的調(diào)用建钥。
您可能已經(jīng)注意到,您從未直接創(chuàng)建上下文菜單火诸。 相反锦针,您將始終創(chuàng)建一個(gè)UIContextMenuConfiguration
對(duì)象荠察,系統(tǒng)將使用該對(duì)象來(lái)配置菜單中的項(xiàng)目置蜀。
通常奈搜,用于創(chuàng)建上下文菜單的UIMenu
不需要標(biāo)題,因此您可以為其提供空白字符串盯荤。 但是馋吗,到目前為止,這將創(chuàng)建一個(gè)空菜單秋秤。 如果菜單中包含一些操作宏粤,它將更加有用。
在contextMenuInteraction(_:configurationForMenuAtLocation :)
下添加此方法:
func makeRemoveRatingAction() -> UIAction {
// 1
var removeRatingAttributes = UIMenuElement.Attributes.destructive
// 2
if currentUserRating == 0 {
removeRatingAttributes.insert(.disabled)
}
// 3
let deleteImage = UIImage(systemName: "delete.left")
// 4
return UIAction(
title: "Remove rating",
image: deleteImage,
identifier: nil,
attributes: removeRatingAttributes) { _ in
self.currentUserRating = 0
}
}
makeRemoveRatingAction()
創(chuàng)建一個(gè)UIAction
來(lái)刪除用戶的評(píng)分灼卢。 稍后绍哎,您將其添加為上下文菜單中的第一項(xiàng)。 您的代碼將逐步執(zhí)行以下操作:
- 1) 動(dòng)作
action
可以具有一組影響其外觀和行為的屬性鞋真。 因?yàn)檫@是一個(gè)刪除操作崇堰,所以可以使用destructive
菜單元素屬性。 - 2) 如果
currentUserRating
為0
涩咖,則表示用戶沒(méi)有評(píng)級(jí)海诲。 沒(méi)有要?jiǎng)h除的內(nèi)容,因此您添加了disable
屬性以禁用菜單項(xiàng)檩互。 - 3)
UIAction
可以具有圖像特幔,并且iOS 13
的SF
符號(hào)看起來(lái)特別好,因此您可以將UIImage(systemName :)
初始化程序與新 SF Symbols應(yīng)用程序中的符號(hào)名稱一起使用闸昨。 - 4) 創(chuàng)建并返回一個(gè)
UIAction
蚯斯。 它不需要標(biāo)識(shí)符,因?yàn)橐院蟛恍枰盟?當(dāng)用戶點(diǎn)擊此菜單項(xiàng)時(shí)饵较,將觸發(fā)handler
閉包溉跃。
返回contextMenuInteraction(_:configurationForMenuAtLocation :)
,將聲明children
變量的行替換為:
let removeRating = self.makeRemoveRatingAction()
let children = [removeRating]
這將創(chuàng)建刪除評(píng)級(jí)操作并將其放置在children
數(shù)組中告抄。
太好了撰茎,您的上下文菜單現(xiàn)在可以執(zhí)行有用的操作!
接下來(lái)打洼,在viewDidLoad()
的末尾添加以下內(nèi)容:
let interaction = UIContextMenuInteraction(delegate: self)
submitRatingButton.addInteraction(interaction)
要在點(diǎn)擊并按住視圖時(shí)顯示上下文菜單龄糊,可以使用addInteraction
方法向該視圖添加UIContextMenuInteraction
。 這將創(chuàng)建一個(gè)交互募疮,并將其添加到submitRatingButton
炫惩。
您終于可以看到運(yùn)行中的上下文菜單了!
生成并運(yùn)行該應(yīng)用程序阿浓。 點(diǎn)擊并按住Update Rating
他嚷。 如果您已經(jīng)添加了評(píng)分,則可以將其刪除。 如果不是筋蓖,則禁用Remove rating
菜單項(xiàng)卸耘。
這是一個(gè)開(kāi)始,但是這個(gè)不起眼的上下文菜單還有很長(zhǎng)的路要走粘咖。 您已經(jīng)了解了上下文菜單中最重要的概念:
- UIContextMenuInteraction:將上下文菜單添加到視圖蚣抗。
-
UIContextMenuConfiguration:使用操作構(gòu)建
UIMenu
并配置其行為。 -
UIContextMenuInteractionDelegate:管理上下文菜單的生命周期瓮下,例如構(gòu)建
UIContextMenuConfiguration
翰铡。
但是,對(duì)于更多的美學(xué)問(wèn)題讽坏,例如自定義菜單的外觀呢锭魔?
Adding Submenus
子菜單是保持上下文菜單整潔有序的好方法。 使用它們對(duì)相關(guān)動(dòng)作進(jìn)行分組路呜。
將以下內(nèi)容添加到SpotInfoViewController.swift
底部的UIContextMenuInteractionDelegate
擴(kuò)展中:
func updateRating(from action: UIAction) {
guard let number = Int(action.identifier.rawValue) else {
return
}
currentUserRating = number
}
此方法使用UIAction
的標(biāo)識(shí)符來(lái)更新用戶的評(píng)分赂毯。
像UIContextMenuConfiguration
一樣,UIAction
可以具有標(biāo)識(shí)符拣宰。 updateRating(from :)
嘗試將操作的標(biāo)識(shí)符轉(zhuǎn)換為Int
并相應(yīng)地設(shè)置currentUserRating
党涕。
在updateRating(from :)
下面添加以下方法:
func makeRateMenu() -> UIMenu {
let ratingButtonTitles = ["Boring", "Meh", "It's OK", "Like It", "Fantastic!"]
let rateActions = ratingButtonTitles
.enumerated()
.map { index, title in
return UIAction(
title: title,
identifier: UIAction.Identifier("\(index + 1)"),
handler: updateRating)
}
return UIMenu(
title: "Rate...",
image: UIImage(systemName: "star.circle"),
children: rateActions)
}
此方法創(chuàng)建的UIAction
具有與每個(gè)用戶等級(jí)匹配的標(biāo)識(shí)符:1到5。 請(qǐng)記住巡社,UIAction
的處理程序是一個(gè)閉包項(xiàng)膛堤,在點(diǎn)擊該項(xiàng)目時(shí)會(huì)觸發(fā)它。 設(shè)置您之前寫(xiě)為每個(gè)操作處理程序的updateRating(from :)
晌该。 然后肥荔,它返回一個(gè)帶有所有操作的UIMenu
作為菜單的子級(jí)。
如果您查看UIAction
和UIMenu
的聲明朝群,它們都是UIMenuElement
的子類燕耿。 children
參數(shù)的類型為[UIMenuElement]
。 這意味著在配置上下文菜單時(shí)姜胖,可以同時(shí)添加操作或整個(gè)子菜單誉帅。
回到contextMenuInteraction(_:configurationForMenuAtLocation :)
,找到聲明子項(xiàng)的行右莱,并用以下內(nèi)容替換:
let rateMenu = self.makeRateMenu()
let children = [rateMenu, removeRating]
不是為每個(gè)可能的評(píng)分添加五個(gè)新項(xiàng)目蚜锨,而是將rateMenu
添加為子菜單。
構(gòu)建并運(yùn)行該應(yīng)用程序慢蜓,并通過(guò)設(shè)置用戶等級(jí)來(lái)測(cè)試您的上下文菜單亚再。
1. Inline Menus
嵌套的子菜單可以清除內(nèi)容,但這意味著用戶需要額外點(diǎn)擊才能執(zhí)行操作晨抡。
為了使操作更簡(jiǎn)單氛悬,您可以內(nèi)聯(lián)顯示菜單则剃。 displayInline
菜單選項(xiàng)將顯示根菜單中的所有項(xiàng)目,但用分隔線分隔如捅。
為此棍现,用以下命令替換創(chuàng)建并返回UIMenu
的makeRateMenu()
的末尾:
return UIMenu(
title: "Rate...",
image: UIImage(systemName: "star.circle"),
options: .displayInline,
children: rateActions)
除了添加.displayInline
菜單選項(xiàng)外,其他操作與以前相同伪朽。
構(gòu)建并運(yùn)行該應(yīng)用程序以查看結(jié)果:
Custom Previews
上下文菜單通常顯示內(nèi)容的預(yù)覽。 現(xiàn)在汛蝙,點(diǎn)擊并按住Submit Rating
按鈕將顯示Submit Rating
按鈕本身烈涮,或者其Update Rating
更改自我,如上一個(gè)屏幕截圖所示窖剑。 這并不完全吸引人坚洽。
接下來(lái),您將設(shè)置自己的預(yù)覽西土。 在UIContextMenuInteractionDelegate
擴(kuò)展的底部添加以下方法:
func makeRatePreview() -> UIViewController {
let viewController = UIViewController()
// 1
let imageView = UIImageView(image: UIImage(named: "rating_star"))
viewController.view = imageView
// 2
imageView.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
imageView.translatesAutoresizingMaskIntoConstraints = false
// 3
viewController.preferredContentSize = imageView.frame.size
return viewController
}
這使一個(gè)簡(jiǎn)單的UIViewController
可以顯示一個(gè)星級(jí)讶舰。
這是逐步發(fā)生的事情:
- 1) 該應(yīng)用程序已有一個(gè)
rating_star
圖像,用于該應(yīng)用程序中的星星需了。 使用該圖像創(chuàng)建一個(gè)UIImageView
并將其設(shè)置為空白UIViewController
的視圖跳昼。 - 2) 設(shè)置圖像的
frame
以指定其尺寸。 設(shè)置frame
就足夠了肋乍,您不需要為您設(shè)置任何“自動(dòng)布局”約束鹅颊。 將translatesAutoresizingMaskIntoConstraints
設(shè)置為false
。 - 3) 您需要指定
preferredContentSize
墓造,以將視圖控制器顯示為預(yù)覽堪伍。 如果您不這樣做,它將占用所有可用空間觅闽。
返回contextMenuInteraction(_:configurationForMenuAtLocation :)
帝雇,找到UIContextMenuConfiguration
初始化程序的PreviewProvider
參數(shù)。 將以下行替換為將makeRatePreview
作為預(yù)覽提供程序傳遞:
previewProvider: makeRatePreview) { _ in
構(gòu)建并運(yùn)行蛉拙。 點(diǎn)擊并按住Submit Rating
按鈕后尸闸,您應(yīng)該會(huì)看到評(píng)分星標(biāo)的預(yù)覽:
做得好! 這樣就為該上下文菜單包裝了所有內(nèi)容孕锄。 現(xiàn)在室叉,您可以為完全不同的事情做準(zhǔn)備了。
Context Menus in Table Views
如果在主表視圖中點(diǎn)擊一個(gè)度假區(qū)會(huì)顯示一個(gè)常見(jiàn)操作列表硫惕,這是否有用茧痕? 查看度假勝地時(shí),View Map
按鈕可打開(kāi)度假勝地所在位置的地圖視圖:
通過(guò)在度假勝地列表上的上下文菜單中添加View Map
操作恼除,用戶可以在打開(kāi)景點(diǎn)信息視圖控制器之前先打開(kāi)地圖踪旷。 您還將添加一個(gè)操作曼氛,可輕松與朋友分享您最喜歡的度假勝地。 到目前為止令野,您已經(jīng)了解了向視圖添加上下文菜單的必要步驟:
- 1) 將
UIContextMenuInteraction
添加到視圖舀患。 - 2) 實(shí)現(xiàn)
contextMenuInteraction(_:configurationForMenuAtLocation :)
,這是UIContextMenuInteractionDelegate
的一種required
方法气破。 - 3) 使用所有菜單項(xiàng)構(gòu)建一個(gè)
UIContextMenuConfiguration
聊浅。
度假勝地列表以表格視圖的形式存在于SpotsViewController
中。 表格視圖中的每一行都是視圖本身现使,或更具體地說(shuō)低匙,是UITableViewCell
。
要向每行添加上下文菜單碳锈,您可以像以前一樣進(jìn)行操作顽冶,但是有一種更簡(jiǎn)單的方法。
打開(kāi)SpotsViewController.swift
并在類的底部添加以下代碼:
// MARK: - UITableViewDelegate
override func tableView(
_ tableView: UITableView,
contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint)
-> UIContextMenuConfiguration? {
// 1
let index = indexPath.row
let vacationSpot = vacationSpots[index]
// 2
let identifier = "\(index)" as NSString
return UIContextMenuConfiguration(
identifier: identifier,
previewProvider: nil) { _ in
// 3
let mapAction = UIAction(
title: "View map",
image: UIImage(systemName: "map")) { _ in
self.showMap(vacationSpot: vacationSpot)
}
// 4
let shareAction = UIAction(
title: "Share",
image: UIImage(systemName: "square.and.arrow.up")) { _ in
VacationSharer.share(vacationSpot: vacationSpot, in: self)
}
// 5
return UIMenu(title: "", image: nil, children: [mapAction, shareAction])
}
}
使用表視圖售碳,將UIContextMenu
添加到每一行就像在UITableViewDelegate
上實(shí)現(xiàn)此方法一樣容易强重。
點(diǎn)擊并按住任意行將調(diào)用tableView(_:contextMenuConfigurationForRowAt:point :)
,從而允許它為特定行提供上下文菜單贸人。
您正在為表格視圖的每一行構(gòu)建一個(gè)有用的功能菜單间景,因此需要進(jìn)行很多工作。在上面的代碼中艺智,您:
- 1) 獲取當(dāng)前行的休假地點(diǎn)拱燃。
- 2) 在上下文菜單中添加一個(gè)標(biāo)識(shí)符,您將立即使用它力惯。您必須將其轉(zhuǎn)換為
NSString
碗誉,因?yàn)闃?biāo)識(shí)符需要符合NSCopying
。 - 3) 菜單中的第一個(gè)動(dòng)作是針對(duì)地圖的父晶。輕觸此項(xiàng)目將調(diào)用
showMap(vacationSpot :)
哮缺,它將打開(kāi)該景點(diǎn)的地圖視圖。 - 4) 添加其他動(dòng)作以共享該地點(diǎn)甲喝。
VacationSharer.share(vacationSpot:in :)
是用于打開(kāi)共享表的幫助器方法尝苇。 - 5) 最后,構(gòu)造并返回包含兩個(gè)項(xiàng)目的
UIMenu
埠胖。
就這樣糠溜。構(gòu)建并運(yùn)行該應(yīng)用程序,然后點(diǎn)擊并按住一個(gè)度假區(qū)以嘗試新的上下文菜單直撤。
1. Custom Previews in Table Views
再次非竿,默認(rèn)預(yù)覽留有一些改進(jìn)的余地。 上下文菜單僅將整個(gè)表格視圖單元格用作預(yù)覽谋竖。
在第一個(gè)上下文菜單中红柱,您使用了UIContextMenuConfiguration
的previewProvider
參數(shù)來(lái)顯示自定義預(yù)覽承匣。 PreviewProvider
使您可以創(chuàng)建一個(gè)全新的UIViewController
作為預(yù)覽。 但是锤悄,還有另一種方式韧骗。
添加以下UITableViewDelegate
方法:
override func tableView(_ tableView: UITableView,
previewForHighlightingContextMenuWithConfiguration
configuration: UIContextMenuConfiguration)
-> UITargetedPreview? {
guard
// 1
let identifier = configuration.identifier as? String,
let index = Int(identifier),
// 2
let cell = tableView.cellForRow(at: IndexPath(row: index, section: 0))
as? VacationSpotCell
else {
return nil
}
// 3
return UITargetedPreview(view: cell.thumbnailImageView)
}
這不是創(chuàng)建一個(gè)新的UIViewController
,而是使用UITargetedPreview
指定一個(gè)現(xiàn)有視圖零聚。 這是逐步發(fā)生的事情:
- 1) 在前面的方法中袍暴,您為
UIContextMenuConfiguration
提供了一個(gè)標(biāo)識(shí)符。 現(xiàn)在隶症,您可以使用它來(lái)獲取分接索引政模。 - 2) 獲取該索引處的單元格。
- 3) 創(chuàng)建一個(gè)
UITargetedPreview
沿腰,并傳遞單元格的圖像視圖览徒。
這告訴上下文菜單將單元格的圖像視圖用作預(yù)覽狈定,而不是整個(gè)單元格颂龙。
構(gòu)建并運(yùn)行以查看新的預(yù)覽:
看起來(lái)好多了,不是嗎纽什? 現(xiàn)在措嵌,點(diǎn)擊預(yù)覽。
度假勝地列表再次在屏幕上顯示動(dòng)畫(huà)芦缰。 好吧企巢,預(yù)覽的目的是預(yù)覽某些內(nèi)容。 在這種情況下让蕾,預(yù)覽休假地點(diǎn)的地點(diǎn)信息視圖控制器將是有意義的浪规。 接下來(lái),您將解決這個(gè)問(wèn)題探孝。
2. Handling Preview Actions
在SpotsViewController
中添加此最終的UITableViewDelegate
方法:
override func tableView(
_ tableView: UITableView, willPerformPreviewActionForMenuWith
configuration: UIContextMenuConfiguration,
animator: UIContextMenuInteractionCommitAnimating) {
// 1
guard
let identifier = configuration.identifier as? String,
let index = Int(identifier)
else {
return
}
// 2
let cell = tableView.cellForRow(at: IndexPath(row: index, section: 0))
// 3
animator.addCompletion {
self.performSegue(
withIdentifier: "showSpotInfoViewController",
sender: cell)
}
}
點(diǎn)擊上下文菜單的預(yù)覽時(shí)笋婿,將觸發(fā)此UITableViewDelegate
方法。 輕按預(yù)覽可關(guān)閉上下文菜單顿颅,而tableView(_:willPerformPreviewActionForMenuWith:animator :)
使您有機(jī)會(huì)在動(dòng)畫(huà)完成時(shí)運(yùn)行代碼缸濒。 下面就是要做的事情:
- 1) 和以前一樣,使用標(biāo)識(shí)符查找上下文菜單所屬的行的索引粱腻。
- 2) 獲取用戶點(diǎn)擊的單元格庇配。
- 3) 動(dòng)畫(huà)
(animator)
對(duì)象處理釋放動(dòng)畫(huà)。 在這里绍些,您添加了一個(gè)完成處理程序捞慌,該處理程序通過(guò)segue
顯示了現(xiàn)場(chǎng)信息視圖控制器。
構(gòu)建并運(yùn)行柬批,查看點(diǎn)擊預(yù)覽時(shí)會(huì)發(fā)生什么卿闹。 在學(xué)習(xí)過(guò)程中揭糕,使用新的上下文菜單會(huì)很有趣,因?yàn)槟呀?jīng)完成了本教程锻霎。 恭喜你著角!
上下文菜單還可以與drag and drop
無(wú)縫地交互。 您可以通過(guò)觀看WWDC 2019的iOS 13的UI現(xiàn)代化視頻Modernizing Your UI for iOS 13了解更多信息旋恼。
后記
本篇主要講述了替換舊的
Peek and Pop
交互的基于iOS13的Context Menus
吏口,感興趣的給個(gè)贊或者關(guān)注~~~