在 iphone 中的 UIWebView 中显示选择的自定义菜单

问题描述 投票:0回答:3

当用户在 UIWebView 上完成选择时,我想显示 2 个选项,例如“hi”和“bye”。

我已将观察者添加到我的视图控制器中,如下所示。但我不知道进一步的实施。

[[UIMenuController sharedMenuController] addObserver:self 
                                          forKeyPath:UIMenuControllerWillShowMenuNotification
                                             options:nil
                                             context:nil
 ];
iphone objective-c xcode uiwebview uimenucontroller
3个回答
44
投票

萨加尔,

你的问题已经有几个月了,但我终于弄清楚了这个问题,所以我想我会回答它,以防它对其他人有帮助。

我将以下代码添加到包含 webview 的视图控制器的 viewDidAppear: 方法中。

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    UIMenuItem *customMenuItem1 = [[[UIMenuItem alloc] initWithTitle:@"Custom 1" action:@selector(customAction1:)] autorelease];
    UIMenuItem *customMenuItem2 = [[[UIMenuItem alloc] initWithTitle:@"Custom 2" action:@selector(customAction2:)] autorelease];
    [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:customMenuItem1, customMenuItem2, nil]];
}

在我看来DidDisappear:,我继续删除这些项目:

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    [[UIMenuController sharedMenuController] setMenuItems:nil];
}

然后,我在视图控制器中实现了 canPerformAction:withSender: 方法。它有助于理解响应者和响应者链的概念,以了解这里发生的情况。基本上,您的 uiviewcontroller 是响应者链的一部分,因此它会被询问是否可以处理响应者链上层对象(如 UIWebView)不知道如何处理的任何操作(如您上面添加的自定义操作)(请参阅 UIResponder 文档iOS 事件处理指南 了解详细信息)。

现在,当为 webview 调用 canPerformAction:withSender: 时,sender 参数设置为 nil。因此,我尝试巧妙地编写这个函数。基本上,我确保发送者为零,我向用户显示网络视图,并且页面上的任何其他控件都不是第一响应者。如果是这种情况,那么我检查这是否是我上面定义的操作之一,如果是,则返回 YES。在所有其他情况下,我通过在 super 上调用相同的方法从 UIViewController 返回默认值。

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if (webView.superview != nil && ![urlTextField isFirstResponder]) {
        if (action == @selector(customAction1:) || action == @selector(customAction2:)) {
            return YES;
        }
    }

    return [super canPerformAction:action withSender:sender];
}

当然,现在下一步是弄清楚如何对选择进行实际操作(可能通过在 Web 视图中运行一些 JavaScript)。


5
投票

快速:

class ViewController: UIViewController {
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        // add two custom menu items to the context menu of UIWebView (assuming in contenteditable mode)
        let menuItem1 = UIMenuItem(title: "Foo", action: #selector(ViewController.foo))
        let menuItem2 = UIMenuItem(title: "Bar", action: #selector(ViewController.bar))
        UIMenuController.sharedMenuController().menuItems = [menuItem1, menuItem2]
    }

    override func viewDidDisappear(animated: Bool) {
        super.viewDidAppear(animated)
        UIMenuController.sharedMenuController().menuItems = nil
    }

    override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        if webView?.superview != nil {
            if action == #selector(ViewController.foo) || action == #selector(ViewController.bar) {
                return true
            }
        }

        return super.canPerformAction(action, withSender: sender)
    }

    func foo() {
        print("foo")
    }

    func bar() {
        print("bar")
    }
}

注意:#selector 在 Swift 2.2 中可用。

screenshot


0
投票

在包含

WKWebView
控件的视图控制器中,重写
buildMenu
方法以添加自定义上下文菜单项,如下所示:

override func buildMenu(with builder: any UIMenuBuilder) {
     
    let customMenuItem1 = UIAction(title: "Hi", image: UIImage(systemName: "star")) { action in
        // Handle menu item action here
    }
    
    let customMenuItem2 = UIAction(title: "Bye", image: UIImage(systemName: "hand")) { action in
        // Handle menu item action here
    }
    
    let menu = UIMenu(title: String(), image: nil, identifier: nil, options: .displayInline, children: [customMenuItem1, customMenuItem2])
    builder.insertSibling(menu, afterMenu: .standardEdit) // Or any other system menu
    
    super.buildMenu(with: builder)
}

适用于 iOS 16 或更高版本

© www.soinside.com 2019 - 2024. All rights reserved.