Button as subview, click start superview - ios

I have a button that will be a subview added to a another UIView, like Path does. The idea is that this button will remain static in one corner of the screen while the user can scroll through the UIVIew behind it.
I am handling the pointsinside method, to know when a user clicks whether it was on the button or the super view.
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
return CGRectContainsPoint(customButton.frame, point);
}
My question is, if the user does click in the button, I need to open up a UIImagePickerController, which is a property of the superview. how can I do that on the superview though?
Thanks.

you should add an event to button by addTarget method.

If the button is Guaranteed (and I mean that, because it will crash without a guarantee) to be the subview of the superview you mention, then casting self.superview will allow you access to it's UIImagePickerController property. A much safer implementation would use a weak reference to the owning superview, then property manipulation would fail gracefully if you tried to re-use the button without it's superview.

Related

iOS - change animation when user taps screen

Lets say that i have an animation - an image is going from left side of the screen to the right. I would like to make it a little bit interactive - when user taps on a screen i want to change direction of image movement. Whats the best approach to implement it?
What I do in some cases is take the main view of the View Controller, in Storyboard, and change the class type of that UIView to UIControl.
In the code that is accessed as MyViewController.view, which you can write:
var viewAsControl = myViewController.view as UIControl
In Swift or some equivalent of that.
The UIControl subclass of UIView is the hierarchical layer (class) that adds the action/target facilities to a view. For example, UIButton is a UIControl, because it generates events (actions), and it is also a UIView so it can be added as a subview.
Then from the Connections Inspector, accessed via the far right Icon of the far right panel (that is, the panel to the right of the storyboard editor window), I'd select the Touch Up Inside event type or some other event and drag it to an #IBAction tagged function I'd add to the View Controller's source code, to receive the tap event. From that tap notification, you can cancel the current animation and add a new one, etc...
Alternatively, you can create an IBOutlet for the view if you've turned it into a UIControl in IB, and use the addTarget() method to assign an action handler for a specific event, e.g. to make it call a function in your code.
Either way the effect will be that any time the view is tapped, it will generate the event for you to respond to

iOS - View that handle taps, but let swipes go through to the superview

I have an app with quite a complex UI, there's a big UIView called the cover with a UITableView underneath it. The tableView is configured with a tableHeaderView of the same height as the cover. As the tableView scrolls up, the cover moves up the screen (with various fancy animations) using a UIScrollViewDelegate. To allow users to scroll the tableView by swiping the cover, I've overridden the - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event method to always return false.
I've now added some UIButton views to the cover. I've managed to make them respond to taps by changing the way I've overriden the pointInside method like this:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
BOOL isInside = [_directionsButton pointInside:[_directionsButton convertPoint:point fromView:self] withEvent:event];
return isInside;
}
The only problem now is that if you start a swipe gesture on the button, it's caught by the button and the tableView doesn't scroll. I want to be able to ignore swipe gestures on the button (so really let them pass to the view below).
Normally, I would just make the cover view the tableHeaderView, which seems to handle this kind of behaviour really well. However, I can't do this here, due to some unique animations done on the cover as the table scrolls.
Did you tried identifying the Gestures using Gesture Recognisers and doing action method that is to be called when the specified gesture is detected?
Please check this link. This may help you for that.

Transfer touches to subView

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.

How to detect "Drag Enter" on UIScrollView

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...

iOS x coordinate of finger when tapping on UIButton

I have a UIButton. How can I get the x-coordinate of the finger when the user taps on said button. I'm thinking it will involve touchesBegan but how do I only get the value if the "touchesBegan" occurred on the button? And if there is a way (without just monitoring the x, y, width, and height of the button and checking if my touch was in that region) will I need to disable the button's user interaction so the code can handle it and not the built in xib stuff. Thanks!
A “tap” is generally considered to be a touch-down inside the button followed by a touch-up inside the button. You need to figure out whether you want the touch-down-inside event or the touch-up-inside event (or both).
Let's say you want the touch-down-inside event. Write a method like this in your view controller:
- (IBAction)buttonWasTouched:(UIButton *)button forEvent:(UIEvent *)event {
NSSet *touches = [event touchesForView:button];
NSLog(#"button:%# touches:%#", button, touches);
}
If you're creating the button in a nib, control-click the button and connect its “Touch Down” outlet to the buttonWasTouched:forEvent: action on your view controller (which is probably File's Owner).
If you're creating the button in code, send an addTarget:action:forControlEvents: to the button to connect its UIControlEventTouchDown event to the view controller's buttonWasTouched:forEvent: action.
If you want to catch the touch-up-inside event, connect its “Touch Up Inside” outlet in the nib, or use UIControlEventTouchUpInside in code.

Resources