使用 WKWebView 修改键盘工具栏/附件视图

Modifying keyboard toolbar / accessory view with WKWebView

我正在使用带有内容可编辑 div 的 WKWebView 作为富文本编辑器的核心,我想修改键盘上方的顶部工具栏——包含自动更正建议的工具栏和格式化按钮。 (不确定这是否算作输入附件视图)。

我找到了一些展示如何删除栏的帖子,但其中 none 似乎有效,理想情况下我还是希望保留自动更正部分。

至少有一个应用程序 Ulysses 可以做到这一点(尽管我不知道它是否具有网络视图):

事实上,我很确定我可以通过对键盘视图层次结构进行手术来实现它...但这似乎是一种乏味且脆弱的方法。

有没有更好的方法?

谢谢!

也许 UITextInputAssistantItem 上的 this tutorial 会有所帮助。

也就是说,在摆弄了一段时间之后,使用 WKWebView 我仍然只能在第一次显示键盘时让它工作,之后每次都会 return 恢复原状。我发现唯一始终如一的工作是像下面这样的东西:

class ViewController: UIViewController {

    @IBOutlet weak private var webView: WKWebView!
    private var contentView: UIView?

    override func viewDidLoad() {
        super.viewDidLoad()
        webView.loadHTMLString("<html><body><div contenteditable='true'></div></body></html>", baseURL: nil)
        for subview in webView.scrollView.subviews {
            if subview.classForCoder.description() == "WKContentView" {
                contentView = subview
            }
        }
        inputAssistantItem.leadingBarButtonGroups = [UIBarButtonItemGroup(barButtonItems: [UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed(_:)))], representativeItem: nil)]
        inputAssistantItem.trailingBarButtonGroups = [UIBarButtonItemGroup(barButtonItems: [UIBarButtonItem(barButtonSystemItem: .camera, target: self, action: #selector(openCamera(_:))), UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(actionPressed(_:)))], representativeItem: nil)]
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: .UIKeyboardDidShow, object: nil)
    }

    @objc private func donePressed(_ sender: UIBarButtonItem) {
        view.endEditing(true)
    }

    @objc private func openCamera(_ sender: UIBarButtonItem) {
        print("camera pressed")
    }

    @objc private func actionPressed(_ sender: UIBarButtonItem) {
        print("action pressed")
    }

    @objc private func keyboardDidShow() {
        contentView?.inputAssistantItem.leadingBarButtonGroups = [UIBarButtonItemGroup(barButtonItems: [UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed(_:)))], representativeItem: nil)]
        contentView?.inputAssistantItem.trailingBarButtonGroups = [UIBarButtonItemGroup(barButtonItems: [UIBarButtonItem(barButtonSystemItem: .camera, target: self, action: #selector(openCamera(_:))), UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(actionPressed(_:)))], representativeItem: nil)]
    }

}

它会给出这样的东西:

每次键盘显示时都必须在内容视图以及视图控制器本身上设置它有点令人沮丧,我希望有更好的方法来做到这一点....但不幸的是我没找到。

也许具有相同行为的更稳定(面向未来)的方法是将 输入附件视图 放在 WKWebView.superview 中,然后使用响应键盘事件,显示和隐藏它。这是制作输入附件视图的老式方法。

详情:

  1. 观察键盘show/hide 通知
  2. 输入附件视图 放入 WKWebView.superview
  3. 在键盘显示上:将输入附件视图放在键盘上方
  4. on keyboard hide: 用键盘隐藏

也许很明显,使用 delegationWKWebView 和您的 UIViewController/UIView 子类之间传递动作事件。

此外,在 iOS 13+ 中,您可以覆盖 inputAccessoryView。您应该能够替换它以在 iPad 上提供您自己的。此处有更多详细信息: