以前一直迷恋于iphone上的alertview,popoverwindow是怎么做的,也就是怎样再iphone上弹出不满屏显示的模态对话窗口。



昨天搞放大镜时突然得到了灵感。

突然又想到这个事,就尝试了一下,成功了。

这里分享下思路。


其实一直以来我们都收到了一个惯性思维的影响,那就是 iphone的程序只有一个window,而且window是继承自view的,再加上IB里不可以创建window,所以一直把window这个东西给忽略掉了。


其实目前那些popover的menu,loadingview之类的都是搞view,可以解决。但显示的时候其实挺麻烦的,得先保证全屏,在addsubview,消失时又得removefromsuperview,还得保证这个view在最上层,代码得可重用度也不高。


其实iphone程序是支持多窗口显示得,而且还支持分层显示,就是设置window得windowlevel。Mac上有类似的属性可以得到很多不同效果的window显示。


那我们完全可以alloc一个window,并让之成为keywindow,那么所有的touch事件都会被它捕获到。并且它是个view啊,那就可以addsubview,可以设置backgroundcolor,那么问题就简单了,大家应该可以猜到ipad 上的popoverwindow是咋做的了。


那就是生成一个fullscreen的windowlevel为UIWindowAlertLevel的window,且backgroundcolor为clearcolor,然后把要显示的controller的view加到subview,并且在drawrect中围绕这个view的周围画上边框,在弹出点画上个箭头,最后以动画的方式显示出来就好啦,然后点击window空白地方时让它动画消失即可。。。对,就是这么简单。。。


那UIAlertView就更简单了,虽然它是继承自UIView,但它的实现应该跟UIWindow差不到哪里去,其实它内部也应该是个window,根据不同的subviews设置不同的内容高度,调整内容的size等。


快速写了个IMPopoverController,接口抄自UIPopoverController,当时只是个demo,给大家提供思路的,至于画边框和箭头,动画就没做的。可以看下截图。

popover window on iphone (代码实现)_#import  

popover window on iphone (代码实现)_sed_02 



其实最关键的代码就是这两个了。


IMPopoverController.h




1 IMPopoverController.h
2 //  IMPopoverController
3 //
4 //  Created by yoyokko on 10-8-28.
5 //  Copyright 2010 [email]yoyokko@gmail.com[/email]. All rights reserved.
6 //
7
8 #import <foundation foundation.h="">
9
10 @interface IMWindow : UIWindow
11 {
12     id delegate_;
13 }
14
15 @property (nonatomic, assign) id delegate;
16
17 @end
18
19
20 @interface IMPopoverController : NSObject {
21     UIViewController    *contentViewController_;
22     IMWindow    *popOverWindow_;
23     CGSize    popOverSize_;
24 }
25
26 @property (nonatomic) CGSize popOverSize;
27
28 - (id) initWithContentViewController:(UIViewController *) con;
29 - (UIViewController *) contentViewController;
30 - (void) setContentViewController:(UIViewController *) newCon animated:(BOOL) animated;
31
32 - (void) presentPopoverFromRect:(CGRect) rect inView:(UIView *) inView animated:(BOOL) animated;
33 - (void) dismissPopoverAnimated:(BOOL) animated;
34
35 @end
36 </foundation>


IMPopoverController.m



