Наблюдение за жесткими касаниями касания в UITableView
Я пытаюсь реализовать ввод/вывод поверх UITableView, я рассмотрел несколько методов, включая этот:
Подобный вопрос
Но пока я могу создать объект UIViewTouch
и наложить его на свой UITableView, события прокрутки не будут переданы в мой UITableView, я все равно могу выбрать ячейки, и они будут правильно реагировать, инициируя переход к новому объекту ViewController. Но я не могу прокручивать UITableView, несмотря на то, что передал прикосновенияBegan, touchsMoved и касается событийEnded.
Ответы
Ответ 1
Это кажется классической проблемой. В моем случае я хотел перехватить некоторые события над UIWebView, которые нельзя подклассифицировать и т.д. И т.д.
Я обнаружил, что лучший способ сделать это - перехватить события с помощью UIWindow:
EventInterceptWindow.h
@protocol EventInterceptWindowDelegate
- (BOOL)interceptEvent:(UIEvent *)event; // return YES if event handled
@end
@interface EventInterceptWindow : UIWindow {
// It would appear that using the variable name 'delegate' in any UI Kit
// subclass is a really bad idea because it can occlude the same name in a
// superclass and silently break things like autorotation.
id <EventInterceptWindowDelegate> eventInterceptDelegate;
}
@property(nonatomic, assign)
id <EventInterceptWindowDelegate> eventInterceptDelegate;
@end
EventInterceptWindow.m:
#import "EventInterceptWindow.h"
@implementation EventInterceptWindow
@synthesize eventInterceptDelegate;
- (void)sendEvent:(UIEvent *)event {
if ([eventInterceptDelegate interceptEvent:event] == NO)
[super sendEvent:event];
}
@end
Создайте этот класс, измените класс вашего UIWindow в MainWindow.xib на EventInterceptWindow, затем где-то установите eventInterceptDelegate на контроллер вида, который вы хотите перехватить события. Пример, который перехватывает двойной щелчок:
- (BOOL)interceptEvent:(UIEvent *)event {
NSSet *touches = [event allTouches];
UITouch *oneTouch = [touches anyObject];
UIView *touchView = [oneTouch view];
// NSLog(@"tap count = %d", [oneTouch tapCount]);
// check for taps on the web view which really end up being dispatched to
// a scroll view
if (touchView && [touchView isDescendantOfView:webView]
&& touches && oneTouch.phase == UITouchPhaseBegan) {
if ([oneTouch tapCount] == 2) {
[self toggleScreenDecorations];
return YES;
}
}
return NO;
}
Дополнительная информация здесь:
http://iphoneincubator.com/blog/windows-views/360idev-iphone-developers-conference-presentation
Ответ 2
Нимрод писал (а):
где-то установите eventInterceptDelegate на контроллер вида, который вы хотите перехватить события
Я не сразу понял это утверждение. В интересах кого-то, у кого была такая же проблема, как и я, способ, которым я это делал, заключался в добавлении следующего кода в мой подкласс UIView, который должен обнаруживать штрихи.
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Register to receive touch events
MyApplicationAppDelegate *appDelegate = (MyApplicationAppDelegate *) [[UIApplication sharedApplication] delegate];
EventInterceptWindow *window = (EventInterceptWindow *) appDelegate.window;
window.eventInterceptDelegate = self;
}
- (void) viewWillDisappear:(BOOL) animated
{
// Deregister from receiving touch events
MyApplicationAppDelegate *appDelegate = (MyApplicationAppDelegate *) [[UIApplication sharedApplication] delegate];
EventInterceptWindow *window = (EventInterceptWindow *) appDelegate.window;
window.eventInterceptDelegate = nil;
[super viewWillDisappear:animated];
}
- (BOOL) interceptEvent:(UIEvent *) event
{
NSLog(@"interceptEvent is being called...");
return NO;
}
Эта версия interceptEvent:
представляет собой простую реализацию обнаружения с фиксированным увеличением. NB. Некоторый код был взят с начала разработки iPhone 3 от Apress.
CGFloat initialDistance;
- (BOOL) interceptEvent:(UIEvent *) event
{
NSSet *touches = [event allTouches];
// Give up if user wasn't using two fingers
if([touches count] != 2) return NO;
UITouchPhase phase = ((UITouch *) [touches anyObject]).phase;
CGPoint firstPoint = [[[touches allObjects] objectAtIndex:0] locationInView:self.view];
CGPoint secondPoint = [[[touches allObjects] objectAtIndex:1] locationInView:self.view];
CGFloat deltaX = secondPoint.x - firstPoint.x;
CGFloat deltaY = secondPoint.y - firstPoint.y;
CGFloat distance = sqrt(deltaX*deltaX + deltaY*deltaY);
if(phase == UITouchPhaseBegan)
{
initialDistance = distance;
}
else if(phase == UITouchPhaseMoved)
{
CGFloat currentDistance = distance;
if(initialDistance == 0) initialDistance = currentDistance;
else if(currentDistance - initialDistance > kMinimumPinchDelta) NSLog(@"Zoom in");
else if(initialDistance - currentDistance > kMinimumPinchDelta) NSLog(@"Zoom out");
}
else if(phase == UITouchPhaseEnded)
{
initialDistance = 0;
}
return YES;
}
Изменить: хотя этот код работал на симуляторе iPhone на 100%, когда я запускал его на устройстве iPhone, я столкнулся с странными ошибками, связанными с прокруткой таблицы. Если это также случается с вами, то заставляйте метод interceptEvent:
возвращать NO во всех случаях. Это означает, что суперкласс также обработает событие touch, но, к счастью, это не нарушило мой код.