UIKit框架(三十二) —— 替換Peek and Pop交互的基于iOS13的Context Menus(一)

版本記錄

版本號 時(shí)間
V1.0 2019.12.28 星期六

前言

iOS中有關(guān)視圖控件用戶能看到的都在UIKit框架里面,用戶交互也是通過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布局的簡單示例(一)
16. UIKit框架(十六) —— 基于自定義UICollectionViewLayout布局的簡單示例(二)
17. UIKit框架(十七) —— 基于自定義UICollectionViewLayout布局的簡單示例(三)
18. UIKit框架(十八) —— 基于CALayer屬性的一種3D邊欄動(dòng)畫的實(shí)現(xiàn)(一)
19. UIKit框架(十九) —— 基于CALayer屬性的一種3D邊欄動(dòng)畫的實(shí)現(xiàn)(二)
20. UIKit框架(二十) —— 基于UILabel跑馬燈類似效果的實(shí)現(xiàn)(一)
21. UIKit框架(二十一) —— UIStackView的使用(一)
22. UIKit框架(二十二) —— 基于UIPresentationController的自定義viewController的轉(zhuǎn)場和展示(一)
23. UIKit框架(二十三) —— 基于UIPresentationController的自定義viewController的轉(zhuǎn)場和展示(二)
24. UIKit框架(二十四) —— 基于UICollectionViews和Drag-Drop在兩個(gè)APP間的使用示例 (一)
25. UIKit框架(二十五) —— 基于UICollectionViews和Drag-Drop在兩個(gè)APP間的使用示例 (二)
26. UIKit框架(二十六) —— UICollectionView的自定義布局 (一)
27. UIKit框架(二十七) —— UICollectionView的自定義布局 (二)
28. UIKit框架(二十八) —— 一個(gè)UISplitViewController的簡單實(shí)用示例 (一)
29. UIKit框架(二十九) —— 一個(gè)UISplitViewController的簡單實(shí)用示例 (二)
30. UIKit框架(三十) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的簡單示例(一)
31. UIKit框架(三十一) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的簡單示例(二)

開始

首先看下主要內(nèi)容

通過上下文菜單(context menus)學(xué)習(xí)增強(qiáng)您的應(yīng)用程序,包括配置操作,添加圖像,嵌套子菜單,添加自定義預(yù)覽等。

下面看下寫作環(huán)境

Swift 5, iOS 13, Xcode 11

接著就是正文了。

隨著iOS 13的正式發(fā)布,我們獲得了一個(gè)新的,簡單,功能強(qiáng)大且簡潔的用戶界面范例-上下文菜單(context menus)。 上下文菜單取代了iOS 12之前使用的標(biāo)準(zhǔn)Peek and Pop交互,并將其進(jìn)一步發(fā)展。 當(dāng)您點(diǎn)擊并按住受支持的視圖時(shí),上下文菜單會(huì)提供一些內(nèi)容的預(yù)覽以及操作列表。 它們在整個(gè)iOS中得到了廣泛使用,例如在Photos應(yīng)用中。 點(diǎn)按并按住照片會(huì)顯示一個(gè)上下文菜單,如下所示:

動(dòng)作列表和預(yù)覽都是可自定義的。 點(diǎn)擊預(yù)覽將打開照片。 您可以自定義在上下文菜單中點(diǎn)擊預(yù)覽時(shí)發(fā)生的情況。

在本教程中,您將構(gòu)建上下文菜單,并通過以下方法將其推至極限:

  • 配置動(dòng)作。
  • 使用新的SF Symbols集合為操作設(shè)置圖像。
  • 帶有嵌套和嵌入式子菜單的簡化菜單。
  • 使用相關(guān)信息構(gòu)建更好的自定義預(yù)覽。
  • 將上下文菜單添加到表視圖中的每個(gè)項(xiàng)目。

Exploring Vacation Spots

上下文菜單旨在使現(xiàn)有內(nèi)容引人注目且易于訪問。 您將菜單添加到現(xiàn)有應(yīng)用程序Vacation Spots中。

在Xcode中打開準(zhǔn)備好的項(xiàng)目,運(yùn)行應(yīng)用程序并開始計(jì)劃下一個(gè)假期。

打開應(yīng)用程序時(shí),您會(huì)看到一個(gè)表格視圖,其中包含不同的目的地。

輕按一個(gè)度假勝地可顯示有關(guān)目的地的重要信息。 您還可以添加景點(diǎn)評級,在地圖上查看或進(jìn)入其Wikipedia頁面。


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)擊它可以更改或查看您的評分。

使用我們的應(yīng)用程序,對于某些急切的世界旅行者而言,這可能會(huì)成為一個(gè)繁瑣的過程。 這是您第一個(gè)上下文菜單的理想選擇。

