在 iPad 上的 UIWebView 中定位弹出框

Posted

技术标签:

【中文标题】在 iPad 上的 UIWebView 中定位弹出框【英文标题】:Positioning a popover in a UIWebView on the iPad 【发布时间】:2013-04-11 11:59:32 【问题描述】:

我已向 UIMenuController 添加了一个自定义操作。单击该操作时,我希望弹出窗口类似于“定义”操作的工作方式(请参见下面的屏幕截图)。

但是,我无法让弹出框在 UIWebView 中正确定位。这是我的代码的摘录,当用户选择自定义操作时会生成弹出框:

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) 
    popover = [[UIPopoverController alloc]
                         initWithContentViewController:contentController];
    [popover setDelegate:self];
    popover.popoverContentSize = CGSizeMake(240., 60.);
    UIMenuController *menuController = [UIMenuController sharedMenuController];

    [popover presentPopoverFromRect:menuController.menuFrame
                             inView:webView
           permittedArrowDirections:UIPopoverArrowDirectionAny
                           animated:YES];

这是设备处于纵向模式时的结果:

如您所见,这还不错,但我无法让它与所选文本完全对齐;在横向模式下,弹出框的位置甚至不接近。

有人知道我如何将弹出框正确定位到所选文本,并在用户旋转设备时使其正确定位吗? SDK 版本为 ios 6.1。

【问题讨论】:

我觉得不错。您能否提供显示所需输出的图像? 如果你看一下我原始帖子中的第一张图片,弹出框的箭头与文本选择的左侧齐平;同样,如果它在下方,箭头的点将与所选文本的底部对齐。在我的例子中,当(理想情况下)它应该与选择的顶部对齐时,箭头的点位于所选文本的中间。 【参考方案1】:

你的代码在这里出错了:

[popover presentPopoverFromRect:menuController.menuFrame
                         inView:webView
       permittedArrowDirections:UIPopoverArrowDirectionAny
                       animated:YES];

您正在使用 menuController 的视图作为定位弹出窗口的矩形,而您真正想要的是文本选择的矩形。

你可以像这样得到文本选择矩形:

- (CGRect) textSelectionRect:(UITextView*)textView


    UITextRange *selectionRange = [textView selectedTextRange];
    NSArray *selectionRects = [self.textView selectionRectsForRange:selectionRange];
    CGRect completeRect = CGRectNull;
    for (UITextSelectionRect *selectionRect in selectionRects) 
        if (CGRectIsNull(completeRect)) 
            completeRect = selectionRect.rect;
         else completeRect = CGRectUnion(completeRect,selectionRect.rect);
    
    return completeRect;

(见答案here)

【讨论】:

我没有使用 UITextView。所选文本位于 UIWebView 中。 @Simon,那么需要使用javascript来获取rect,但原理是一样的。请参阅this useful explanation 以及 Cassius 的回答。【参考方案2】:

您可以使用 Javascript 代码从选定的文本中返回 CGRect。创建一个 file.js 并添加此代码(或将其放在 NSString 上):

// Method that gets the Rect of current selected text
// and returns in a JSON format
var getRectForSelectedText = function(elm) 
    if (typeof elm === "undefined") 
        elm = window.getSelection().getRangeAt(0);
    

    var rect = elm.getBoundingClientRect();
    return "" + rect.left + "," + rect.top + ", " + rect.width + "," + rect.height + "";

加载 Javascript(文件或 NSString)

- (void)webViewDidFinishLoad:(UIWebView *)theWebView

    //Load JS file
    NSString *filePath  = [[NSBundle mainBundle] pathForResource:@"file" ofType:@"js"];
    NSData *fileData    = [NSData dataWithContentsOfFile:filePath];
    NSString *jsString  = [[NSMutableString alloc] initWithData:fileData encoding:NSUTF8StringEncoding];

    [self.webview stringByEvaluatingJavaScriptFromString:jsString];

现在展示你的弹出框:

CGRect rect = CGRectFromString([self.webview stringByEvaluatingJavaScriptFromString:@"getRectForSelectedText()"]);

[popover presentPopoverFromRect:rect
                         inView:webView
       permittedArrowDirections:UIPopoverArrowDirectionAny
                       animated:YES];

如果你需要在你的self.view中使用矩形,调整框架:

- (CGRect)rectForSelectedText

    CGRect rect = CGRectFromString([self.webview stringByEvaluatingJavaScriptFromString:@"getRectForSelectedText()"]);
    rect.origin.x += self.webview.frame.origin.x;
    rect.origin.y += self.webview.frame.origin.y;
    return rect;

希望对你有所帮助!

【讨论】:

不幸的是它没有用。这是screenshot。有什么想法吗? Simon,如果你给我发一个测试项目来解释我出了什么问题,我可以更好地帮助你!

以上是关于在 iPad 上的 UIWebView 中定位弹出框的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iPad 上的 UIWebView 中上传文件?

UIWebView 的 allowInlineMediaPlayback 属性在 iPad 上的 4.2 上不起作用

iPad上的iOS UIWebView窗口宽度和高度

与 UIWebview 表单弹出框通信?

UIWebView 在 iPad 上无法正确显示

在 uipopover 中加载 uiwebview