could anyone tell me how to place a translucent black mask over the whole screen, but with the area of a particular UIView being excluded? I want to use this mask over a UITextField, which calls resignFirstResponder when the outside part of the textfield is tapped.
The subview tree would be like:
UIWindow
|-UIView
| |-UITextField
|
|-Mask
Thanks,
You can use the:
- (void)bringSubviewToFront:(UIView *)view
And send the UITextField to the front after you add the black mask view.
UPDATE
Ok this are the steps to do it (you can see the apple example for UIGestureRecognizers for more)
create a mask view (programmatically or with IB) and call it "maskView".
create a gestureRecognizer and add it to the maskView.
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFrom:)];
recognizer.delegate = self;
UIImageView *maskView = [[UIImageView alloc] init];
[maskView addGestureRecognizer:recognizer];
you will need to set your view controller as the delegate for "UIGestureRecognizerDelegate"
#interface YourViewController : UIViewController <UIGestureRecognizerDelegate>
add the maskView to your ViewController when you want to mask the screen. and then move the text field above the mask.
[self.view addSubView:maskView];
[self.view bringSubviewToFront:textField];
set this 2 functions:
in the first one you can set the action if the user touches the mask
- (void)handleTapFrom:(UITapGestureRecognizer *)recognizer {
//resign the first responder when the user taps the mask
//you can remove the mask here if you want to
}
in the second one you tell the app not to receive touches from the textField
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// Disallow recognition of tap gestures in the segmented control.
if ((touch.view == textField)) {//checks if the touch is on the textField
return NO;
}
return YES;
}
Hope it make some sense
shani
Related
I have a question - is there any possibilities in iPhone to make UITapGestureRecognizer respond the tap only on a part of UIImageView. Actualy, the problem is as follows - there is an UIImageView with gesture recognizer add and some part of these UIImageView is covered with other View. When tapping on this other View, UIImageView recognizes the tap. How this problem can be solved?
I'm not sure I understand your question. Do you want the gesture recognizer to be triggered when the view which overlaps the image view is tapped? If so, I guess you could just add the gesture recognizer to the overlapping view.
If you have two overlapping views and want to only handle the touch if the overlapped part was touched, I suggest adding the tap gesture recognizer to the main view and check if the overlap was touched.
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureRecognizerTriggered:)];
[self.view addGestureRecognizer:gestureRecognizer];
}
- (void)tapGestureRecognizerTriggered:(UITapGestureRecognizer *)gestureRecognizer
{
CGPoint location = [gestureRecognizer locationInView:self.view];
if (CGRectContainsPoint(self.frontView.frame, location) &&
CGRectContainsPoint(self.backView.frame, location))
{
// Handle touch
}
}
If you want to handle the touch if the touch happens in the front CGRectContainsPoint(self.backView.frame, location) from the conditional statement.
I have a view controller and I have created an another view in same view controller and added it as a sub view.When a button clicked the subview will appear and it takes half of the screen.How can I close the subview when user touched the superview(main view in background) ?
You can use a gesture recognizer and on a single tap action on the superview call removeFromSuperview on the subview.
In your viewDidLoad add something like this:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[singleTap setNumberOfTapsRequired:1];
[mainView addGestureRecognizer:singleTap];
And then add the function:
- (void) handleSingleTap: (id) sender
{
[secondView removeFromSuperView];
}
For more control of when you want the subview to be removed, you could override the mainViewController's responder method like so:
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[subview removeFromSuperView];
}
This way you can actually see where in the screen the user tapped, and respond accordingly.
i am making a chat application, and in the chat window there are uilabels in uitableviewcells. initially the keyboard will be present but when the user touches on any place on uitableview, i will make the chat window as fullscreen (dissappearing keyboard).
i cant find a way/trick to accomplish this.
i have tried the following method: by using tableview:didselectrowatindexpath, i am able to do it but, user needs to press on an existent uitableviewcell. but i want to understand the press even when uitableview is empty..
note: my chat tableview is interactive e.x. some rows will include image button which need to be pressable, so i cant just put an invisible button onto uitableview.
thank you for your thoughts
Aytunc Isseven
What you want to do is add a gesture recognizer to the UITableView that responds to the appropriate gestures. I would recommend against using UITapGestureRecognizer as the UITableView is already using taps for selecting the cells, so you might want to try the UILongPressGestureRecognizer. I put together a small sample of how you can do this as follows:
In my viewDidLoad I did the following:
UILongPressGestureRecognizer *gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPressFrom:)];
[self.tableView addGestureRecognizer:gesture];
and the handleLongPressFrom: is as follows:
- (void)handleLongPressFrom:(UILongPressGestureRecognizer *)recognizer {
NSLog(#"handleLongPressFrom: %#", recognizer);
// Add real code here
}
The full list of gestures can be found here.
Oh, if you did want to still use tap, check out this stack overflow question. I don't know if the method presented works fully, but it'd be a good place to start.
Using UITapGestureRecognizer with a UITableView:
Okay, since the tap gesture seems to be the correct one for your use case you can try and do the following. Step 1 is to set up the gesture recognizer as I listed above using the tap gesture instead of the long press gesture.
The code in viewDidLoad is very similar with an important addition ...
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFrom:)];
// we need to set the gesture delegate so we can allow the tap to pass through to the
// UITableViewCell if necessary.
gesture.delegate = self;
[self.tableView addGestureRecognizer:gesture];
The handleTapFrom: function is pretty much the same with just the different gesture recognizer as the parameter.
- (void)handleTapFrom:(UITapGestureRecognizer *)recognizer {
NSLog(#"handleTapFrom: %#", recognizer);
// Add real code here
}
The major changes to this approach is that we need to implement the UIGestureRecognizerDelegate protocol. Since our goal is to allow the tap gesture to pass through the UITableView to it's subviews (i.e. the UITableViewCell and it's components) we need to implement the gestureRecognizer:shouldRecieveTouch: function. The following implementation should cover what you are attempting.
#pragma mark UIGestureRecognizerDelegate methods
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// If the view that is touched is not the view associated with this view's table view, but
// is one of the sub-views, we should not recognize the touch.
if (touch.view != self.tableView && [touch.view isDescendantOfView:self.tableView]) {
return NO;
}
return YES;
}
The isDescendantOfView: function returns YES if the view it is testing against is the same as the view doing the testing, so we need to accommodate that case separately. You can generify this function by using gestureRecognizer.view instead of self.tableView, but I didn't think it was necessary in this case.
The trick is to make your viewController put a tap recognizer on the view but make it always opt out by returning NO from the delegate method "gestureRecognizerShouldBegin". That way gestureRecognizerShouldBegin gets called for every touch on the view, but you don't interfere with the normal event handling of the table.
- (void)viewDidLoad {
[super viewDidLoad];
[self detectTouchesOnView:self.tableView];
}
- (void)detectTouchesOnView:(UIView*)theView {
UITapGestureRecognizer* tapR = [[UITapGestureRecognizer alloc]initWithTarget:nil action:nil];
tapR.delegate = self;
[theView addGestureRecognizer:tapR];
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
// React to the UITableView being touched E.G. by hiding the keyboard as below.
[self.view endEditing:YES];
return NO;
}
I have a View With Navigation Bar
Actually I have taken a Image View and Put it on a navigation bar....
As I want Button Not at right or Left but at somewhere on the navigation bar
By this method I can recognize touch on view but can not recognize touch on Navigation Bar ?
Can I change anything...
In this method...
Why?
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event {
CGPoint p;
p.x=0;
p.y=0;
p = [[touches anyObject] locationInView:self.nvbrCalculateBar];
NSLog(#" %f",p.x);
if(p.x==0 && q.x==0)
{
}
else
{
//Load View
}
}
You can add a UITapGestureRecognizer to your UIImageView and that should do the trick
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapEvent:)];
[yourImageView addGestureRecognizer:tap];
[tap release];
- (void)tapEvent:(UITapGestureRecognizer *)gesture {
//Do whatever you need when user taps the imageView
}
Also set the userInteractionEnabled of the imageView to YES to be able to receive the gesture recognizer events.
Hope this helps.
The UINavigationBar itself is not set to return touches, since I believe its not part of the actual UIView (for which the touchesBegan) method applies. Instead, you can push various items onto the nav bar (e.g. buttons) which you can define interactions for.
See its reference here.
USer Interaction Must be enabled of UINavigation Bar Property, And then Apply touch method..
Can you try:
[imageView setUserInteractionEnabled:NO];
This should prevent your imageview to cancel the touches.
What I want:
In an iPhone app, I'd like to show information in a tableView.
In each cell, the text is like: John recently listen to music abcdefg.mp3.
and if needed, the text can have two lines.
In the text, a.mp3 should be clickable so when the user touches the abcdefg.mp3 part, another page will be invoked. When user touches abcdefg.mp3, it will also have some effects, just like touching a button.
What I do:
I calculate the frame of the text, and I use a UIButton for abcdefg.mp3.
My Problem:
Sometimes abcdefg.mp3 may be in multiline, like:
abc is at the end of the first line
defg.mp3 is in second line.
What should I do in this case?
I've already searched about: Create tap-able "links" in the NSAttributedString of a UILabel?
However I think it is not suitable here as the clickable text is all in one line in the sample.
The most simple way is to just add a gesture recognizer to the actual view (be it a UILabel or some custom view of your own). In order for the gesture recognizer to work, the view must be set userInteractionEnabled.
Here's an example, assuming that your label view (or whatever it is) is called labelView:
UITapGestureRecognizer* gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(userTappedOnLink:)];
// if labelView is not set userInteractionEnabled, you must do so
[labelView setUserInteractionEnabled:YES];
[labelView addGestureRecognizer:gesture];
In this example, an action message will be sent to self and the message would be defined as
- (void)userTappedOnLink:(UIGestureRecognizer*)gestureRecognizer;
This works the same as wiring up any other UIControl subclass, such as a button.
Other notes: don't try to add the same gesture recognizer to multiple views, it won't work. Don't add more than one copy of the gesture recognizer to multiple views (it doesn't replace them, it just stacks them up and wastes memory). You should add the gesture recognizer when you initially create and configure your view.
For more information, see the documentation for UIGestureRecognizer.
Swift 4.2 Version:
var labelView = UILabel()
let gesture = UITapGestureRecognizer(target: self, action: #selector(userTappedOnLink))
// if labelView is not set userInteractionEnabled, you must do so
labelView.isUserInteractionEnabled = true
labelView.addGestureRecognizer(gesture)
#objc func userTappedOnLink() {
print("clicked!")
}
Swift 2.0 version:
func userTappedOnLink() {
print("clicked!")
}
///tap and link to FB page
let gesture = UITapGestureRecognizer(target: self, action: "userTappedOnLink")
// if labelView is not set userInteractionEnabled, you must do so
lblStaff.userInteractionEnabled = true
lblStaff.addGestureRecognizer(gesture)
Sounds similar to what they accomplished in Twitteriffic with Fancy UILabels. Basically, Craig Hockenberry made his own custom "data detector", so that he could insert links within labels and multi-line text. See this question: Is there a way to create custom UIDataDetectorTypes?
You could also just put an "invisible Button" above, by using a custom button without text and images.
I think you can use textView and diable the scrolling. I did same for my project where I need to point to website addresses. just uncheck everything as shown in screenshot in 'scroll view' section in inspector window.
By adding UITapGestureRecognizer to the label, to make UIlabel clickable.
Before adding the label to tapgesture, don't forgot to enable userinteraction for UIlabel
Here is the sample code:
//Tap Gesture
UITapGestureRecognizer* gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(userTapped:)];
//Adding userinteraction for label
[labelName setUserInteractionEnabled:YES];
//Adding label to tap gesture
[labelName addGestureRecognizer:gesture];
This solution for clickable UILabel. It isn't for select link in text. Just nice solution in my opinion for clickable UILabel like UIButton:
#import <UIKit/UIKit.h>
#protocol ClickableLablelDelegate <NSObject>
#required
- (void)onClickLabel:(UILabel *) label;
#end
#interface ClickableLable : UILabel
#property (nonatomic, weak) id <ClickableLablelDelegate> delegate;
#end
#import "ClickableLable.h"
#implementation ClickableLable
-(void)awakeFromNib
{
[super awakeFromNib];
[self setUserInteractionEnabled:YES];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self setBackgroundColor:[UIColor lightGrayColor]];
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self setBackgroundColor:[UIColor clearColor]];
if ([_delegate respondsToSelector:#selector(onClickLabel:)]) {
[_delegate onClickLabel:self];
}
}
-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self setBackgroundColor:[UIColor clearColor]];
}