返回Xcode,打開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 :),您剛剛通過創(chuàng)建并返回一個(gè)新的UIContextMenuConfiguration對象來實(shí)現(xiàn)該方法。

有很多事情要做,但是一旦完成,您將了解iOS中上下文菜單的基礎(chǔ)。 UIContextMenuConfiguration初始化程序采用三個(gè)參數(shù):

  • 1) identifier - 標(biāo)識符:使用標(biāo)識符來跟蹤多個(gè)上下文菜單。
  • 2) PreviewProvider:返回UIViewController的閉包。如果將其設(shè)置為nil,則菜單的默認(rèn)預(yù)覽將顯示,這只是您點(diǎn)擊的視圖。稍后您將使用它來顯示更吸引人的預(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的閉包要多得多。 您將在本教程中編寫的大多數(shù)代碼都大量使用了閉包。 這也是一種正常的Swift風(fēng)格,即使用尾隨閉包語法(trailing closure syntax),而忽略了調(diào)用中的最終參數(shù)名稱。 在本教程中,您將看到其余的調(diào)用。

您可能已經(jīng)注意到,您從未直接創(chuàng)建上下文菜單。 相反,您將始終創(chuàng)建一個(gè)UIContextMenuConfiguration對象,系統(tǒng)將使用該對象來配置菜單中的項(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來刪除用戶的評分。 稍后,您將其添加為上下文菜單中的第一項(xiàng)。 您的代碼將逐步執(zhí)行以下操作:

  • 1) 動(dòng)作action可以具有一組影響其外觀和行為的屬性。 因?yàn)檫@是一個(gè)刪除操作,所以可以使用destructive菜單元素屬性。
  • 2) 如果currentUserRating0,則表示用戶沒有評級。 沒有要?jiǎng)h除的內(nèi)容,因此您添加了disable屬性以禁用菜單項(xiàng)。
  • 3) UIAction可以具有圖像,并且iOS 13SF符號看起來特別好,因此您可以將UIImage(systemName :)初始化程序與新 SF Symbols應(yīng)用程序中的符號名稱一起使用。
  • 4) 創(chuàng)建并返回一個(gè)UIAction。 它不需要標(biāo)識符,因?yàn)橐院蟛恍枰盟?當(dāng)用戶點(diǎn)擊此菜單項(xiàng)時(shí),將觸發(fā)handler閉包。

返回contextMenuInteraction(_:configurationForMenuAtLocation :),將聲明children變量的行替換為:

let removeRating = self.makeRemoveRatingAction()
let children = [removeRating]

這將創(chuàng)建刪除評級操作并將其放置在children數(shù)組中。

太好了,您的上下文菜單現(xiàn)在可以執(zhí)行有用的操作!

接下來,在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)添加了評分,則可以將其刪除。 如果不是,則禁用Remove rating菜單項(xiàng)。

這是一個(gè)開始,但是這個(gè)不起眼的上下文菜單還有很長的路要走。 您已經(jīng)了解了上下文菜單中最重要的概念:

  • UIContextMenuInteraction:將上下文菜單添加到視圖。
  • UIContextMenuConfiguration:使用操作構(gòu)建UIMenu并配置其行為。
  • UIContextMenuInteractionDelegate:管理上下文菜單的生命周期,例如構(gòu)建UIContextMenuConfiguration

但是,對于更多的美學(xué)問題,例如自定義菜單的外觀呢?


Adding Submenus

子菜單是保持上下文菜單整潔有序的好方法。 使用它們對相關(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)識符來更新用戶的評分。

UIContextMenuConfiguration一樣,UIAction可以具有標(biāo)識符。 updateRating(from :)嘗試將操作的標(biāo)識符轉(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è)用戶等級匹配的標(biāo)識符:1到5。 請記住,UIAction的處理程序是一個(gè)閉包項(xiàng),在點(diǎn)擊該項(xiàng)目時(shí)會(huì)觸發(fā)它。 設(shè)置您之前寫為每個(gè)操作處理程序的updateRating(from :)。 然后,它返回一個(gè)帶有所有操作的UIMenu作為菜單的子級。

如果您查看UIActionUIMenu的聲明,它們都是UIMenuElement的子類。 children參數(shù)的類型為[UIMenuElement]。 這意味著在配置上下文菜單時(shí),可以同時(shí)添加操作或整個(gè)子菜單。

回到contextMenuInteraction(_:configurationForMenuAtLocation :),找到聲明子項(xiàng)的行,并用以下內(nèi)容替換:

let rateMenu = self.makeRateMenu()
let children = [rateMenu, removeRating]

不是為每個(gè)可能的評分添加五個(gè)新項(xiàng)目,而是將rateMenu添加為子菜單。

構(gòu)建并運(yùn)行該應(yīng)用程序,并通過設(shè)置用戶等級來測試您的上下文菜單。

