【问题标题】:How to get the coordinates of Hyperlink in UIWebview如何在 UIWebview 中获取超链接的坐标
【发布时间】:2015-12-16 16:43:38
【问题描述】:

我正在UIWebview 中加载 pdf(具有多个超链接)文档。我必须通过超链接动态显示UIPopover

我可以使用 TapGesture Action 方法捕获超链接的坐标

- (void)tapAction:(UITapGestureRecognizer *)sender    
{
    self.point = [sender locationInView:self.myWebView];  
}

并使用以下方法通过超链接呈现UIPopover

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSURL *rqstUrl = [request URL];
    if (([[rqstUrl scheme] isEqualToString: @"https"] || [[rqstUrl scheme] isEqualToString: @"http"]) && (navigationType == UIWebViewNavigationTypeLinkClicked))
    {
        [self.myWebView stopLoading];
        CGRect rect = CGRectMake(self.point.x,self.point.y-5, 5, 5);
        UIPopoverController *popController = [[UIPopoverController alloc] initWithContentViewController:contentViewController];
        popController.popoverContentSize = CGSizeMake(500, 200);
        self.popController = popController;
        self.popController.delegate =self;
        UIPopoverArrowDirection direction = UIPopoverArrowDirectionUp|UIPopoverArrowDirectionDown;
        self.popController.popoverLayoutMargins = UIEdgeInsetsMake(0, rect.origin.x, 1, 1);
        [self.popController presentPopoverFromRect:rect inView:webView permittedArrowDirections:direction animated:YES];
    }
    return YES;
}

但问题是,如果我在 1 秒或 2 秒内点击了两个不同的位置,比如第一次点击是 在超链接,第二次点击是在“UIWebview 的其他地方”,UIPopover 是仅在第二个点击位置呈现,而不是在超链接位置呈现。 我必须仅根据超链接位置显示UIPopover,而不是在其他位置。我该如何解决这个问题?

【问题讨论】:

    标签: objective-c xcode uiwebview uipopovercontroller uitapgesturerecognizer


    【解决方案1】:

    使用覆盖视图

    1. 将您注册点击位置的方法替换为 覆盖 并通过点击。 UITapGestureRecognizer 有以下限制:

      • 当在超链接外部发生点击时,它会记录其位置,这要归功于UITapGestureRecognizer
      • 不幸的是,UIWebview 超链接点击优先于手势识别器,您永远不会得到centroid。这是真正的问题,导致弹出框出现错位。
    2. UIPopoverController 在 iOS 9 中已弃用。

      “不推荐使用 UIPopoverController。弹出框现在实现为 UIViewController 演示文稿。使用 UIModalPresentationPopover 和 UIPopoverPresentationController 的模态演示样式。”

    3. tapActionshouldStartLoadWithRequest 不耦合,可以彼此独立出现。此外,它们基本上是相互排斥的。

    使用叠加层在该视图中注册位置,然后点击下方的视图。 如果您的叠加层和 Web 视图具有相同的框架,您可以互换使用点按位置。覆盖将保证紧密耦合,并且您的方法的其余部分将按设计工作。

    class TapOverlayView: UIView {
        var centroid:CGRect = CGRect.zero
    
        override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
            centroid = CGRect(origin: point, size: CGSize(width: 1, height: 1))
            return nil // tap through
        }
    }
    

    委托

    extension ViewController: UIWebViewDelegate {
        public func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
            let rqstUrl = request.url
    
            if( rqstUrl!.scheme?.contains("http"))! && ( .linkClicked == navigationType) {
                webView.stopLoading()
    
                let contentViewController = storyboard!.instantiateViewController(withIdentifier: "popover")
                contentViewController.modalPresentationStyle = .popover
                contentViewController.preferredContentSize = CGSize(width: 200, height: 40)
    
                if let popController = contentViewController.popoverPresentationController {
                    popController.permittedArrowDirections = .down
                    popController.sourceView = webView
                    popController.sourceRect = CGRect(origin: tap.centroid.origin, size: CGSize.zero)
                    present(contentViewController, animated: true, completion: nil)
                }
            }
            return true
        }
    }
    

    ► 在GitHub 上查找此解决方案,在Swift Recipes 上查找更多详细信息。

    【讨论】:

    • 它工作正常,但是如何在点击的单词中间获得点?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    • 2013-12-26
    • 2011-11-26
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多