最近做項目封裝了一個pickerView 用法很簡單,先來看圖
先來說思路吧,首先創建一個基類的
BasePickerView
,方便以后擴展功能用,它是繼承自UIView
的
單一選擇器
1.看看BasePickerView.h
文件
@interface BasePickerView : UIView<UIPickerViewDataSource, UIPickerViewDelegate>
/** 確認按鈕 */
@property (nonatomic, strong) UIButton *comfirmBtn;
/** 取消按鈕 */
@property (nonatomic, strong) UIButton *cancelBtn;
/** pickerView */
@property (nonatomic, strong) UIPickerView *pickerView;
/** 子類實現的方法 */
- (void)setupPickerView;
/** 確認按鈕點擊事件 */
- (void)comfirmBtnClick;
/** 取消按鈕點擊事件 */
- (void)cancelBtnClick;
/** 彈出頁面 */
- (void)show;
@end
可以看到基類中已經引入了UIPickerViewDataSource
和UIPickerViewDelegate
,子類在繼承的時候就不用再引入了,接下來是一些公開屬性,其實comfirmBtn
和cancelBtn
是不用公開的
/** 子類實現的方法 */
- (void)setupPickerView;
這個方法是給子類實現的,方便做一些數據配置
2.BasePickerView.m
#define kWindowH [UIScreen mainScreen].bounds.size.height //應用程序的屏幕高度
#define kWindowW [UIScreen mainScreen].bounds.size.width //應用程序的屏幕寬度
@interface BasePickerView ()<UIGestureRecognizerDelegate>
/** 確認 取消按鈕所在的視圖 */
@property (nonatomic, strong) UIView *barView;
/** 內容視圖 */
@property (nonatomic, strong) UIView *contentView;
/** 內容高度 */
@property (nonatomic, assign) CGFloat contentHeight;
/** barViewHeight */
@property (nonatomic, assign) CGFloat barViewHeight;
/** btnWidth */
@property (nonatomic, assign) CGFloat btnWidth;
@end
@implementation BasePickerView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
/** 設置默認的內容視圖高度 */
self.contentHeight = 250;
/** 設置默認的按鈕視圖高度 */
self.barViewHeight = 40;
/** 設置默認的按鈕寬度 */
self.btnWidth = 50;
self.bounds = [UIScreen mainScreen].bounds;
self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.1];
[self addSubview:self.contentView];
[self.barView addSubview:self.comfirmBtn];
[self.barView addSubview:self.cancelBtn];
[self.contentView addSubview:self.barView];
[self.contentView addSubview:self.pickerView];
/** 添加手勢 */
UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(remove)];
self.userInteractionEnabled = YES;
tap.delegate = self;
[self addGestureRecognizer:tap];
[self setupPickerView];
}
return self;
}
/** 展示 */
- (void)show {
/** 添加到window */
[[UIApplication sharedApplication].delegate.window addSubview:self];
self.center = [UIApplication sharedApplication].keyWindow.center;
CGRect contentViewFrame = CGRectMake(0, kWindowH, kWindowW, self.contentHeight);
contentViewFrame.origin.y -= self.contentView.frame.size.height;
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.contentView.frame = contentViewFrame;
} completion:^(BOOL finished) {
}];
}
/** 銷毀 */
- (void)remove {
CGRect contentViewFrame = self.contentView.frame;
contentViewFrame.origin.y += self.contentView.frame.size.height;
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.contentView.frame = contentViewFrame;
} completion:^(BOOL finished) {
[self.contentView removeFromSuperview];
[self removeFromSuperview];
}];
}
/** 子類實現的方法 */
- (void)setupPickerView {
}
/** 確認按鈕點擊事件 */
- (void)comfirmBtnClick {
[self remove];
}
/** 取消按鈕點擊事件 */
- (void)cancelBtnClick {
[self remove];
}
#pragma mark - UIGestureRecognizerDelegate
/** 為了不讓子視圖響應手勢點擊 */
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if ([touch.view isDescendantOfView:self.contentView]) {
return NO;
}
return YES;
}
#pragma mark - lazy
- (UIView *)barView {
if (!_barView) {
_barView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kWindowW, self.barViewHeight)];
}
return _barView;
}
- (UIView *)contentView {
if (!_contentView) {
_contentView = [[UIView alloc] initWithFrame:CGRectMake(0, kWindowH, kWindowW, self.contentHeight)];
_contentView.backgroundColor = [UIColor whiteColor];
}
return _contentView;
}
- (UIPickerView *)pickerView {
if (!_pickerView) {
_pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, self.barViewHeight, self.contentView.frame.size.width, self.contentView.frame.size.height - self.barViewHeight)];
_pickerView.delegate = self;
_pickerView.dataSource = self;
_pickerView.backgroundColor = [UIColor colorWithRed:230/255.0 green:230/255.0 blue:230/255.0 alpha:1];
}
return _pickerView;
}
- (UIButton *)comfirmBtn {
if (!_comfirmBtn) {
_comfirmBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_comfirmBtn.frame = CGRectMake(kWindowW - self.btnWidth, 0, self.btnWidth, self.barViewHeight);
[_comfirmBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[_comfirmBtn setTitle:@"確定" forState:UIControlStateNormal];
[_comfirmBtn addTarget:self action:@selector(comfirmBtnClick) forControlEvents:UIControlEventTouchUpInside];
}
return _comfirmBtn;
}
- (UIButton *)cancelBtn {
if (!_cancelBtn) {
_cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_cancelBtn.frame = CGRectMake(0, 0, self.btnWidth, self.barViewHeight);
[_cancelBtn setTitle:@"取消" forState:UIControlStateNormal];
[_cancelBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[_cancelBtn addTarget:self action:@selector(cancelBtnClick) forControlEvents:UIControlEventTouchUpInside];
}
return _cancelBtn;
}
#pragma mark - UIPickerViewDataSource
/** 僅消除警告 子類會重寫*/
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
/** 僅消除警告 子類會重寫*/
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return 1;
}
整個文件的代碼都貼出來了,很簡單,一看就明白,這里提一點就是為了防止子視圖響應點擊手勢而銷毀頁面,在UIGestureRecognizerDelegate
代理方法-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
中做了處理,基類就這么完了,是不是很簡單,我也覺得....
3.接下來我們看看SinglePickerView
,這個是繼承自BasePickerView.h
的子類,頭文件 SinglePickerView.h
中的內容也不多,看代碼
#import "BasePickerView.h"
typedef void(^selectedBlock)(NSString *str,NSInteger index);
/** 單列的pickerView 傳一個數組即可 */
@interface SinglePickerView : BasePickerView
/** 回調block */
@property (nonatomic, copy) selectedBlock block;
/** 使用類方法創建 傳一個數組即可 str為選中的字符串 index為字符串對應數組元素的下標 (比如 要顯示的值為廣州 發請求的時候取code 這時就可以用到index來取值了) */
+ (instancetype)showWithDataArray:(NSArray *)array block:(selectedBlock)block;
@end
公開一個類方法方便調用,不用創建一堆的屬性,命名可能不規范,不要吐槽了....
4.SinglePickerView.m
+(instancetype)showWithDataArray:(NSArray *)array block:(selectedBlock)block {
SinglePickerView *pick = [[SinglePickerView alloc] init];
[pick setDataArray:array];
[pick show];
pick.block = block;
return pick;
}
調用的類方法,大神常用這種方式的,此外應有贊
- (void)setupPickerView {
[super setupPickerView];
_index = 0;
}
設置默認的下標為0,其實在- (void)setDataArray:(NSArray *)dataArray
中已經設置了,這里........
- (void)setDataArray:(NSArray *)dataArray {
_dataArray = dataArray;
_selectedTitle = dataArray.firstObject;
_index = 0;
[self.pickerView reloadAllComponents];
}
初始化數據,_selectedTitle
為選中的字符串 ,_index
為選中的數組下標
- (void)show {
[super show];
if (self.dataArray.count>0) {
[self.pickerView selectRow:0 inComponent:0 animated:NO];
}
}
pickerView默認選中第一行
- (void)comfirmBtnClick{
if (self.block) {
self.block(self.selectedTitle,self.index);
}
[super comfirmBtnClick];
}
確認按鈕點擊事件,回調block,嗯,完犢子了....
地址選擇器
上面說了那么多,感覺都是廢話......
來來來,繼續,接下來有請JWAddressPickerView
,上圖,哎呦,命名沒改..你們自己改吧...
1.來看看
JWAddressPickerView.h
也是沒啥可看的
#import "BasePickerView.h"
typedef void(^AddressBlcok)(NSString *province,NSString *city,NSString *area);
@interface JWAddressPickerView : BasePickerView
/** 回調block */
@property (nonatomic, copy) AddressBlcok addressBlock;
+ (instancetype)showWithAddressBlock:(AddressBlcok)block;
@end
太簡單,不解釋
2.JWAddressPickerView.m
,這個文件得說下.JWAddress.plist
是數據我是拿到別人的,然后轉plist了,時間太久不記得是誰的了,有看到的@我一個,我加上來源
- (void)loadAddressData {
NSString *path = [[NSBundle mainBundle] pathForResource:@"JWAddress" ofType:@"plist"];
self.pickerDic = [[NSDictionary alloc] initWithContentsOfFile:path];
self.provinceArray = [self.pickerDic valueForKey:@"p"];
self.selectedArray = self.pickerDic[@"c"][self.provinceArray.firstObject];
self.cityArray = self.selectedArray;
self.townArray = self.pickerDic[@"a"][@"北京市-北京市"];
}
這個是在本地加載地址數據的方法,也很簡單,嗯,完了,獻上你們要的具體的Demo,請點贊