2009-06-13 2 views
35

Я создал подкласс UIWebView и внедрили методы touchesBegan, touchesMoved и touchesEnded.Обработка касаний внутри UIWebView

, но подкласс webview не обрабатывает события touch.

Есть ли способ обработки событий касания внутри подкласса UIWebView ???

+3

Я бы подозревать любое поведение, когда подклассы UIWebView. Dev-doc говорит, что он не может быть подклассифицирован. Я предполагаю, что компилятор, обработка событий, runloop и т. Д.позволит подкласс, но я не буду доверять возможным побочным эффектам. Кроме того, ваш код может перестать работать вместе в будущем выпуске. Можете ли вы объяснить, что вы хотите сделать с подклассом UIWebView? – mobibob

+0

Я не понимаю, почему вы когда-либо хотели бы переопределить события касания, обрабатываемые UIWebView. Ваш пользователь захочет увеличить масштаб и уменьшить масштаб веб-сайта, а также нажать, чтобы щелкнуть hpyerlinks и т. Д. Код, который вы опубликовали выше, не имеет реализации в сенсорных методах ... Я думаю, что важно знать, что вы пытаетесь выполнить. Переопределение сенсорных событий в веб-представлении кажется мне плохой идеей. Есть ли другой способ выполнить поведение, которое вы ищете из своего приложения? –

+3

Я не ожидаю таких комментариев от разработчика. «Переопределение событий прикосновения в веб-представлении кажется мне плохой идеей» Остерегайтесь «Stanza» и «Kindle», как они подклассифицировали/подключили UIWebView для обработки событий. – Biranchi

ответ

0

Вы имеете в виду, что ваша субклассическая реализация не вызывается, когда вызывается touchBegan, touchsMoved и touchesEnded?

Это звучит как проблема с тем, как вы создали экземпляр объекта. Требуется больше деталей. Я думаю.

(Взяты форма комментариев)

Заголовочный файл

#import <UIKit/UIKit.h> 

@interface MyWebView : UIWebView { } @end 

Файл Реализация

#import "MyWebView.h" 

@implementation MyWebView 

- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { } return self; 
} 

- (void)drawRect:(CGRect)rect { 
    NSLog(@"MyWebView is loaded"); 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    NSLog(@"touches began"); 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    NSLog(@"Touches ended");  
} 

- (void)dealloc { 
    [super dealloc]; 
} 

@end 
+0

#import @interface MyWebView: UIWebView { } @end #import "MyWebView.h" @implementation MyWebView - (ID) initWithFrame: (CGRect) кадр { , если (self = [super initWithFrame: frame]) { } return self; } - (void) drawRect: (CGRect) rect { \t NSLog (@ «MyWebView загружен»); } - (void) touchesBegan: (NSSet *) касается объекта: (UIEvent *) событие { \t NSLog (прикосновения «@» начались »); } - (void) touchesEnded: (NSSet *) затрагивает событиеEvent: (UIEvent *) { \t NSLog (@ "Touches закончился"); \t } - (void) dealloc { [super dealloc]; } @end – Biranchi

+0

Где вы называете MyWebView * obj = [[MyWebView alloc] initWithFrame: CGMakeZero]; – rjstelling

+3

Может ли кто-нибудь с достаточной кармой сделать это блоком кода? –

5

Я не уверен, если это то, что вы хотите (это не то, что вы просили, но это может сработать заканчивается на том, что ваш конец игры), но вы могли бы вместо того, чтобы интерпретировать штрихи в JavaScript внутри UIWebView, и получить JavaScript, чтобы сделать

document.location='http://null/'+xCoord+'/'+yCoord; // Null is arbitrary. 

Тогда вы можете поймать, что используя метод делегата в UIWebView в

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 

И если request.URL.host (или что-то еще) isEqualToString: @ "null" принять соответствующее действие (и вернуть NO вместо YES). Вы даже можете добавить JS на каждую страницу, сделав что-то вроде:

- (void)webViewDidFinishLoad:(UIWebView *)webView { 
    [webView stringByEvaluatingJavaScriptFromString:@"window.ontouchstart=function(/* ... */);"]; 
} 

Надеюсь, это поможет?

+0

Могли ли вы сделать такой подход? – pgb

+0

Да, хотя и не с окном. Возможно, на прикосновениях. – Benjie

+0

Этот подход не работает должным образом. Кажется, что работать с clickable html-элементами можно только как изображения и ссылки. Кажется, что это не имеет никакого эффекта при нажатии на теги div, p, body, document :( – mana

0

Я бы попробовал переопределить -sendEvent: в UIWindow, чтобы проверить, можете ли вы перехватить эти события касания.

1

Следуя тому, что сказал Unfalkster, вы можете использовать метод hitTest для достижения того, чего хотите, но вам не нужно подкласса UIWindow. Просто поставьте это в подклассу веб-представления. Вы получите предупреждение о времени компиляции, но оно работает:

- (void)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 
    if (event.type == UIEventTypeTouches) { 

     // get location info 
     CGFloat x = point.x; 
     CGFloat y = point.y; 

     // get touches 
     NSSet *touches = [event allTouches]; 

     // individual touches 
     for (UITouch *touch in touches) { 

      if (touch.phase == UITouchPhaseBegan) { 
       // touches began 

      } else if (touch.phase == UITouchPhaseMoved) { 

      } 

      // etc etc 
     } 
    } 

    // call the super 
    [super hitTest:point withEvent:event]; 
} 

Надеюсь, что это поможет!

+1

Это странно ... По какой-то причине [event allTouches] всегда возвращает пустой набор –

+0

Обычно метод 'hitTest: withEvent:' возвращает ' UIView * '. Было ли это намеренно опущено? – ThomasW

