Should "clickable" areas in iOS be buttons? - ios

Should "clickable" areas in iOS be buttons or is it ok to just use a generic UIView, UIImage and so on?
Say i have a block of text with an icon, borders, shadows and so on. It looks like a bilboard. What would be the best way to implement that? Using a custom UIButton and just add subviews to it or creating just a generic UIView?
Any thoughts appreciated!

You can simply add UIGestureRecognizers to your UIView and handle them. You can find the documentation here and a tutorial here.

Probably for a view containing multiple subviews, you want to use a UIView subclass. While a UIButton would be OK for adding views, state changes, enabling/disabling may do wonky things to the view as a whole (including the subviews). Using your own UIView subclass will ensure that what gets displayed doesn't get toyed around with by any state changes, giving you complete control. You can override
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
to intercept touches on your custom view. If you're going to do this, remember that the userInteractionEnabled field MUST be set to true.
An additional note: you mentioned shadows as one of the elements in your question. If you're using CALayer to do this, definitely avoid using UIButton, as it's set of layers to handle different states is quite complex.

If the target area is big enough, you could place a transparent UIButton (switch the button type to custom, but don't supply an image) over the top of the clickable view to intercept the taps.

Related

Handling a touch event across multiple subviews

I am new to iOS development. I have a custom drawn view which is composed of multiple subviews covering the target area on screen. Specifically this is a board game like chess where I used a view for each square. The squares are created as subviews on a UIView. There is one UIViewController for this. From what I read, I have to have touchesBegan, touchesEnded etc calls in my UIView to handle these. But none of these functions are getting called. I added these calls on the base view and all the subviews. So -
How do I simulate these touch events in the iOS simulator? A mouse click is not calling the touchesBegan ,touchesEnded calls on any view.
Ideally I would like to handle these in the UIViewController because I want to run the touch through some logic. Is that possible? How do I achieve it?
Please refer THIS
It is tutorial in Apple sample codes it describes how to handle touches very nicely.
Just run the sample code and go through description you will get clear idea how touches work un iOS.
Turns out when I add the view programmatically and not through the storyboard the userInteractionEnabled variable is set to NO by default. After setting it up, I get the touchesEnabled call getting called in the view.
Check this :
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if(![touch.view isKindOfClass:[yourView class]])
{
}
}
Hope this will help.

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.

How to use touches began?

So I'm writing an app in which I have a custom UIView which contains a UIScrollView which contains a series of UIImageViews. I want to make it so that when I touch one of the UIImageViews within the UIScrollView, an event happens (for now, let's just say I print an NSLog() or something).
I know that there exists this function:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
But I'm not entirely sure how to use it. Which UIView should implement this function? Where would I call it exactly? Or does it get called automatically when something is touched? How do I find the correct UIImageView?
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event is already implemented by UIView (actually implemented by the UIResponder superclass, and by default it does nothing). this method is there for you to override in subclasses to do whatever you want to do.
this method is indeed called automatically whenever touches begin within the views boundary.
In your case using a UIButton with an image may be better.
instead of using touchesBegin: , subclass UIImageView, add Tap gesture to this new Class and use this Class instead of the ImageViews you are using on scrollView.

Touch Event in Scrollview ios

Scrolling is not stopping when I touch over the contact labels. How can I add this feature for this open project.
https://www.cocoacontrols.com/controls/scroller
If I touch the background, it is working perfectly. I would like to have same thing for the contacts labels too.
Basically, it uses scrollview and there is an animation while scrolling. I can not make stop it when I touch over the labels.
Any help is welcome.
Though I am unfamiliar with the scroller project, maybe this can at least get you on the right path.
The likely reason why touching the contacts isn't stopping the scrolling is because the labels are receiving their own touch events for their own purpose, which is probably the desired behavior, since you would probably want to touch one of the contacts and have it do something. It's possible that since the touch events are being intercepted in that view for that reason, that you can not interact with the scroll view using the same event.
You may need to set the userInteractionEnabled property of the view surrounding each contact to false until the scrollview has stopped scrolling. There are several ways you could do this, but this might be enough to get you started on a good solution.
My condition may be similar with yours.
I build a scroll view in storyboard and a view is added to the scroll view.All of my UI component was placed in the content view including two textfields.Generally speaking, I would like to rewrite the - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event method, and end editing actions in this view.
However,rewrite the method in scrollview's superview has little help.But when I subclass the view and rewrite that method in this subclass Every thing is OK.
According to my condition ,subclass the view and rewrite - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event.Process the logic in view level.

Regarding views and gesture recognizers

So I have somewhat of a silly requirement, I am trying to put an "easter egg" type function into the app, where if you tap a certain area 3 times, a special view controller comes up with some silly pictures, etc...
I created a UIView and added a UITapGestureRecognizer to it. but when I set the background color to "clear" (to effectively hide the view) it doesn't respond to the tap.
How can I make the view "invisible" and yet still active? I want to use a UIView because I've set it to respond to multiple taps, which is why I didn't use a UIButton
If it is the case where alpha < 0.1 starts ignoring events (I never heard that either), you could drop in a 1x1pt custom view/control where the 1px showing has a color that matches its background and has an alpha > 0.1,
Then override:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
to return YES for a larger area than the 1x1 pt.

Resources