iOS UIMenuController UIMenuItem

时间:2020-02-23 14:45:56  来源:igfitidea点击:

在本教程中,我们将在iOS应用程序中实现UIMenuController元素。

UIMenuController

UIMenuController类用于在UI元素上显示编辑菜单。
编辑菜单是一个具有不同操作的矩形框。
默认情况下,有一些内置操作,例如剪切,复制,粘贴,查找,替换,定义等。

通常,这也称为iOS工具提示菜单,因为它具有用于快速操作的便捷命令。

UIMenuItems添加到此UIMenuController中。

通过示例更容易理解这种工作方式。

让我们从一个很小的基础项目开始。

代码

如下图所示,在XCode的Main.storyboard中添加一个UITextField:

以下是ViewController.swift的代码:

class ViewController: UIViewController, UITextFieldDelegate {
  
  @IBOutlet weak var myTextField: UITextField!
  override func viewDidLoad() {
      super.viewDidLoad()
      
      
      myTextField.delegate = self
      
      let menuController: UIMenuController = UIMenuController.shared
      
      menuController.setMenuVisible(true, animated: true)
      
   
      menuController.arrowDirection = UIMenuController.ArrowDirection.default
      
      menuController.setTargetRect(CGRect.zero, in: view)
      
      let menuItem1: UIMenuItem = UIMenuItem(title: "Menu 1", action: #selector(onMenu1(sender:)))
      let menuItem2: UIMenuItem = UIMenuItem(title: "Menu 2", action: #selector(onMenu2(sender:)))
      let menuItem3: UIMenuItem = UIMenuItem(title: "Menu 3", action: #selector(onMenu3(sender:)))
      
      //Store MenuItem in array.
      let myMenuItems: [UIMenuItem] = [menuItem1, menuItem2, menuItem3]
      
      //Added MenuItem to MenuController.
      menuController.menuItems = myMenuItems
  }

  override func canPerformAction(_ action: Selector, withSender sender: Any!) -> Bool {
          return true
  }
  
  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
      textField.resignFirstResponder()
      return true
  }
  
  @objc internal func onMenu1(sender: UIMenuItem) {
      print("onMenu1")
  }
  
  @objc internal func onMenu2(sender: UIMenuItem) {
      print("onMenu2")
  }
  
  @objc internal func onMenu3(sender: UIMenuItem) {
      print("onMenu3")
  }
  
}

让我们分析一下以上代码中发生的事情。

  • UIMenuController是一个单例实例。
    因此使用" shared"初始化。

  • 将属性arrowDirection设置为默认值。
    默认方向是上还是下,具体取决于屏幕上的位置。

  • setTargetRect用于设置MenuController的位置。
    在上面的代码中,我们将CGRect设置为零,这意味着它将在UI元素的上方/下方显示MenuController。

但是MenuController如何知道其中显示以及向谁显示?

答:UIResponder。

UIResponder负责保持响应者链层次结构。
类似于视图层次结构。
作为第一响应者的对象将获取所有新事件。
通常,UITextField是第一响应者。

要将另一个UI元素设置为第一响应者,我们可以调用becomeFirstResponder

要创建UIMenuItem的实例,我们可以将其定义为:

UIMenuItem(title:,action:)-标题是字符串,而action是选择器函数,当单击该UIMenuItem时会触发该选择器函数。

然后我们通过在menuController.menuItems上设置MenuItem的数组。

canPerformAction(_:withSender :)是UIResponder的一部分。
返回true表示将显示所有操作。
让我们看看所有动作是什么。

让我们在模拟器上运行上述iOS应用程序,然后查看输出。

哇!它显示了很多动作。
为什么这样?

默认情况下,我们在canPerformAction中返回true。
这将返回所有动作。

为了只显示我们想要的动作,我们可以将canPerformAction函数更改为:

override func canPerformAction(_ action: Selector, withSender sender: Any!) -> Bool {
      if [#selector(onMenu1(sender:)), #selector(onMenu2(sender:)), #selector(onMenu3(sender:))].contains(action) {
          return true
      }
      else{
          return false
      }
  }

这样,我们可以检查动作是否属于以上选择器之一。
否则,我们返回false。
要包含任何默认操作,我们只需包含其内置选择器即可。
一些内置的选择器如下所示:

  • #selector(cut(_:))
  • #selector(copy(_:))
  • #selector(paste(_:))

以上方法的内置实现在UIResponderStandardEditActions协议中可用。
我们也可以覆盖它们。