1 //
2 //  IMPopoverController.m
3 //  IMPopoverController
4 //
5 //  Created by yoyokko on 10-8-28.
6 //  Copyright 2010 [email]yoyokko@gmail.com[/email]. All rights reserved.
7 //
8
9 #import "IMPopoverController.h"
10
11 @implementation IMWindow
12
13 @synthesize delegate = delegate_;
14
15 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
16 {
17     [self.delegate touchesEnded:touches withEvent:event];
18 }
19
20 @end
21
22
23 @interface IMPopoverController (Private)
24
25 @property (nonatomic, retain) IMWindow *popOverWindow;
26
27 @end
28
29
30 @implementation IMPopoverController
31
32 @synthesize popOverSize = popOverSize_;
33
34 - (UIWindow *) popOverWindow
35 {
36     return popOverWindow_;
37 }
38
39 - (void) setPopOverWindow:(UIWindow *) newValue
40 {
41     if (popOverWindow_ != newValue)
42     {
43         [popOverWindow_ release];
44         popOverWindow_ = [newValue retain];
45     }
46 }
47
48 - (id) initWithContentViewController:(UIViewController *) con
49 {
50     if (self = [super init]) {
51
52         self.popOverWindow = [[[IMWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
53         self.popOverWindow.windowLevel = UIWindowLevelAlert;
54         self.popOverWindow.backgroundColor = [UIColor clearColor];
55         self.popOverWindow.hidden = YES;
56         self.popOverWindow.delegate = self;
57
58         [self setContentViewController:con animated:NO];
59     }
60     return self;
61 }
62
63 - (UIViewController *) contentViewController
64 {
65     return contentViewController_;
66 }
67
68 - (void) setContentViewController:(UIViewController *) newCon animated:(BOOL) animated
69 {
70     if (contentViewController_ != newCon) {
71         [contentViewController_ release];
72         contentViewController_ = newCon;
73     }
74 }
75
76 - (void) presentPopoverFromRect:(CGRect) rect inView:(UIView *) inView animated:(BOOL) animated
77 {
78     UIWindow *mainWin = [[[UIApplication sharedApplication] delegate] window];
79     CGRect newFrame = [mainWin convertRect:rect fromWindow:mainWin];
80     [[self contentViewController].view setFrame:CGRectMake(newFrame.origin.x, newFrame.origin.y, self.popOverSize.width, self.popOverSize.height)];
81     [self.popOverWindow addSubview:[self contentViewController].view];
82     self.popOverWindow.hidden = NO;
83     [self.popOverWindow makeKeyWindow];
84 }
85
86 - (void) dismissPopoverAnimated:(BOOL) animated
87 {
88     [self.popOverWindow resignKeyWindow];
89     self.popOverWindow.hidden = YES;
90 }
91
92 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
93 {
94     [self dismissPopoverAnimated:YES];
95 }
96
97 - (void) dealloc
98 {
99     self.popOverWindow = nil;
100     [super dealloc];
101 }
102
103 @end


附件是实例代码




1、初始化UIPopoverController

    UIPopoverController *popover = [[UIPopoverController alloc]initWithContentViewController:navigationController]; 

  

//必须是个 ViewController

/*且该 ViewController的 viewDidLoad方法中要设置其在popover中的尺寸,如

    self.contentSizeForViewInPopover = CGSizeMake(300.0, 280.0);

*/


    self.recentSearchesPopoverController = popover;

    recentSearchesPopoverController.delegate = self;    //self要实现UIPopoverControllerDelegate协议


2、设置当popover弹出时,用户仍可以交互的视图

    // Ensure the popover is not dismissed if the user taps in the search bar.

    popover.passthroughViews = [NSArray arrayWithObject:searchBar];


3、展现popover

    [self.recentSearchesPopoverControllerpresentPopoverFromRect:self.searchBar.bounds

                                                          inView:self.searchBar

                                       permittedArrowDirections:UIPopoverArrowDirectionAny

                                                        animated:NO];

4、消失popover

//dismiss the popover.

    [recentSearchesPopoverController dismissPopoverAnimated:YES];

 

5、实现 UIPopoverControllerDelegate协议的方法

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {

}


 


 


1、初始化UIPopoverController

    UIPopoverController *popover = [[UIPopoverController alloc]initWithContentViewController:navigationController]; 

  

//必须是个 ViewController

/*且该 ViewController的 viewDidLoad方法中要设置其在popover中的尺寸,如

    self.contentSizeForViewInPopover = CGSizeMake(300.0, 280.0);

*/


    self.recentSearchesPopoverController = popover;

    recentSearchesPopoverController.delegate = self;    //self要实现UIPopoverControllerDelegate协议


2、设置当popover弹出时,用户仍可以交互的视图

    // Ensure the popover is not dismissed if the user taps in the search bar.

    popover.passthroughViews = [NSArray arrayWithObject:searchBar];


3、展现popover

    [self.recentSearchesPopoverControllerpresentPopoverFromRect:self.searchBar.bounds

                                                          inView:self.searchBar

                                       permittedArrowDirections:UIPopoverArrowDirectionAny

                                                        animated:NO];

4、消失popover

//dismiss the popover.

    [recentSearchesPopoverController dismissPopoverAnimated:YES];

 

5、实现 UIPopoverControllerDelegate协议的方法

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {

}