如何在iPhone/iPad/iOS上显示临时弹出消息

30

我想在iPhone/iPad上显示一个临时消息,用于确认某个操作或者显示一些与后台活动有关的快速状态。

是否有标准控件可以实现这个功能?我看过一些应用程序使用了这种效果。显示为一个圆角矩形,外观较暗,部分透明,内部有文本。它不需要用户输入,但会在短时间内自动消失。 Android也有类似的构造,这是标准的。类似于Growl显示的窗口。

欢迎提供建议。

10个回答

16

1
这是最接近我所寻找的,尽管最终我还是自己写了一个。 - David
1
更新:备受欢迎的MBProgressHUD现在有了类似Toast的通知功能(http://dl.dropbox.com/u/378729/MBProgressHUD/7.png)。 - Joe Masilotti

15
创建一个继承自UIAlertView的类。在你的构造函数中只需调用[super init],然后将任何你想要添加为子视图的视图添加进去。你甚至可以在 Interface Builder 中设计这个视图。例如:
- (id)initWithMessage:(NSString *)message dismissAfter:(NSTimeInterval)interval
{
  if ((self = [super init]))
  {
     CustomView * customView = [[[CustomView alloc] init] autorelease]; // or load from NIB
     [self addSubview:customView];
     [self performSelector:@selector(dismissAfterDelay) withObject:nil afterDelay:interval];
  }
  return self;
}

- (void)dismissAfterDelay
{
  [self dismissWithClickedButtonIndex:0 animated:YES]; 
}

要显示您的自定义警报视图,只需初始化它,并像常规的UIAlertView一样调用show

CustomAlertView * cav = [[CustomAlertView alloc] initWithMessage:@"Doing Something];
[cav show];
[cav release];

作为一个不错的副作用,当您显示此视图时,背景会变暗,并且任何警报视图都会获得漂亮的摇晃动画。


3
UIAlertView类旨在直接使用,不支持子类化。该类的视图层次结构是私有的,不得进行修改。 - MC.

9
请使用UIAlertView。这里有一个简单示例的快速链接:UIAlertView
编辑:抱歉,没有看到它自己消失的相关信息。我认为您需要通过用户确认已接收到消息。UIAlertView基本上可以实现这一点。除非您在具有计时器或事件延迟的视图的应用程序中,否则不确定是否会逐渐消失,该视图将显示并最终删除它。
第二次编辑:找到了一种实现方法。您可以在指定的一些时间后手动调用dismiss函数。(对于混乱的帖子感到抱歉)它可能看起来像这样:
//Create UIAlertView alert
alert = [[UIAlertView alloc] initWithTitle:@"Title" message:@"Some message" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles: nil];

//After some time
[alert dismissWithClickedButtonIndex:0 animated:TRUE];

我用一个没有按钮的UIAlertView实现了一个简单而粗糙的功能。我在延迟后亲自将其关闭。它能够工作,但看起来远不如我所描述的那样好。如果平台上没有内建的话,肯定有其他地方实现了类似的功能。自己实现起来并不难,但似乎已经有人做过了。'FeeddlerRSS'这个应用经常使用类似的功能。 - David
我找到了一个关于另一个类似问题的帖子。我认为这更符合你所说的内容:https://dev59.com/oHRB5IYBdhLWcg3wiHv7 - Kennzo

8

我创建了一个Android风格的toast,因为目前不需要更多的功能,所以很简单。

当它被显示时,它会添加到父视图的底部,所以如果该视图是VC的视图,则它将位于设备的底部中心。

框架会自动调整以适应文本长度。

你可以这样使用: [self.view addSubview:[[ToastAlert alloc] initWithText:@"Sent"]];,它将被自动删除,因此不需要引用。

我还没有实现这个,但是你可以创建一个静态方法来缩短和澄清说明,类似于:[ToastAlert showText:@"Sent" inView:self.view];

该类:

ToastAlert.h

@interface ToastAlert : UILabel {

}

- (id)initWithText: (NSString*) msg;

@end

ToastAlert.m

#import "ToastAlert.h"
#import <QuartzCore/QuartzCore.h>

@implementation ToastAlert

#define POPUP_DELAY  1.5

- (id)initWithText: (NSString*) msg
{

    self = [super init];
    if (self) {

        self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.7];
        self.textColor = [UIColor colorWithWhite:1 alpha: 0.95];
        self.font = [UIFont fontWithName: @"Helvetica-Bold" size: 13];
        self.text = msg;
        self.numberOfLines = 0;
        self.textAlignment = UITextAlignmentCenter;
        self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;


    }
    return self;
}

- (void)didMoveToSuperview {

    UIView* parent = self.superview;

    if(parent) {

        CGSize maximumLabelSize = CGSizeMake(300, 200);
        CGSize expectedLabelSize = [self.text sizeWithFont: self.font  constrainedToSize:maximumLabelSize lineBreakMode: NSLineBreakByTruncatingTail];

        expectedLabelSize = CGSizeMake(expectedLabelSize.width + 20, expectedLabelSize.height + 10);

        self.frame = CGRectMake(parent.center.x - expectedLabelSize.width/2,
                                parent.bounds.size.height-expectedLabelSize.height - 10,
                                expectedLabelSize.width,
                                expectedLabelSize.height);

        CALayer *layer = self.layer;
        layer.cornerRadius = 4.0f;

        [self performSelector:@selector(dismiss:) withObject:nil afterDelay:POPUP_DELAY];
    }
}

- (void)dismiss:(id)sender {
    // Fade out the message and destroy self
    [UIView animateWithDuration:0.6  delay:0 options: UIViewAnimationOptionAllowUserInteraction
                     animations:^  { self.alpha = 0; }
                     completion:^ (BOOL finished) { [self removeFromSuperview]; }];
}

@end

8

使用没有标题和按钮的UIAlertView,然后在需要时将其解散。这是我如何做到的:

在.h文件中创建一个警告视图的实例变量:

@interface StatusMessageController : UIViewController {
    UIAlertView *statusAlert;
}

在你的 .m 文件中,创建一个方法以显示警告视图并启动计时器,另一个方法用于处理计时器到期后关闭警告:

- (void)showStatus:(NSString *)message timeout:(double)timeout {
    statusAlert = [[UIAlertView alloc] initWithTitle:nil
                                                    message:message
                                                   delegate:nil
                                          cancelButtonTitle:nil
                                          otherButtonTitles:nil];
    [statusAlert show];
    [NSTimer scheduledTimerWithTimeInterval:timeout
                                     target:self
                                   selector:@selector(timerExpired:)
                                   userInfo:nil
                                    repeats:NO];
}

- (void)timerExpired:(NSTimer *)timer {
    [statusAlert dismissWithClickedButtonIndex:0 animated:YES];
}

每当您想要显示状态消息时,请调用它:
[self showStatus:@"Computing" timeout:4.5];

随时可以使用以下方式关闭提示:

[statusAlert dismissWithClickedButtonIndex:0 animated:YES];

您可以使用新的状态动态更改消息:
statusAlert.message = @"Looking up user";

4

我最终创建了自己的类。没有继承自UIAlertView。一般结构是:

-(id)initWithText:(NSString *)msg {
    // Create a view. Put a label, set the msg
    CALayer *layer = self.layer;
    layer.cornerRadius = 8.0f;
    ...
    self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.8];
    [self performSelector:@selector(dismiss:) withObject:nil afterDelay:2.0];
    [self setAutoresizesSubviews:FALSE];
    return self;
}


