iPad UIWebView позиционирует представление UIPopoverController в координатах ссылки href - PullRequest
4 голосов
/ 25 июня 2010

Я надеюсь, что этот вопрос не глупый, но как можно позиционировать представление UIPopoverController над UIWebView, чтобы стрелка всплывающего представления указывала на ссылку UIWebView, которая была нажата, чтобы показать его?

Я использую метод делегата;

-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( [[[inRequest URL] absoluteString] hasPrefix:@"myscheme:"] ) {
//UIPopoverController stuff here
return NO;
}

}

для захвата и маршрутизации щелчка, но я не уверен, как получить координаты ссылки для позиционирования всплывающего окна.

Буду очень признателен за любую помощь или указатель на соответствующую информацию.

Ответы [ 3 ]

7 голосов
/ 31 июля 2010

У меня есть решение, которое работает, но я думаю, что есть лучший способ сделать это.

Я создал TouchableWebView, который наследуется от UIWebView, и сохранил позицию касания в методе hitTest. После этого вам нужно установить делегат для вашего веб-просмотра и реализовать метод -webView:shouldStartLoadWithRequest:navigationType:

TouchableWebView.h:

@interface TouchableWebView : UIWebView {
CGPoint lastTouchPosition;
}
@property (nonatomic, assign) CGPoint lastTouchPosition;

TouchableWebView.m:

// I need to retrieve the touch position in order to position the popover
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    self.lastTouchPosition = point;
    return [super hitTest:point withEvent:event];
}

В RootViewController.m:

[self.touchableWebView setDelegate:self];

// WebView delegate, when hyperlink clicked
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request     navigationType:(UIWebViewNavigationType)navigationType {

    if (navigationType == UIWebViewNavigationTypeLinkClicked) 
    {   
        CGPoint touchPosition = [self.view convertPoint:self.touchableWebView.lastTouchPosition fromView:self.touchableWebView];
        [self displayPopOver:request atPosition:touchPosition isOnCelebrityFrame:FALSE];
        return FALSE;
    }

    return TRUE;
}

Это нехорошо, потому что документация UIWebView говорит, что вы не должны создавать подклассы. Я думаю, что есть более хороший способ, но это работает. Вы нашли другое решение?

2 голосов
/ 18 июня 2011

Присвойте каждой ссылке уникальный идентификатор и передайте этот идентификатор в свой код Obj-C с помощью логики «myscheme:».

Затем вы можете определить левое и верхнее смещение ссылки в UIWebView с помощью вызовов Javascript:

NSString *leftJS = [NSString stringWithFormat:@"document.getElementById('%d').offsetLeft - scrollX", linkID];
NSInteger leftOffset = [[currentTextView stringByEvaluatingJavaScriptFromString:js] intValue];

NSString *topJS = [NSString stringWithFormat:@"document.getElementById('%d').offsetTop - scrollY", linkID];
NSInteger topOffset = [[currentTextView stringByEvaluatingJavaScriptFromString:js] intValue];

Вычитание scrollX / scrollY учитывает, сколько раз пользователь или пользователь прокрутил UIWebView влево или вниз.

Насколько я понимаю, offsetLeft и offsetTop возвращают смещения элемента в его родительском элементе. Надеемся, что ваши ссылки находятся на вершине иерархии, а не встроены в div, иначе определение смещения становится более сложным.

1 голос
/ 18 ноября 2015

Для меня, использование getBoundingClientRect() и преобразование его в CGRect прекрасно работает.

NSString *js = [NSString stringWithFormat:@"JSON.stringify($(\"a[href='%@']\")[0].getBoundingClientRect())", [inRequest URL]];                                                                          
// {top:, right:, bottom:, left:, width:, height:}
NSString *rectJson =  [webView stringByEvaluatingJavaScriptFromString:js];                                                                                                                       
NSError *error = nil;                                                                                                                                                                            
NSDictionary *rectDict = [NSJSONSerialization JSONObjectWithData:[rectJson dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error];                         
if (error) {
    NSLog(@"json deserialization failed: %@\n%@", rectJson, error);                                                                                                                              
}
CGRect rect = CGRectMake([rectDict[@"left"] floatValue], [rectDict[@"top"] floatValue], [rectDict[@"width"] floatValue], [rectDict[@"height"] floatValue]);                                      
...