9

I have a subclass of UIView on top of a UITableView. I am using the UITableView to display some data and, at the same time, I would like to overlay an animation that follows the finger (for instance, leaving a trail).

If I get it right, I need the touch events to be handled both by the UIView subclass and the UITableView. How can I do that? Is it possible to have, ie, touchesMoved being triggered on the UIView subclass and then on UITableView?

Thank you so much for any help.

ios-lizard
  • 816
  • 1
  • 12
  • 18

3 Answers3

12

The way I have solved this problem is in a way that is not that clean, but it works. Please let me know if there's a better way to do this.

I have overridden hitTest for my custom UIView so that it directs touches to the UITableView underneath. Then in the UITableView I am handling the gestures through touchesBegan, touchesMoved, etc. There I am also calling touchesBegan on the UIView.

In this way touches are handled by two views. The reason why I am not doing the other way around (having UIView's touchesBegan calling UITableView's touchesBegan) is that gestures recognizers on the UITableView would not work.

UIView subclass' hitTest

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    // tview is the UITableView subclass instance
    CGPoint tViewHit = [tView convertPoint:point fromView:self];        
    if ([tView pointInside:tViewHit withEvent:event]) return tView;

    return [super hitTest:point withEvent:event];
}

UITableView subclass's touchesBegan

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:touch.view];
    // ....

    // view is the UIView's subclass instance
    [view touchesBegan:touches withEvent:event];
}
ios-lizard
  • 816
  • 1
  • 12
  • 18
1

No, you cann't do it implicity. Event Delivery chapter says

The window object uses hit-testing and the responder chain to find the view to receive the touch event. In hit-testing, a window calls hitTest:withEvent: on the top-most view of the view hierarchy; this method proceeds by recursively calling pointInside:withEvent: on each view in the view hierarchy that returns YES, proceeding down the hierarchy until it finds the subview within whose bounds the touch took place. That view becomes the hit-test view.

So, when window finds touched view it returns YES. Only one view can handle touches at the current moment.

But if you need to handle event for UITableView then handle it for UIView! You can convert touched point to required coordinates with – convertPoint, – convertRect functions, add subview to UITableView and move it depends on coordinate, and a lot of another things.

beryllium
  • 29,214
  • 15
  • 99
  • 123
  • This could definitely work. I might have multiple elements "under" the UIView subclass... do I need to repeat the process for all those elements? Also, do I need to convert the coordinates to get the global coordinates, right? Thank you. – ios-lizard Dec 03 '11 at 21:39
  • I have done as you have suggested but I cannot scroll the UITableView anymore. Do you know why? Thank you – ios-lizard Dec 04 '11 at 23:51
0

UITableView relays unhandled touch events to UIView. (Google "responder chain") UITableView Documentation

So, you can handle your touch events in UIView only. So. In your UIView

  1. touchesstart - do initialization stuff

  2. touchesmove - draw tail on UIView (Use timers/delayedresponse to desable points so that it would look like a trail)

  3. touchesend - do remaining stuff

Hope this helps.

hrishikeshp19
  • 7,748
  • 21
  • 73
  • 135
  • Thanks for your reply but I am not sure I fully understand (in particular I do not understand the meaning of the first sentence). I know I can draw the trail in UIView but I'd still need to "pass on" the touch events to the UITableView (to scroll, select, etc). Sorry if I have misunderstood. – ios-lizard Dec 03 '11 at 21:38
  • In Objective-C, there is something called responder chain. If a class does not handle particular events, those are needed to be handled by its Super class. If no class handled that event, ultimately that event is handled by NSObject. So, in your case as UIView is superclass of UITableView, you can respond UITableView events from UIView. – hrishikeshp19 Dec 04 '11 at 00:18
  • I apologize if I am not particularly expert with Objective-C... could you please make an example of how this might apply to might case? Should I have the UITableView handle of the gestures and then pass them on to the superclass? How? – ios-lizard Dec 04 '11 at 23:54
  • Do not handle events in UITableView at all, only handle events in UIView. – hrishikeshp19 Dec 05 '11 at 23:02
  • What do you think of the answer I have just posted? – ios-lizard Dec 08 '11 at 21:40
  • You should handle events in UIView. I guess thats what you have done. – hrishikeshp19 Dec 08 '11 at 21:54