I want to dismiss UIActionsheet when user taps anywhere else on screen. I don't want to
provide cancel button.
My code
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:sheetTitle delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles: nil];
[sheet setTag:indexPath.row];
for (NSString *buttonTitle in buttonTitles)
{
[sheet addButtonWithTitle:buttonTitle];
}
[sheet showFromToolbar:self.navigationController.toolbar];
[sheet release];
[buttonTitles release];
Make your ActionSheet object global and then allocate it into your block. then you can dismiss it from outside touches event on your view.
add following block into your view.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[sheet removeFromSuperView];
sheet=nil;
}
hope this will help you
try this
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOut:)];
tap.cancelsTouchesInView = NO;
[actionSheet.window addGestureRecognizer:tap];
[tap release];`<br> `-(void)tapOut:(UIGestureRecognizer *)gestureRecognizer {
CGPoint p = [gestureRecognizer locationInView:self.actionSheet];
if (p.y < 0) {
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
}
It is UIActionsheet default feature to dismiss when touch outside. No Need of additional code.
[sheet showFromToolbar:self.navigationController.toolbar];
is making the problem I think. Change it to
[sheet showInView:[UIApplication sharedApplication].keyWindow];
Declare ActionSheet globally and then paste this code after the viewdidload
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
works 100%
Related
I want to hide the keyboard by touching the view. Everybody recommends to use this method, saying there's no need to link or anything else, but is not working.
The problem is that my method is not called.Is there anything else that should be done?
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[self view] endEditing:YES];
}
I had trouble with this so use a method that loops through all views seeing if they are textviews and firstResponders. Not sure of the structure of a UITextView but you might need to check for that too although it may be covered.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UIView *txt in self.view.subviews){
if ([txt isKindOfClass:[UITextField class]] && [txt isFirstResponder]) {
[txt resignFirstResponder];
}
}
}
The best approach is to create a "lock view" which is a UIView that takes over the whole screen once the textField becomesFirstResponder. Make sure it's on top of all views (well, besides the textview, of course).
- (void)loadLockView {
CGRect bounds = [UIScreen mainScreen].bounds;
_lockView = [[UIView alloc] initWithFrame:bounds];
_lockView.backgroundColor = [UIColor clearColor];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(lockViewTapped:)];
[_lockView addGestureRecognizer:tgr];
[self.view addSubview:_lockView];
}
- (void)lockViewTapped:(UITapGestureRecognizer *)tgr {
[_lockView removeFromSuperView];
[_textField resignFirstResponder];
}
Use UITapGestureRecognizer For Dismiss keyboard.
Write this code on your viewdidload().
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];[self.view addGestureRecognizer:tap];
and in dismissKeyboard method put this code.
-(void)dismissKeyboard
{
[TextFieldName resignFirstResponder];
}
I want to takeout the keyboard when the user clicks on the background or any other item on the view.
I found out that the following code will take it off. But where should i add it.
[self.view endEditing:YES];
All my UI components are created programatically.
It's super simple, you only need to implement this code in your .m file:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
This will do.
Use below code
UITapGestureRecognizer *recognizer;
recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:nil];
recognizer.numberOfTouchesRequired=1;
[self.view addGestureRecognizer:recognizer];
recognizer.delegate = self;
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
[userName resignFirstResponder];
[passWord resignFirstResponder];
return NO;
}
I have problem with hide keyboard when I showed optionsSheet.
Where is the problem in my code?
- (void)optionsSheet2{
if(optionsSheet2) {
[optionsSheet2 dismissWithClickedButtonIndex:-1 animated:YES];
optionsSheet2 = nil;
}
optionsSheet2 = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:NSLocalizedString(#"Cancel", nil) destructiveButtonTitle:nil otherButtonTitles:NSLocalizedString(#"Delete", nil), NSLocalizedString(#"Delete all", nil), nil];
[optionsSheet2 showInView:self.parentViewController.view];
}
- (void)dismissKeyboard {
[_uiSearchBar resignFirstResponder];
[_uiSearchBar setShowsCancelButton:NO animated:YES];
[_uiSearchBar setHidden:true];
[self.view endEditing:YES];
}
you change code like this:
- (void)optionsSheet2
{
[self.view endEditing:YES];
}
Use this simple Solution
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
Works with UITextField, UITextView and all subviews.
I want to dismiss UIAlertView anywhere outside it with one tap. I want to show a UIAlertView without any button.
I have standard UIAlertView codes here, but I need input how to dismiss it, if it is possible.
With UITouch? With UITapGestureRecognizer?
Thank you.
EDIT:
in viewDidLoad
alertview initialization here with name "alert"
if (alert)
{
emptyview = [[UIView alloc]initWithFrame:CGRectMake(0,0,320,480)];
emptyview.backgroundColor = [UIColor clearColor];
[self.view addSubview:emptyview];
[emptyview addSubview:alert];
NSLog (#"emptyview is there!");
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[emptyview addGestureRecognizer:singleTap];
[singleTap release];
}
But this emptyview doesnt not respond at all and it does not respond to handleSingleTap selector, which I rewrote a bit:
-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
[alert dismissWithClickedButtonIndex:0 animated:YES];
[emptyview removeFromSuperview];
}
I need this emptyview being upon alert when alert is shown then I can dismiss alert with one tap.
I tried:
if (alert)
{
emptyview = [[UIView alloc]initWithFrame:CGRectMake(0,0,320,480)];
emptyview.backgroundColor = [UIColor clearColor];
[self.view addSubview:emptyview];
[emptyview addSubview:alert];
NSLog (#"emptyview is there!");
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[alert addGestureRecognizer:singleTap];
[singleTap release];
}
Of course, alert did respond to handleSingleTap function. What did I wrong with emptyview?
SECOND EDIT:
What I want to achieve in this case is to show a small view with explanation after selecting a word, similar function in Kindle app, if you have one.
Maybe I should create a UIView instead of UIAlertView? But the small view in Kindle app is so nice with shadow below it, how is it possible?
It sounds like you are essentially trying to recreate a "Toast" on iOS. Good news, someone has already done that. See this project.
Edit: Don't want to use iToast. I like your style, less code it is. Here is what I come up with. It would seem obvious as others have said that the only way to overcome the modal nature of the UIAlertView is to add a superview to handle touch events. But you don't have to do that manually every time, consider subclassing UIAlertView. Try something like this:
Edit: #wagashi, Thanks for accepting my answer, and thanks for the heads up about setFrame: being a good place to adjust the size. Your code does make a very toast-like little alert, however when I tried it I found that if the message was to long the view seemed to fall apart. So I have modified setFrame: to simply reduce the size of the alert by about the size of one button, and to remain centered on the screen. So that the class accurately answers the question title "iOS How to dismiss UIAlertView with one tap anywhere?"
NoButtonAlertView.h
#import <UIKit/UIKit.h>
#interface _NoButtonAlertViewCover : UIView
#property (nonatomic,assign) UIAlertView *delegate;
#end
#interface NoButtonAlertView : UIAlertView
-(id)initWithTitle:(NSString *)title message:(NSString *)message;
#end
NoButtonAlertView.m
#import "NoButtonAlertView.h"
#implementation _NoButtonAlertViewCover
#synthesize delegate = _delegate;
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[self removeFromSuperview];
[_delegate dismissWithClickedButtonIndex:0 animated:YES];
}
#end
#implementation NoButtonAlertView
-(void)show{
[super show];
_NoButtonAlertViewCover *cover = [[_NoButtonAlertViewCover alloc] initWithFrame:[UIScreen mainScreen].bounds];
cover.userInteractionEnabled = YES;
cover.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:.01];
cover.delegate = self;
[self.superview addSubview:cover];
}
-(id)initWithTitle:(NSString *)title message:(NSString *)message{
if ((self = [super initWithTitle:title message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:nil, nil])){
}
return self;
}
- (void)setFrame:(CGRect)rect {
// Called multiple times, 4 of those times count, so to reduce height by 40
rect.size.height -= 10;
self.center = self.superview.center;
[super setFrame:rect];
}
#end
With this simple UIAlertView subclass and its UIView subclass for a cover, you can use it as simply as you would a standard UIAlertView. Like so:
NoButtonAlertView *alert = [[NoButtonAlertView alloc] initWithTitle:#"Hello" message:#"I am the very model of a modern major general; I'm information, vegitable, animal, and mineral."];
[alert show];
Will yield:
After showing UIAlertView add to your view controller (or even window) new empty UIView with full screen size. Attach to this wiew UITapGestureRecognizer
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[view addGestureRecognizer:singleTap];
[singleTap release];
Now in handleSingleTap method you can dismiss UIAlertView and remove this view from window
-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
[myAlert dismissWithClickedButtonIndex:0 animated:YES];
[view removeFromSuperView];
}
Inside my viewDidLoad, I have the following:
UILongPressGestureRecognizer *longpressGesture =[[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongpressGesture:)];
longpressGesture.minimumPressDuration = 1;
longpressGesture.allowableMovement = 5;
longpressGesture.numberOfTouchesRequired = 1;
[self.tableView addGestureRecognizer:longpressGesture];
[longpressGesture release];
I created the following:
-(IBAction) handleLongpressGesture:(UIGestureRecognizer *) sender {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Delete Record?" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:#"Yes",#"No",nil];
[actionSheet showInView:self.view];
[actionSheet release];
}
Using the simulator, when I long press, two action sheet shows up instead of the one.
Any ideas as to why this is so?
Is it a problem with the simulator?
It's not a problem with the simulator.
The gesture handler is called multiple times as the gesture goes through different states (began, ended, etc).
You need to check the gesture's state in the handler method:
-(IBAction) handleLongpressGesture:(UIGestureRecognizer *) sender {
if (sender.state == UIGestureRecognizerStateBegan)
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] init...
[actionSheet showInView:self.view];
[actionSheet release];
}
}