1

I have a view with several lines drawn in it in different directions. I need to determine which line was tapped by the user and then respond accordingly.

I have a few different ideas in my head, but I want the best, most efficient way to do this...

Ultimately what makes the most sense to me is having each line in a separate view and treated like individual objects. If I did this would I need to position and rotate the view to be exactly where the line is so I know when it is tapped? If not I would assume the views will overlap each other and I would not be able to determine what line was tapped.

I hope I am making sense. Please let me know the best way to achieve this. Thanks!

digthewells
  • 657
  • 5
  • 17
  • 1
    If you are going with the one-view-per-line approach you might want to have a look at my answer here: http://stackoverflow.com/questions/5847876/whats-the-best-approach-to-draw-lines-between-views/5848118#5848118 – Nikolai Ruhe Mar 18 '13 at 16:53
  • Perfect! Exactly what I had in mind...If you want to put this as an answer I will accept it. – digthewells Mar 18 '13 at 20:33

2 Answers2

5

For me the best way to approach this is create UIView's as lines. If they are simply lines with plain colors just use the background view and set the CGRectFrame accordingly.

In order to react to touch event's without dealing with positions etc, create a touchEvent in the init method of the UIView like this:

UITapGestureRecognizer *onTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(lineClicked)];
 [self addGestureRecognizer:onTap];   

Declare the function inside the UIView class:

-(void)lineClicked {
  //You can check some @property here to know what line was clicked for example
  if (self.color == [UIColor blackColor])
      //do something
  else
      //do another thing

  // You can use a custom protocol to tell the ViewController that a click happened
  (**) if ([self.delegate respondsToSelector:@selector(lineWasClicked:)]) {
         [self.delegate lineWasClicked:self];
     }
}

(**) You will probably want to put some logic into your viewController after clicking in the line. The best way to approach this is to declare a @protocol in your CustomUIView.h file and pass self as parameter so the viewController knows who was clicked:

@protocol LineClikedDelegate <NSObject>
@optional
- (void)lineWasClicked:(UIView *)line; //fired when clicking in the line
@end

Finally, create a @property in your CustomUIView to point the delegate:

@property id<DisclosureDelegate> delegate;

And in the ViewController. When you create lines as UIViews set the delegate like:

blackLine.delegate = self.

Implement the method - (void)lineWasClicked:(UIView *)line; in the ViewController and you are set.

Pauls
  • 2,596
  • 19
  • 19
  • This is a good answer as well...The code for the transform is what was the most helpful in the answer by Nikolai Ruhe. I'm going to combine both of your suggestions for my solution. If there is a way I could accept both answers I would. Thanks! – digthewells Mar 18 '13 at 20:37
1

As requested I'm adding this as an answer:

You could use layers instead of views for displaying the lines. This is both efficient in drawing and allows for hit testing to determine which line has been tapped.

Here's code for the geometry calculations.

Community
  • 1
  • 1
Nikolai Ruhe
  • 81,520
  • 17
  • 180
  • 200