10

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?

wagashi
  • 894
  • 3
  • 15
  • 39

2 Answers2

10

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:

Custom AlertView

NJones
  • 27,139
  • 8
  • 70
  • 88
  • 1
    Um, my goal is not to make or use a view made of complicated and long codes. This iToast is really great, but I wonder if it is possible to make a such feature with less codes? Thanks for sharing this link with us. – wagashi Nov 24 '11 at 21:51
  • this was immeasurably helpful! I added in .m : ` - (void)setFrame:(CGRect)rect { //[super setFrame:CGRectMake(0, 0, rect.size.width, 300)]; [super setFrame:CGRectMake(0, 0, 100, 100)]; //code below makes UIAlertView being centered. //self.center = CGPointMake(320/2, 480/2); //my custom cgpointmake self.center = CGPointMake(200, 400); }` – wagashi Nov 24 '11 at 23:21
  • Yes, you did answer my question. However I am not going to put much information in my "alert", so CGRectMake 0,0,100,100 is just perfect in my case. I wonder if it is possible to change font size of text inside UIAlertView? – wagashi Nov 25 '11 at 09:04
  • and your another solution to CGRectMake is also useful, thank you again. – wagashi Nov 25 '11 at 10:56
  • 1
    Alert view doesn't seem to be dismissed with ios 7 :( – Eshwar Chaitanya May 06 '14 at 07:27
3

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];
}
beryllium
  • 29,669
  • 15
  • 106
  • 125
  • 1
    I'd add a custom UIButton with no text or image – Zaky German Nov 24 '11 at 17:58
  • Yes, good idea. It saves from writing several lines of code. In any case you need to handle tap action. – beryllium Nov 24 '11 at 18:01
  • 1
    Out of curiosity, why use a `UIAlertView` at all? Put a full screen `UIButton` in front of all other views with whatever text and background color w/ alpha you like (or get fancier). – XJones Nov 24 '11 at 18:22
  • @beryllium That is good idea. But I think I think not very logically, please see my edit. – wagashi Nov 24 '11 at 21:16
  • @XJones That is also a good idea. I am a bit far more than new beginner. Please see my second edit for what I want to achieve. – wagashi Nov 24 '11 at 21:24
  • @beryllium By the way I have a UITextView on main UIView. UIView did respond to your suggestion, but not UITextView, is this a common problem? – wagashi Nov 24 '11 at 23:03