Stop the UIButton being 'active' when finger is dragged outside its bounds - ios

How can I make the area of a UIButton in which the button still triggers the touchUpInside method smaller? When I press a button and drag my finger outside it (not lifting the finger), the area outside the button's bounds that keeps the button highlighted is pretty large.
I would like to achieve that the touchUpInside method would only get triggered if the finger (being dragged) is still inside the bounds of the button. Currently, if you press a button and, while not lifting your finger, you drag your finger outside the button, the area in which the touchUpInside method (instead of the touchUpOutside method) is called is pretty big. Can I limit the touchUpInside method to get called only if the finger is inside the bounds of the button?
Thank you.

I'm not pretty sure if I clearly understand your problem. So I would like to provide my 2 solutions:
The tricky one: you add another smaller subview to the button which being dragged, you turn off userInteraction of this button and reactivate it when you're done dragging.
Disable userInteraction for the stable button, you recognise if the two buttons touch each others base on their frame. Reactive userInteraction when you're done just like above.

Related

UINavigationItem: detect touch

Is it possible to detect a touch in a UINavigationItem?
I would like to create a little animation on an UINavigationItem when the user taps on it.
In other words:
my titles contain way too much text, hence I had to truncate them
I want the user to be able to read the full title text when he/she presses the navigation item
To do so I need to:
Detect the touch
Animate the String / text (I could have a timer to animate this, however I am wondering if there is already a built in function in iOS - do you know of any?)
UINavigationItem inherits directly from NSObject as johnryu stated in the comments, but instead of showing a title in your navigation bar you can do something more complex by adding a UIView in place of the title.
This view can be composed of a UILabel that will show the actual title and a transparent button.
The transparent button can have an action that triggers a popup with a full text for a "touch down" event or "touch up inside".
Or you can add to that view a simple tap gesture recognizer.
Try assigning a custom titleView to UINavigationItem. Make it a UIView with a label inside which you will have your text. In default state, the label would have same size as its superview. Make sure that the UIView has clipsToBounds set to YES/true.
Attach a UITapGestureRecognizer to either the label or the view to switch to "animating" state and back.
When entering animating state, make the label wide enough to have enough space for the entire string and animate its movement within the container, you can use NSString's boundingRectWithSize:options:attributes:context: to calculate the proper width.
Then just add an animation where label moves to the left until its right end is visible, probably best if it's repeating.

UIButton not receiving IBAction

I have what should be a very simple thing to do. I'm working on someone else's code, and I want to enlarge a UIButton because it's too small for users. I made it bigger in the storyboard, but when I run the app, the associated IBAction only gets hit when touching where the original rectangle was before I changed it. The button is still visibly larger, but only a portion of it receives touch events. Does anyone know what else might be at play here?
Note: there are no views on top of the new area that the button occupies, so I don't think the touches get picked up by a view on top.
Something to check is whether the UIButton has an ancestor view (i.e. a view in its superview chain) that is the smaller size. Hit-tests only pass down the view hierarchy if the touch is contained within the view so a smaller superview will stop the touches outside its bounds, even if the touch is inside the button.
Is the IBAction hooked up to "touch up inside" in Interface Builder/Storyboard? I've made mistakes where I hook it up with a different kind of event, which exhibits behaviours like you're experiencing.
Found the issue. There was a view being programmatically added on top of the button. It's origin.x was being hardcoded to where the buttons width use to end.

how to stop a button from overruling a drag gesture

I have an image that can be dragged on the screen along the y axis and it works brilliantly, but when when I place a button on top of the image which tracks the image (moves with the image, so it's always on top), when trying to drag the button (as it's on top of the image I want to drag), the image won't budge. The button is just cancelling out the drag gesture. How do I prevent this from happening while still enabling the user to press the button? I'm using a UIPanGestureRecognizer
I've tried various ways but they don't work. Go steady with me please, I've very new to developing and this is my first App Store app :)
Thanks
I am not sure if these will solve your issue but you can try both of them and see which one works.
1) Make the UIButton a subview of the UIImage so that it inherits the gesture recognizer.
2) Add a pan gesture recognizer to the UIButton with the same handler as the image.

UIscrollView swipe gesture + UIButton finger down effect on iOS

I'm trying to come up with a UISCrollView in paging mode, where each page shows an image of a product and, besides being able to swipe between pages, I'd also like for the product image to switch to a "down" version of it when a specific product/page is tapped.
So far I tried the following:
1 - adding UIButtons as the pages of the scrollview: obviously, this way I can have the images switch to their "Selected" version on finger down, but the buttons, taking up the whole page, prevent the scrollview from detecting the swipe gesture.
2 - adding UIVIews instead of buttons, and an UITapGestureRecognizer: this way I can tap an image to select a product and the recognizer also lets the gesture pass on to the scrollview, allowing for swiping too. But the problem with this approach is that I can't switch images to their "selected" versions when the user touches them, since the tap recognizer only reports UIGestureRecognizerStateEnded.
Any ideas as to how to get both the button up/down and scrollview swipe behaviors?
Scrap everything (well not everything, but you get the gist). No gesture recognizers no nothing. I recently had this problem too, having mounted a UIView on a UIScrollview that needed to have some interactive elements in it. The solution, UIView's friggin awesome property called exclusiveTouch. Exclusive touch takes all of the events from the scrollview, and ignores them if the event is inside the UIView, then passes them directly to your view. And because UIButton inherits from UIView, all you need is self.button.exclusiveTouch = YES
Pretty cool, huh!?

Is it possible to remove the delay of UIButton's highlighted state inside a UIScrollView?

I have noticed a slight delay on the highlighted state of a UIButton when touched down if it is inside a UIScrollView (or a table view). Otherwise, the highlighted state is pretty much instantaneous.
I surmise this must be by-design to provide a chance for user to scroll. But it just seems like the button is unresponsive to me. Is there a way to fix this?
Indeed, it's a design choice. It needs this small time to differentiate a scroll (panGesture) from a tap. If you eliminate this delay, then the user won't be able to scroll if he places the finger on top of the button, which is not good user experience.
Because a scroll view has no scroll bars, it must know whether a touch signals an intent to scroll versus an intent to track a subview in the content. To make this determination, it temporarily intercepts a touch-down event by starting a timer and, before the timer fires, seeing if the touching finger makes any movement. If the timer fires without a significant change in position, the scroll view sends tracking events to the touched subview of the content view.
from the UIScrollView Documentation
I wouldn't recommend disabling the delay, but if you insist, you can set it in interface builder (select the Scroll View, and on the right panel, right under "Bounces Zoom"), or using this code:
scrollView.delaysContentTouches = false

Resources