- (void)dismiss:(id)sender {
    // Fade out the message and destroy self
    [UIView animateWithDuration:0.5 
                 animations:^  { self.alpha = 0; }
                 completion:^ (BOOL finished) { [self removeFromSuperview]; }];
}

请注意,在访问视图层的cornerRadius属性之前,您必须先导入<QuartzCore/QuartzCore.h>。 - Will Pragnell
嘿,我用了这段代码。它运行得很好。但是它只加载一次。当文本字段再次获得焦点时它就不起作用了。有什么解决办法吗? - Manann Sseth

2

与@marco-mustapic类似的答案,但不涉及继承。

- (void)dismissAlert:(UIAlertView *)alertView
{
    [alertView dismissWithClickedButtonIndex:0 animated:YES];
}

- (void)showPopupWithTitle:(NSString *)title
                    mesage:(NSString *)message
              dismissAfter:(NSTimeInterval)interval
{
    UIAlertView *alertView = [[UIAlertView alloc]
           initWithTitle:title
                 message:message
                delegate:nil
        cancelButtonTitle:nil
        otherButtonTitles:nil
    ];
    [alertView show];
    [self performSelector:@selector(dismissAlert:)
               withObject:alertView
               afterDelay:interval
    ];
}

使用方法如下:
[self showPopupWithTitle:@"Hi" message:@"I like pie" dismissAfter:2.0];

将其放入NSObject类别或其他类别中,以始终保持其存在。


2
您可以使用我自己编写的Swift框架StatusAlert。它可以让您显示类似于苹果系统的警报,同时还可以在UIView中展示无图像、标题或消息的相同警报。
它可通过Cocoapods和Carthage获得,并支持iPhone X、安全区域布局和iPad,并允许一些自定义。 StatusAlertExample application screenshow

干得好。加入一个禁用模糊效果的属性会很不错。如果 isBlurAvailable 为 true,则背景设置将被忽略。 - Paglian

2

*Swift 2.2答案:

func showPopupWithTitle(title: String, message: String, interval: NSTimeInterval) {
    let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
    presentViewController(alertController, animated: true, completion: nil)
    self.performSelector(#selector(dismissAlertViewController), withObject: alertController, afterDelay: interval)
}

func dismissAlertViewController(alertController: UIAlertController) {
    alertController.dismissViewControllerAnimated(true, completion: nil)
}

showPopupWithTitle("Title", message: "Message", interval: 0.5)

2

这只是Swift 3版本user2234810的2.2版本。

func showPopupWithTitle(title: String, message: String, interval: TimeInterval) {
    let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
    present(alertController, animated: true, completion: nil)
    self.perform(#selector(dismissAlertViewController), with: alertController, afterDelay: interval)
}

func dismissAlertViewController(alertController: UIAlertController) {
    alertController.dismiss(animated: true, completion: nil)
}
showPopupWithTitle(title: "Title", message: "Message", interval: 0.5)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接