3

When UITextView's allowsEditingTextAttributes property is enabled,

textView.allowsEditingTextAttributes = true

the textview can show the BIU (bold/italic/underlined) styling options in the context menu by UIMenuController.

UIMenuController - BIU Styling Options #1

UIMenuController - BIU Styling Options #2

I wonder how to add more styling options (e.g., strikethrough, highlight) to the context menu inside the BIU. For example, the iOS' native Notes app has four options (BIU + strikethrough) inside the styling menu.

BIU Styling Options in the native Notes app

Is there any way to do it? I have been spending hours to find a way to override the "Selector(("_showTextStyleOptions:"))" but couldn't find out how.. Please help me!!

Jaehoon Lee
  • 49
  • 1
  • 5

1 Answers1

5

When the editing menu is about to become visible, you get a canPerformAction(_:withSender:) call in your UITextView. This method is called again when the user selects a button within the menu. You can check if the font style button was selected and add a custom button to that submenu.

class MyTextView: UITextView {

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        let menuController = UIMenuController.shared
        if var menuItems = menuController.menuItems,
            (menuItems.map { $0.action }).elementsEqual([.toggleBoldface, .toggleItalics, .toggleUnderline]) {
            // The font style menu is about to become visible
            // Add a new menu item for strikethrough style
            menuItems.append(UIMenuItem(title: "Strikethrough", action: .toggleStrikethrough))
            menuController.menuItems = menuItems
        }
        return super.canPerformAction(action, withSender: sender)
    }

    @objc func toggleStrikethrough(_ sender: Any?) {
        print("Strikethrough button was pressed")
    }

}

fileprivate extension Selector {
    static let toggleBoldface = #selector(MyTextView.toggleBoldface(_:))
    static let toggleItalics = #selector(MyTextView.toggleItalics(_:))
    static let toggleUnderline = #selector(MyTextView.toggleUnderline(_:))
    static let toggleStrikethrough = #selector(MyTextView.toggleStrikethrough(_:))
}

According to documentation, you may have to call update() on the UIMenuController after adding the button. But this was not necessary in my case.

Felix
  • 776
  • 8
  • 16