+0

он сработает, если вы не вернете UIView из этого метода – malhal

7

Вы можете разместить UIView над своим UIWebView и обойти touchesDidBegin и т. Д., А затем отправить их на свой веб-просмотр. Пример:

Пользователь касается вашего UIView, который вызывает

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    // Execute your code then send a touchesBegan to your webview like so: 
[webView touchesBegan:touches withEvent:event]; 
return; 
} 

ваш UIView должен быть над WebView.

+0

это приложение iphone и его использование рамок UIKit, я полагаю, NSView предназначен только для разработки приложений Mac и доступен в AppKit Ракурс – Biranchi

+0

Жаль, что я имел в виду UIView –

+1

Я пробовал этот подход, и он не работает. –

2

Я только что нашел, что UIWebView проверяет, отвечает ли он на селектор - (void)webViewDidNotClick: (id)webBrowserView, как только один из них нажимает на область просмотра (а не на гиперреф или любую другую область, которая должна обрабатываться специально). Таким образом, вы можете реализовать этот селектор с кодом обработки :)

+0

По какой-то причине я не могу обнаружить двойной кран, используя этот метод. –

+0

Куда это должно идти? Я добавил его в свой делегат UIWebView, но это не сработало. – zekel

+1

Не на делегата, вы должны создать подкласс сам UIWebView и переписать этот селектор, такие как ' - (Недействительными) webViewDidNotClick: (ID) webBrowserView { [self.superview touchesEnded: ноль withEvent: ноль]; } ' – indexless

8

Если все, что вам нужно обрабатывать жесты, оставляя остальную часть функциональности UIWebView нетронутым, вы можете создать подкласс UIWebView и использовать эту стратегию:

в метод инициализации вашего UIWebView подкласса, добавить жест распознаватель, например:

UISwipeGestureRecognizer * swipeRight = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeGestureRightMethod)]; 
swipeRight.direction = UISwipeGestureRecognizerDirectionRight; 
[self addGestureRecognizer:swipeRight]; 
swipeRight.delegate = self; 

затем добавьте этот метод в класс:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{ 
    return YES; 
} 

Добавить й обработки вашего назначенный селектор класса, в данном случае «handleSwipeGestureRightMethod», и вы хорошо идти ...

+0

С распознающими признаками кажется самым чистым способом. – Tudorizer

+0

Это работает, спасибо. Только то, что мне было нужно. – wzbozon

43

Нет подклассов требуется, просто добавьте UITapGestureRecognizer:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapMethod)]; 
[tap setNumberOfTapsRequired:1]; // Set your own number here 
[tap setDelegate:self]; // Add the <UIGestureRecognizerDelegate> protocol 

[self.myWebView addGestureRecognizer:tap]; 

Добавить протокол <UIGestureRecognizerDelegate> в файле заголовка, и добавить этот метод:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
{ 
    return YES; 
} 
+1

Мне нужно было показать и скрыть навигационную панель навигационного контроллера одним касанием сверху веб-представления, и этот метод отлично работал для меня. – brindy

+0

Это хорошо для меня, спасибо! – tangqiaoboy

+0

отличный ответ! должны быть приняты. – aztack

3

Обработка жестов на UIWebView обсуждается в this Apple Developer forum thread.

Используя предоставленную информацию, в большинстве случаев или во всех случаях не требуется дополнительный просмотр, и, как упоминалось выше, переопределение UIWebView - это не тот путь.

CopyPaste наиболее важный пост в теме:

Это известная проблема. UIWebView имеет свои собственные UITapGestureRecognizers, и они находятся в частном подчинении самого UIWebView. Приоритет UIGestureRecognizer определяет, что жесты, прикрепленные к представлениям глубже в иерархии представлений, будут исключать их для супервизоров, поэтому жесты перехвата веб-просмотров всегда будут побеждать вас.

Если в вашем случае это нормально, чтобы ваш кран мог произойти вместе с обычным нажатием на веб-изображение, лучшим решением было бы реализовать gigesture UIGestureRecognizerDelegateRecognizer: shouldRecognizeSimultaneousWithGestureRecognizer и вернуть YES для других жестов жесты. Таким образом вы получите вызов обработчика крана, и веб-представление все равно получит его вызов.

Если вам нужно быть только один кран обработки вы будете иметь подкласс UITapGestureRecognizer, так что вы можете использовать однонаправленные переопределения в UIGestureRecognizerSubclass.h, вы можете вернуть NO из canBePreventedByGestureRecognizer: когда его спросили, если веб распознаватель жестов в раскрывающемся списке может помешать вашему.

В любом случае мы знаем об этом и надеемся облегчить его в будущем.

0

Если вы хотите, чтобы обнаружить свои собственные краны, но отключить краны в UIWebView, то вы можете использовать мое решение:

-(void)recursivelyDisableTapsOnView:(UIView*)v{ 
    for(UIView* view in v.subviews){ 
     for(UIGestureRecognizer* g in view.gestureRecognizers){ 
      if(g == self.ownTapRecognizer){ 
       continue; 
      } 
      if([g isKindOfClass:[UITapGestureRecognizer class]] || 
       [g isKindOfClass:[UILongPressGestureRecognizer class]] || 
       [g isKindOfClass:NSClassFromString(@"UITapAndAHalfRecognizer")]){ 
       g.enabled = NO; 
      } 
     } 
     [self recursivelyDisableTapsOnView:view]; 
    } 
} 


- (void)webViewDidFinishLoad:(UIWebView *)webView{ 
    [self recursivelyDisableTapsOnView:webView]; 

    //disable selection 
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"]; 
    // Disable callout 
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"]; 
} 
Смежные вопросы