昨天搞放大镜时突然得到了灵感。
突然又想到这个事,就尝试了一下,成功了。
这里分享下思路。
其实一直以来我们都收到了一个惯性思维的影响,那就是 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,给大家提供思路的,至于画边框和箭头,动画就没做的。可以看下截图。
其实最关键的代码就是这两个了。
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 {
}