Domanda

I have several UIViews that have somewhat complex shapes that I have drawn via each UIView's drawRect: method. I have saved a reference to the path (via a CGPath property) and I am using that in my touches methods to detect whether or not the touch is actually within the path or shape (CGPathContainsPoint). Because of the shapes, there are areas of the view that are transparent (obviously anything that is not square/rectangular will have areas of transparency, assuming the view's backgroundColor property is set to clearColor or some such).

For situations (which occur often) where the view's end up on top or overlapping one another, I am testing in the touches methods (touchesBegan etc) to see if the touch is actually within the CGPath or shape. If the touch is not within the shape, I am forwarding the touch to the next view underneath to see if it in turn passes that requirement.

Sadly though (and much to my dismay), this does not behave the same as a touch actually being bound to the view. I have worked around this issue in every way except for one in particular. Each view is using a UIRotationGestureRecognizer. But if a touch originates in another view's transparent area, and that view forwards that touch to a view underneath it, the UIGestureRecognizer is never triggered.

I have looked at this from every angle I know how to. I have tried to think of some way of actually reassigning or binding the touch to the appropriate view, but I don't know if this is even possible. So long as the views are just forwarding the touch to another view, the touch will remain bound to the original view that received the touch first.

I wonder if you can do something this way by subclassing UIApplication or UIWindow and override the sendEvent:" method. I'm not sure exactly what control Apple might give you in this. I can't afford to do anything that might be accessing private API's. I really just need some way to reassign the touch so that the view thinks the touch belongs to it.

Any ideas?'

È stato utile?

Soluzione

You could do this by either subclassing UIView or subclassing UIGestureRecognizer.

Subclassing UIView

By subclassing UIView (or any of its subclasses) and overriding

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

you can decide what points are considered to be inside your view. For points outside the path you simply return NO

Subclassing UIGestureRecognizer

By subclassing UIGestureRecognizer (or any of its subclasses) and overriding

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

you can decide what touches the gesture recognizer should recognize. For all touches outside the path you should call (but not subclass)

- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent *)event

on yourself.


Point inside of path?

In either case you need to know if the points is inside of the path that you say you've stored.

If the paths are already stored as UIBezierPaths you can simply call

- (BOOL)containsPoint:(CGPoint)point

On the bezier path. The point or the touch may need to be converted to the same view coordinates as the path by calling

- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view

or

- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view

On your view.

If the path is stored as a CGPath you can create a UIBezierPath from it using

[UIBezierPath bezierPathWithCGPath:CGPath]; 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top