iOS中封裝一個(gè)自定義UIPickerView(Button篇)

UIPickerView是iOS開發(fā)中懦铺,相當(dāng)常用的一個(gè)UI控件担败,用于滾動選擇選項(xiàng)殿托。也是項(xiàng)目中經(jīng)常復(fù)用的一個(gè)控件霹菊,封裝成一個(gè)統(tǒng)一風(fēng)格的庫,可以減少很多代碼量支竹。一般還會在PickerView上加上Toolbar和確定取消按鈕旋廷。
點(diǎn)擊button彈出picker,并改變指定label的值礼搁,效果如下圖所示饶碘。



最終目的是在viewcontroller中button的event reponse中調(diào)用封裝好的庫的方法進(jìn)行傳值及操作。

- (IBAction)showPicker:(UIButton *)sender {
    NSArray *array = @[@"電子科技大學(xué)",@"清華大學(xué)",@"四川大學(xué)",@"華中科技大學(xué)",@"西安電子科技大學(xué)"];
    [CDZPicker showPickerInView:self.view withObjectsArray:array withlastString:self.label.text withStringBlock:^(NSString *string) {
        self.label.text = string;
    }];
    }

實(shí)現(xiàn)思路從數(shù)據(jù)馒吴,視圖扎运,按鈕處理三個(gè)方面說

1. 數(shù)據(jù)

  • 傳入數(shù)據(jù)(上層view對象卑雁,數(shù)組array,最后的值)
  • 改變的值(利用block傳值回調(diào))
  • UIPickerView的Delegate和DataSource方法的實(shí)現(xiàn)

上層view對象和數(shù)組array沒啥可說的绪囱,關(guān)于取消按鈕的實(shí)現(xiàn)测蹲,個(gè)人想法是把彈出picker改變前最后的值傳進(jìn)view的內(nèi)部并存儲起來,等待按鈕的動作響應(yīng)判斷是否取出鬼吵。(但個(gè)人感覺把這個(gè)值傳進(jìn)去實(shí)現(xiàn)不太優(yōu)雅扣甲,但水平不夠沒想到其它實(shí)現(xiàn)方法,希望交流)
改變值用利用block方法傳值齿椅,不用delegate和通知的原因是感覺都太復(fù)雜了琉挖,通知還需要注冊,但block的使用要注意避免循環(huán)引用導(dǎo)致內(nèi)存沒辦法得到釋放的問題涣脚。
在.h文件中定義block的別名便于使用
typedef void (^CDZStringResultBlock)(NSString *string);
.m中增加以下屬性

@property (nonatomic,strong) NSArray *dataArray;
@property (nonatomic,strong) NSString *lastString;
@property (nonatomic,  copy) CDZStringResultBlock block;

實(shí)現(xiàn)Pickerview的Delegate和DataSource協(xié)議
<UIPickerViewDelegate,UIPickerViewDataSource>
實(shí)現(xiàn)Pickerview的Delegate和DataSource相關(guān)方法

#pragma mark - PickerDataSource
//返回picker列數(shù)
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 1;
}

//picker行數(shù)
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    return self.dataArray.count;
}
#pragma mark - PickerDelegate
//返回每行高度
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
    return 44;
}

//滑動到當(dāng)行進(jìn)行的操作示辈,這里把當(dāng)行的數(shù)據(jù)回調(diào)
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
    self.block(self.dataArray[row]);
}

//要修改picker滾動里每行文字的值及相關(guān)屬性,分割線等在此方法里設(shè)置
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
    //設(shè)置分割線的顏色,這里設(shè)為隱藏
    for(UIView *singleLine in pickerView.subviews){
        if (singleLine.frame.size.height < 1) {
            singleLine.backgroundColor = [UIColor clearColor];
        }
    }
    
    //設(shè)置文字的屬性
    UILabel *genderLabel = [UILabel new];
    genderLabel.textAlignment = NSTextAlignmentCenter;
    genderLabel.text = self.dataArray[row];
    genderLabel.font = [UIFont systemFontOfSize:23.0];
    genderLabel.textColor = [UIColor blackColor];

    return genderLabel;
}

另外有一點(diǎn)要注意
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
這個(gè)方法的優(yōu)先級比
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
這個(gè)方法優(yōu)先級高遣蚀,也就是說會覆蓋后面那個(gè)方法里的設(shè)置矾麻,后面的方法只能確定每行返回的方法的值,沒辦法對字體大小芭梯,顏色险耀,分割線等進(jìn)行自定義,需要自定義就使用第一個(gè)方法玖喘。

2. 視圖

視圖上甩牺,由一個(gè)壓黑背景的view上面加上一個(gè)包含確定和取消兩個(gè)按鈕和pickerview的containview組成。
先在最開始進(jìn)行一些顏色累奈,屏幕大小的宏定義和全局靜態(tài)變量定義贬派,方便使用

#define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
#define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
#define BACKGROUND_BLACK_COLOR [UIColor colorWithRed:0.412 green:0.412 blue:0.412 alpha:0.7]
static const int pickerViewHeight = 228;
static const int toolBarHeight = 44;