1. Inline Menus

嵌套的子菜單可以清除內(nèi)容,但這意味著用戶需要額外點(diǎn)擊才能執(zhí)行操作。

為了使操作更簡單,您可以內(nèi)聯(lián)顯示菜單。 displayInline菜單選項(xiàng)將顯示根菜單中的所有項(xiàng)目,但用分隔線分隔。

為此,用以下命令替換創(chuàng)建并返回UIMenumakeRateMenu()的末尾:

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è)屏幕截圖所示。 這并不完全吸引人。

接下來,您將設(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è)簡單的UIViewController可以顯示一個(gè)星級。

這是逐步發(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ì)看到評分星標(biāo)的預(yù)覽:

做得好! 這樣就為該上下文菜單包裝了所有內(nèi)容。 現(xiàn)在,您可以為完全不同的事情做準(zhǔn)備了。


Context Menus in Table Views

如果在主表視圖中點(diǎn)擊一個(gè)度假區(qū)會(huì)顯示一個(gè)常見操作列表,這是否有用? 查看度假勝地時(shí),View Map按鈕可打開度假勝地所在位置的地圖視圖:

通過在度假勝地列表上的上下文菜單中添加View Map操作,用戶可以在打開景點(diǎn)信息視圖控制器之前先打開地圖。 您還將添加一個(gè)操作,可輕松與朋友分享您最喜歡的度假勝地。 到目前為止,您已經(jīng)了解了向視圖添加上下文菜單的必要步驟:

  • 1) 將UIContextMenuInteraction添加到視圖。
  • 2) 實(shí)現(xiàn)contextMenuInteraction(_:configurationForMenuAtLocation :),這是UIContextMenuInteractionDelegate的一種required方法。
  • 3) 使用所有菜單項(xiàng)構(gòu)建一個(gè)UIContextMenuConfiguration。

度假勝地列表以表格視圖的形式存在于SpotsViewController中。 表格視圖中的每一行都是視圖本身,或更具體地說,是UITableViewCell

要向每行添加上下文菜單,您可以像以前一樣進(jìn)行操作,但是有一種更簡單的方法。

打開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)識符,您將立即使用它。您必須將其轉(zhuǎn)換為NSString,因?yàn)闃?biāo)識符需要符合NSCopying
  • 3) 菜單中的第一個(gè)動(dòng)作是針對地圖的。輕觸此項(xiàng)目將調(diào)用showMap(vacationSpot :),它將打開該景點(diǎn)的地圖視圖。
  • 4) 添加其他動(dòng)作以共享該地點(diǎn)。 VacationSharer.share(vacationSpot:in :)是用于打開共享表的幫助器方法。
  • 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è)上下文菜單中,您使用了UIContextMenuConfigurationpreviewProvider參數(shù)來顯示自定義預(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)識符。 現(xiàn)在,您可以使用它來獲取分接索引。
  • 2) 獲取該索引處的單元格。
  • 3) 創(chuàng)建一個(gè)UITargetedPreview,并傳遞單元格的圖像視圖。

這告訴上下文菜單將單元格的圖像視圖用作預(yù)覽,而不是整個(gè)單元格。

構(gòu)建并運(yùn)行以查看新的預(yù)覽:

看起來好多了,不是嗎? 現(xiàn)在,點(diǎn)擊預(yù)覽。

度假勝地列表再次在屏幕上顯示動(dòng)畫。 好吧,預(yù)覽的目的是預(yù)覽某些內(nèi)容。 在這種情況下,預(yù)覽休假地點(diǎn)的地點(diǎn)信息視圖控制器將是有意義的。 接下來,您將解決這個(gè)問題。

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)畫完成時(shí)運(yùn)行代碼。 下面就是要做的事情:

  • 1) 和以前一樣,使用標(biāo)識符查找上下文菜單所屬的行的索引。
  • 2) 獲取用戶點(diǎn)擊的單元格。
  • 3) 動(dòng)畫(animator)對象處理釋放動(dòng)畫。 在這里,您添加了一個(gè)完成處理程序,該處理程序通過segue顯示了現(xiàn)場信息視圖控制器。

構(gòu)建并運(yùn)行,查看點(diǎn)擊預(yù)覽時(shí)會(huì)發(fā)生什么。 在學(xué)習(xí)過程中,使用新的上下文菜單會(huì)很有趣,因?yàn)槟呀?jīng)完成了本教程。 恭喜你!

上下文菜單還可以與drag and drop無縫地交互。 您可以通過觀看WWDC 2019的iOS 13的UI現(xiàn)代化視頻Modernizing Your UI for iOS 13了解更多信息。

后記

本篇主要講述了替換舊的Peek and Pop交互的基于iOS13的Context Menus,感興趣的給個(gè)贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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