最终效果图:
代码片段:
// // DockItemLocation.m // 帅哥_团购 // // Created by beyond on 14-8-13. // Copyright (c) 2014年 com.beyond. All rights reserved. // #import "DockItemLocation.h" // 点击dock上面的locationBtn,弹出的Popover封装的控制器,其上方是搜索栏,下方是tableView #import "CityLocationController.h" // 按钮上面是图片,下面是文字,这是图片在高度上的比例 #define kImageHeightRatioInBtn 0.5 @interface DockItemLocation()<UIPopoverControllerDelegate> { //popover控制器,创建出来之后,show方法显示,因此不可以是局部变量,必须用成员变量记住,否则方法btnClick调用完毕就销毁了,还如何 显示捏? UIPopoverController *_popoverCtrl; } @end @implementation DockItemLocation - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // 1.调用父类的方法,设置内部的图片 [self setIcon:@"ic_district.png" selectedIcon:@"ic_district_hl.png"]; // 2.自动伸缩 self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin; // 3.设置默认的文字 [self setTitle:@"定位中" forState:UIControlStateNormal]; self.titleLabel.font = [UIFont systemFontOfSize:16]; self.titleLabel.textAlignment = NSTextAlignmentCenter; [self setTitleColor:[UIColor whiteColor] forState:UIControlStateDisabled]; [self setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; // 4.设置图片属性 self.imageView.contentMode = UIViewContentModeCenter; // 5.监听点击【Location定位】,弹出一个Popover控制器 [self addTarget:self action:@selector(locationBtnOnDockClicked) forControlEvents:UIControlEventTouchDown]; } return self; } // 5.监听点击【Location定位】,弹出一个Popover控制器 - (void)locationBtnOnDockClicked { // 禁用,只可点击一次 self.enabled = NO; // 点击dock上面的locationBtn,弹出的Popover封装的控制器,其上方是搜索栏,下方是tableView CityLocationController *cityVC = [[CityLocationController alloc] init]; // 唯一一个不是继承自UIViewController的控制器,它继承自NSObject //popover控制器,创建出来之后,show方法显示,因此不可以是局部变量,必须用成员变量记住,否则方法btnClick调用完毕就销毁了,还如何 显示捏? _popoverCtrl = [[UIPopoverController alloc] initWithContentViewController:cityVC]; // 设置这个Popover控制器的显示的大小 _popoverCtrl.popoverContentSize = CGSizeMake(320, 480); // 代理,监听Popover控制器的XX事件 _popoverCtrl.delegate = self; // 因为其他方法也要显示,_popoverCtrl,所以抽取成自定义方法 [self showPopoverCtrl]; // 因为屏幕旋转时,弹出的popover的指向的位置就不对了,所以有必要注册监听屏幕旋转的通知 // 先移除监听器,保证健壮性 [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; // 再添加一个监听器,一旦设备出现UIDeviceOrientationDidChangeNotification,就会调用observer的selector方法 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenDidRotated) name:UIDeviceOrientationDidChangeNotification object:nil]; } // 5-1,因为侦听到屏幕旋转了,也要再次显示_popoverCtrl,所以抽取成自定义方法 - (void)showPopoverCtrl { // 显示到哪里? 如果目标view是self自己,则rect使用bounds,因为bounds的原点才是相对于自己 // 如果目标view是self.superView,则rect使用frame,因为frame的原点才是相对于父控件 [_popoverCtrl presentPopoverFromRect:self.bounds inView:self permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } // 5-2,再添加一个监听器,一旦设备出现UIDeviceOrientationDidChangeNotification,就会调用observer的selector方法 - (void)screenDidRotated { if (_popoverCtrl.popoverVisible) { // 1. 关闭之前位置上面的_popoverCtrl [_popoverCtrl dismissPopoverAnimated:NO]; // 2. 0.5秒后创建新的位置上的_popoverCtrl [self performSelector:@selector(showPopoverCtrl) withObject:nil afterDelay:0.5]; } } #pragma mark - popOver代理方法 - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { // 消失前,让定位按钮恢复可以点击状态 self.enabled = YES; // 消失前,即popover被销毁的时候,移除注册的监听器(通知) [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; } #pragma mark - 销毁时,移除当前对控制器对屏幕的监听,防止野指针 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - 覆写调整图片和文字在按钮中的Frame - (CGRect)imageRectForContentRect:(CGRect)contentRect { CGFloat btnW = contentRect.size.width; CGFloat imgH = contentRect.size.height * kImageHeightRatioInBtn; return CGRectMake(0, 0, btnW, imgH); } - (CGRect)titleRectForContentRect:(CGRect)contentRect { CGFloat btnW = contentRect.size.width; CGFloat textH = contentRect.size.height * (1 - kImageHeightRatioInBtn); // 文字在下面,图片在上面 CGFloat textY = contentRect.size.height - textH; return CGRectMake(0, textY, btnW, textH); } @end