進(jìn)行view的布局,增加button點(diǎn)擊動作等澎媒,pickerview要指定datasource和delegate為self

- (void)initView{
    UIView *containerView = [[UIView alloc]initWithFrame:CGRectMake(0, SCREEN_HEIGHT - pickerViewHeight, SCREEN_WIDTH, pickerViewHeight)];
    containerView.backgroundColor = [UIColor whiteColor];
    
    UIButton *btnOK = [[UIButton alloc] initWithFrame:CGRectMake(SCREEN_WIDTH -70, 5, 40, 30)];
    btnOK.titleLabel.font = [UIFont systemFontOfSize:18.0];
    [btnOK setTitle:@"確定" forState:UIControlStateNormal];
    [btnOK setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [btnOK addTarget:self action:@selector(pickerViewBtnOk:) forControlEvents:UIControlEventTouchUpInside];
    [containerView addSubview:btnOK];
    
    UIButton *btnCancel = [[UIButton alloc] initWithFrame:CGRectMake(30, 5, 40, 30)];
    btnCancel.titleLabel.font = [UIFont systemFontOfSize:18.0];
    [btnCancel setTitle:@"取消" forState:UIControlStateNormal];
    [btnCancel setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [btnCancel addTarget:self action:@selector(pickerViewBtnCancel:) forControlEvents:UIControlEventTouchUpInside];
    [containerView addSubview:btnCancel];
    
    UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 32, SCREEN_WIDTH, pickerViewHeight - toolBarHeight)];
    pickerView.backgroundColor = [UIColor whiteColor];
    pickerView.delegate = self;
    pickerView.dataSource = self;
    [containerView addSubview:pickerView];
    
    self.backgroundColor = BACKGROUND_BLACK_COLOR;
    [self addSubview:containerView];
}

3.響應(yīng)按鈕點(diǎn)擊事件

很簡單搞乏,見代碼即可。取消的話把傳進(jìn)來的lastString傳回去即可旱幼。

#pragma mark - event response
- (void)pickerViewBtnOk:(UIButton *)btn{
    [self removeFromSuperview];
}

- (void)pickerViewBtnCancel:(UIButton *)btn{
    self.block (self.lastString);
    [self removeFromSuperview];
}

封裝成工廠方法

+ (void)showPickerInView:(UIView *)view
        withObjectsArray:(NSArray *)array
          withlastString:(NSString *)string
         withStringBlock:(CDZStringResultBlock)stringBlock{
    CDZPicker *pickerView = [[CDZPicker alloc]initWithFrame:view.bounds];
    pickerView.dataArray = array;
    pickerView.lastString = string;
    pickerView.block = stringBlock;
    pickerView.block(array[0]);//未滑動的話默認(rèn)為第一個(gè)數(shù)據(jù)
    [pickerView initView];
    [view addSubview:pickerView];
}

最后

所有源碼和Demo
這是我第一次寫技術(shù)類文章查描,雖然不是什么很深入的問題突委,但希望能分享給有需要的人柏卤。

如果您覺得有幫助,不妨給個(gè)star鼓勵(lì)一下,歡迎關(guān)注&交流
有任何問題歡迎評論私信或者提issue
QQ:757765420
Email:nemocdz@gmail.com
Github:Nemocdz
微博:@Nemocdz

謝謝觀看

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市匀油,隨后出現(xiàn)的幾起案子缘缚,更是在濱河造成了極大的恐慌,老刑警劉巖敌蚜,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桥滨,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)齐媒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門蒲每,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人喻括,你說我怎么就攤上這事邀杏。” “怎么了唬血?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵望蜡,是天一觀的道長。 經(jīng)常有香客問我拷恨,道長脖律,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任腕侄,我火速辦了婚禮小泉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘冕杠。我一直安慰自己膏孟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布拌汇。 她就那樣靜靜地躺著柒桑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪噪舀。 梳的紋絲不亂的頭發(fā)上魁淳,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機(jī)與錄音与倡,去河邊找鬼界逛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛纺座,可吹牛的內(nèi)容都是我干的息拜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼净响,長吁一口氣:“原來是場噩夢啊……” “哼少欺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起馋贤,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤赞别,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后配乓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仿滔,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惠毁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了崎页。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞠绰。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖飒焦,靈堂內(nèi)的尸體忽然破棺而出洞豁,到底是詐尸還是另有隱情,我是刑警寧澤荒给,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布丈挟,位于F島的核電站,受9級特大地震影響志电,放射性物質(zhì)發(fā)生泄漏曙咽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一挑辆、第九天 我趴在偏房一處隱蔽的房頂上張望例朱。 院中可真熱鬧,春花似錦鱼蝉、人聲如沸洒嗤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渔隶。三九已至,卻和暖如春洁奈,著一層夾襖步出監(jiān)牢的瞬間间唉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工利术, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呈野,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓印叁,卻偏偏與公主長得像被冒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子轮蜕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容