I'm developing an iOS 4.0 application.
I want to add a custom UIView over an image (UIImageView) to detect when user touches on some image's parts. I don't want to subclass UIImageView because I'm using SDWebImage package (or maybe I can subclass UIImageView+WebCache class to handle touches. If you tell me how).
This UIImageView will be inside an UIScrollView.
My idea is to detect when a user touches the image and notify viewController where user has touched. I don't need to detect moves or swipes or multitouches. Only one finger touch.
I'm creating my own UIView subclass to detect that using methods touchesBegan: touchesEnd:, etc. But I'm not sure if this is the best way to do that.
What do you think? Do you know a better approach?
You can add tapGestureRecognizer to your imageView in viewDidLoad, and then in handler method use CGPoint gestureLocation = [gestureRecognizer locationInView:self.imageView]; to check that tap was in selected area.
Related
I have array of UIImageView that printed on the main View (as subviews) in a matrix.
That UIImageViews interact while I am tap on them (work like a pixel when I touch one of them it turn on (move from black to green)
but I want to do it with swipe gesture so i can with one swipe trigger more than one "pixel" (UIImageView)
I found this for android triggering-multiple-buttonsonclick-event-with-one-swipe-gesture
and I wonder if there is something like that in ios with swift that recognise general touch (not tap or swipe) so I can looks for it.
The main purpose of all of this is to draw "shapes" on matrix of pixels with one swipe gestures.
If there is another way that you think will help I will be happy to here about it.
Many thanks
You are looking for the UIGestureRecognizer.
With this you can add many types of gestures, as swipe, touch..etc.
You can also get position, duration, and basically all the information about it.
You can check step by step tutorial in this link.
http://www.raywenderlich.com/76020/using-uigesturerecognizer-with-swift-tutorial
And also in the apple documentation.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIGestureRecognizer_Class/
i Manage to do the the swipe action using touchesMoved and touchesEnded
while the main idea is to invoke the UIIMageViews using the Coordinate of the touch and compare it to the to the UIImageViews Coordinates in the touchesMoved function
using flags to disable already edited UIIMageViews (while i am in the same touch session , the finger still on the screen) and refresh the UIImageViews to be editable again in the touchesEnded
func swipeTouches(touches: NSSet!) {
// Get the first touch and its location in this view controller's view coordinate system
let touch = touches.allObjects[0] as! UITouch
let touchLocation = touch.locationInView(self.view)
for pixel in pixelArrays {
// Convert the location of the obstacle view to this view controller's view coordinate system
let pixelViewFrame = self.view.convertRect(pixel.pixelImage.frame, fromView: pixel.pixelImage.superview)
// Check if the touch is inside the obstacle view
if CGRectContainsPoint(pixelViewFrame, touchLocation) {
// check if the pixel is Editable
if(!pixel.isEditable){
let index = pixel.index
pixelArrays.insert(updatePixel(index) , atIndex: index)
}
}
}
}
the only problem that i have now that if the swipe begin on one of the UIImageViews the touchesMoved function consider it the the view to looks for the coordinate and the other UIImageViews are not effected
my idea to solve it is to add layer on top all of the UIImageViews and disable the tap recognition that they alredy have and implement the tap also with the Coordinates way.
i will be happy to hear if there is another way to do it
Update :
i mange to solve the problem above by sort of what i wrote but instead of add another layer i disable the touch on all of the UIImageViews and invoke them using the Coordinates of the touch and them
many thanks
I have a UITableView with Custom Cells, when you touch the cell it adds a subview of a UIImageView.
I want the image to disappear after the user lifts there finger and i have a touchesEnded method on the UIImageVIew Subview but its never called.
It is only called if you lift your finger then press it down again and release it.
How do I get the method to be called on the original touch ended.
Im kinda going for what Snapchat does when you view images.
The reason the subview does not get the touchesEnded event is that it has not received the touchesBegan event: these two come in pairs - whichever view gets the touches began is going to get the touches ended. Your UIImageView could not get touchesEnded because it wasn't there at the time; it gets touchesEnded the second time around when you press down and release because it's there for both events.
There are several ways around this problem:
Process view removal in the same place where you process the addition of UIImageView - when you add the subview, store a __weak reference to it in a separate variable. When the view that added the UIImageView gets the touchesEnded event, go to that variable, and remove subview.
Keep UIImageView there, but control its transparency - rather than adding and removing the subvuew, start it as fully transparent, then make it opaque on touch, then make it transparent again on release.
Don't add the temporary UIImageView at all, use CALayer instead - it looks like you are adding the image view simply to host an image in it for a short time. There is a simpler way of doing it that's much lighter-way - using CALayer. This approach should be easier to implement, because the layer does not participate in handling of touch events.
Presumably the touchBegan method is on the Cell. That's when the subview gets added.
The touch has already been recorded by the Cell. The Cell's touchesEnded is what's going to be called when you lift up your finger. So that's where you need to handle removing the subview from the screen. Save a reference to the subview in the cell class, and if it is not equal to nil, remove it on touchesEnded. Simple as that.
The touch began on the Cell, before the subview existed. That same touch is going to end on the cell. You can't transfer the touch to another view while it's in progress.
When you touch that view and raise your finger, you should not drag your finger. If you did like that, then touchesCancelled: method will get called. So I think your view is too small to touch. If yes, then make a big View and try it again. It will work for you then.
Imagine a UIButton and a user who taps somewhere OUTSIDE the button and then slides onto it. If I want the button to detect such touches I can register it for any "Touch Drag Enter" events.
My question: is there some way to achieve the same for a UIScrollView?
I.e., I tap somewhere outside the scrollview, drag my finger onto the scrollview and as soon as I enter the scrollviews frame it starts panning? (Because by default it doesn't, I have to start my touch INSIDE the scrollview in order to pan)
If you want to do this, you will have to do a custom implementation using -touchesBegan, -touchesMoved, and -touchesEnded
The documentation for the UIResponder class (which all ViewControllers inherit from) that allows you to do this is here.
Hopefully you can figure out what to do from here. :)
As an extra hint, you will also most likely need to use this function
bool contains = CGRectContainsPoint(CGRect rect, CGPoint point);
Imagine a UIButton and a user who taps somewhere OUTSIDE the button and then slides onto it. If I want the button to detect such touches I can register it for any "Touch Drag Enter" events
Actually, no you can't. A UIControl will not get any of the control events unless the touch started in the control.
And that's for the same reason that you are seeing a similar effect with the scroll view. This is the entire basis of touch delivery on iOS. A touch "belongs" to the view that was initially touched.
After all, the runtime cannot possibly know that you are going to drag into the scroll view...
In MonoTouch how do I get a UIImage or UIImageView to fire off a delegate or something when clicked?
Exactly as Dimitris pointed out, you'll want to subclass UIImageView, and also ensure that the userInteractionEnabled flag is set to true.
I should point out that in most cases where people intend to have a UIImageView respond to interaction, these problems can just as easily be fixed by creating a UIButton instance with an image instead.
You have to subclass it (the UIImageView) and override one of TouchesBegan, TouchesMoved or TouchesEnded methods, according to what you want to do.
I have a UIButton (a subclass of one, actually) that interacts with the user via the touchesbegan: and touchesmoved: functions.
What I would like is for the user to be able to press down the button, drag their finger away, and have a second finger touch the button (all while the first finger has never left the screen).
Problem is, the second touch event never calls touchesbegan: unless the first finger has been released.
Is there some way to override this, or am I trying to do the impossible?
Have you tried setting multipleTouchesEnabled to YES?
If the interactions are using touchesbegan: and touchesmoved: then use a UIView instead of a UIButton. A button is a UIControl, and the way to interact with UIControls is
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents.
I'm not sure this two ways of getting events mix well.