iPhone开发:在UIAlertView中显示进度条
今天这个问题是,在一个iPhone程序中,我要在后台做大量的数据处理,希望在界面上显示一个进度条(Progress Bar)使得用户了解处理进度。这个进度条应该是在一个模态的窗口中,使界面上其他控件无法被操作。怎么用最简单的方法来实现这个功能?UIAlertView是一个现成的模态窗口,如果能把进度条嵌入到它里面就好了。
以下内容适用于iOS 2.0+。
我们知道,如果要显示一个alert窗口(比如用来显示错误或警告信息、询问用户是否确认某操作等等),只要简单地创建一个UIAlertView对象,再调用其show方法即可。示意代码如下:
1
2
3
4
5
6
7 UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:@"Title"
message:@"Message"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil]
autorelease];
[alertView show];
如果要添加一个进度条,只要先创建并设置好一个UIProgressView的实例,再利用addSubbiew方法添加到alertView中即可。
在实际应用中,我可能需要在类中保存进度条的对象实例,以便更新其状态,因此先在自己的ViewController类中添加成员变量:
1
2
3
4
5
6
7
8
9 // MySampleViewController.h
#import <UIKit/UIKit.h>
@interface MySampleViewController : UIViewController {
@private
UIProgressView* progressView_;
}
@end
接下来写一个叫做showProgressAlert的方法来创建并显示带有进度条的alert窗口,其中高亮的部分就是把进度条添加到alertView中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 - (void)showProgressAlert:(NSString*)title withMessage:(NSString*)message {
UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:nil]
autorelease];
progressView_ = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
progressView_.frame = CGRectMake(30, 80, 225, 30);
[alertView addSubview:progressView_];
[alertView show];
}
为了让数据处理的子进程能够方便地修改进度条的值,再添加一个简单的方法:
1
2
3
另外,数据处理完毕后,我们还需要让进度条以及alertView消失,由于之前并没有保存alertView的实例,可以通过进度条的superview访问之:
1
2
3
4
5
6
7
8
9
10
11
12
13 - (void)dismissProgressAlert {
if (progressView_ == nil) {
return;
}
if ([progressView_.superview isKindOfClass:[UIAlertView class]]) {
UIAlertView* alertView = (UIAlertView*)progressView_.superview;
[alertView dismissWithClickedButtonIndex:0 animated:NO];
}
[progressView_ release];
progressView_ = nil;
}
假设处理数据的方法叫processData,当然它会在一个单独的线程中运行,下面的片段示意了如何更新进度条状态,以及最后如何让它消失。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 - (void)processData:(int)total {
for (int i = 0; i < total; ++i) {
// Update UI to show progess.
float progress = (float)i / total;
NSNumber* progressNumber = [NSNumber numberWithFloat:progress];
[self performSelectorOnMainThread:@selector(updateProgress:)
withObject:progressNumber
waitUntilDone:NO];
// Process.
// do it.
}
// Finished.
[self performSelectorOnMainThread:@selector(dismissProgressAlert)
withObject:nil
waitUntilDone:YES];
// Other finalizations.
}
在实际使用中,带进度条的alert view大概长得是这样的:

带进度条的alert窗口
参考:
不一定相关的相关文章:作者: Calf
标签: iOS, iPhone 开发, ObjC, progress bar, UIAlertView, UIProgressView, 进度条 发表评论
翻译
友情链接
- Bebluesky 快乐生活,幽它一默
- Python俱乐部 以提供Python知识为目标,原创并收集Python编程相关的知识
- 东华博客 关注生活,关注科技,关注互联网,了解互联网,了解科技,了解生活!
- 阅微堂 数学、金融、计算机
随便看看
- 等概率随机排列数组(洗牌算法)
- 可以继承的C++ Singleton基类
- WordPress数学公式插件LaTeX
- 2011.5.15我们的婚礼(二)——迎亲篇
- 搞怪趣题:让11、12、13、14通过加减乘除运算得到46
广而告之
系列文章
Other posts belonging to the Series: iOS开发笔记
标签云
Algorithm BlueHost Game iOS iPhone 开发 LaTeX Math ObjC OS Plugin Twilight Princess Wii WordPress WordPress Plugin 任天堂 单次遍历 塞尔达传说 婚礼 建站 智力题 概率 游戏攻略 照片 等概率 算法题 随机数 随机选取 面试题 黎明公主 黑苹果
WP Cumulus Flash tag cloud by Roy Tanck requires Flash Player 9 or better.
最新评论
- 正在加载...
2011年12月10日 22:44
准备开发App啦,赞的
2011年12月12日 13:33
呵呵,还没有,只是写写玩儿
2011年12月23日 12:46
方法挺好,但是苹果iOS文档 View and Window Architecture 最后一条是这样的:
Do Not Customize Controls by Embedding Subviews
Although it is technically possible to add subviews to the standard system controls—objects that inherit from UIControl—you should never customize them in this way. Controls that support customizations do so through explicit and well-documented interfaces in the control class itself. For example, the UIButton class contains methods for setting the title and background images for the button. Using the defined customization points means that your code will always work correctly. Circumventing these methods, by embedding a custom image view or label inside the button, might cause your application to behave incorrectly now or at some point in the future if the button’s implementation changes.
不知有没有更好的解决方法。
2011年12月26日 12:49
这确实是个问题,而且对于UIAlertView,文档中也专门说到:“The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.”。
如果不这样搞,那只能是自己写一个类似的alert view了,工作量倒也不是特别大。
2012年02月29日 14:47
最近由于要自定义AlertView的样式(改变背景图案,改变按钮图案,修改字体等),索性就重新写了一个CustomAlertView,除了可以修改样式外,还可以直接支持添加子元素。
2011年12月29日 09:52
我想一下.... processData 你是在哪里调用的呢? 我没办法模拟出你截图的效果
2011年12月29日 10:58
processData需要在另外一个线程中。我目前用到了两种执行的方式:
一种是在单独的线程中处理数据,并通过performSelectorOnMainThread方法通知主线程刷新UI。比如:
另一个方式也差不多,是直接调用一个异步处理方法(比如AVAssetExportSession类的- (void)exportAsynchronouslyWithCompletionHandler:(void (^)(void))handler)。但由于这种异步处理方法是不受用户代码干扰的,所以再开一个NSTimer,当timer触发的时候更新UI:
2011年12月29日 13:45
额....我采用了一种方法..不过不知道为什么不行,如果有时间的话,能不能帮我看看...
代码如下
//在 按钮事件里开启 AlertView
-(IBAction) click :(id)sender
{
[self showProgressAlert:@"title" withMessage:@"message"];
}
//在按钮事件 里面触发 processData 方法
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex==1) {// 这个按钮 是提示框的确定按钮
[self processData:1000];
}
}
但是 .. 进度条不动.....
2011年12月30日 16:08
这可能是因为你没有在单独的线程中处理数据。在主线程中,如果你的函数仍在运行,UI基本上不会被更新的。
你可以用NSThread来创建新的线程,并在新的线程中处理数据,比如这样(注意这里的processData跟我上面提供的有一些小的差异,一方面把它的参数改成NSObject的子类,另一方面在其内部添加了autorelease pool):
2012年05月15日 20:44
我的gtalk: mailipod5@gmail.com