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

发布于 2024-09-03 11:11:36 字数 397 浏览 6 评论 0原文

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

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

[[UIMenuController sharedMenuController] addObserver:self 
                                          forKeyPath:UIMenuControllerWillShowMenuNotification
                                             options:nil
                                             context:nil
 ];

I want to show 2 options like "hi" & "bye" when user completes selection on UIWebView.

I have added observer to my view controller as follows. But I don't know further implementation.

[[UIMenuController sharedMenuController] addObserver:self 
                                          forKeyPath:UIMenuControllerWillShowMenuNotification
                                             options:nil
                                             context:nil
 ];

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

如果没有 2024-09-10 11:11:36

萨加尔,

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

我将以下代码添加到包含 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]];
}

在我的 viewDidDisappear: 中,我继续删除这些项目:

- (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)。

Sagar,

Your question is a couple of months old, but I finally figured this one out, so I figured I'd answer it in case it helps out someone else.

I added the following code to the viewDidAppear: method of the view controller that contains the webview.

- (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]];
}

In my viewDidDisappear:, I go ahead and remove those items:

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

    [[UIMenuController sharedMenuController] setMenuItems:nil];
}

Then, I implemented the canPerformAction:withSender: method in the view controller. It helps to understand the concept of responders and responder chains to understand what is going on here. Basically, your uiviewcontroller is part of the responder chain, so it gets asked if it can handle any actions (like your custom actions you added above) that objects higher up the responder chain (like the UIWebView) don't know how to handle (see the UIResponder documentation and the Event Handling Guide for iOS for the gory details).

Now, when canPerformAction:withSender: is called for the webview, the sender parameter is set to nil. So, I try to be a bit clever about how I write this function. Basically, I make sure that the sender is nil, I'm showing the webview to the user, and any other controls on the page aren't the first responder. If that's the case, then I check to see if this is one of the actions I defined above and retur YES if it is. In all other cases I return the default value from UIViewController by calling the same method on super.

- (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];
}

Of course, now the next step is figuring out how to actually do something with the selection (probably by running some JavaScript in the webview).

指尖凝香 2024-09-10 11:11:36

在 swift 中:

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 中可用。

截图

In swift:

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")
    }
}

Note: #selector is available in Swift 2.2.

screenshot

好多鱼好多余 2024-09-10 11:11:36

在包含 WKWebView 控件的视图控制器中(没有人再使用 UIWebView 控件),重写 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或更新的

In the view controller that contains the WKWebView control (nobody uses the UIWebView control anymore), override the buildMenu method to add custom context menu items, like this:

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)
}

Works with iOS 16 or newer

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文