年前的某天,公司的UI拿了張設計圖讓我看下能否實現,隨意一瞥發現只是個PickerView,心想著用UIPickerView封裝一下還不是so easy的事情,然而接下去了解了需求後才發現沒那麼簡單......
具體需求如下:
- 需要能自定義選中顏色及未選中顏色,且跟隨滾動實時變化;
- 需要能自定義選中指示器;
- 需要滾動效果是平面滾動;
根據上面的需求,翻看了下UIPickerView的介面並寫程式碼測試了下後發現情況不容樂觀:
- UIPickerView預設不支援選中顏色設定,可通過自定義view實現,但是無法跟隨滾動實時變化;
- UIPickerView原生不支援設定選中指示器樣式;
- UIPickerView預設滾動效果為類曲面滾動,且不支援設定;
到現在已經基本確定UIPickerView的方案已經被斃了,不過沒關係,原生沒法實現那麼就自己實現一個,於是 STDPickerView 就在這種情況下誕生了:
STDPickerView 是什麼 STDPickerView 是基於 UICollectionView 封裝的選擇控制元件,相容UIPickerView大部分介面,並增加了多個定製化介面,可實現更多的效果!STDPickerView 效果圖如下:
STDPickerView 怎麼使用
- 初始化
STDPickerView *pickerView = [[STDPickerView alloc] init];
pickerView.dataSource = self;
pickerView.delegate = self;
/*
STDPickerViewSelectionIndicatorStyleNone:無選中指示器
STDPickerViewSelectionIndicatorStyleDefault:預設選中指示器
STDPickerViewSelectionIndicatorStyleDivision: 分段選中指示器
STDPickerViewSelectionIndicatorStyleCustom:自定義選中指示器,需實現 selectionIndicatorViewInPickerView: 代理方法
*/
pickerView.selectionIndicatorStyle = STDPickerViewSelectionIndicatorStyleDefault;
/*
預設情況下,如果同時實現了titleForRow以及viewForRow資料來源方法,
則會優先使用viewForRow方法返回自定義view,
此時可設定 forceItemTypeText = YES 來指定使用titleForRow方法
*/
pickerView.forceItemTypeText = YES;
//是否顯示垂直分割線
pickerView.showVerticalDivisionLine = YES;
//設定pickerView四周的間距
pickerView.edgeInsets = UIEdgeInsetsMake(0, 20, 0, 20);
//設定component之間的間距
pickerView.spacingOfComponents = 30;
//僅在文字模式下有效
pickerView.textColor = kLightTextColor;
pickerView.selectedTextColor = kGlobalColor;
pickerView.font = [UIFont systemFontOfSize:16];
...
[self.view addSubview:pickerView];
複製程式碼
- 通用資料來源及代理方法
#pragma mark - STDPickerViewDataSource
//返回component數目
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
//返回row數目
- (NSInteger)pickerView:(STDPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return self.items.count;
}
#pragma mark - STDPickerViewDelegate
//返回條目高度
- (CGFloat)pickerView:(STDPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 60;
}
//選中了某個條目
- (void)pickerView:(STDPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSLog(@"pickerView - didSelectRow %zd inComponent %zd", row, component);
}
//若selectionIndicatorStyle = STDPickerViewSelectionIndicatorStyleCustom,則需實現以下方法
- (UIView *)selectionIndicatorViewInPickerView:(STDPickerView *)pickerView
{
UIView *view = [[UIView alloc] init];
view.backgroundColor = kGlobalColorWithAlpha(0.3);
view.layer.cornerRadius = 5;
view.layer.masksToBounds = YES;
return view;
}
...
複製程式碼
- 預設選中樣式
#pragma mark - STDPickerViewDataSource
// 返回item的標題
(注:若同時實現了 pickerView: viewForRow:forComponent:reusingView: 優先採用後者,此時可通過設定 forceItemTypeText = YES 來強制使用本方法)
- (NSString *)pickerView:(STDPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return self.items[row];
}
複製程式碼
- 自定義選中樣式
#pragma mark - STDPickerViewDataSource
// 返回item的自定義view,優先順序較高
(注:若同時實現了 pickerView: titleForRow:forComponent: 且 forceItemTypeText = YES 則本方法無效)
- (UIView *)pickerView:(STDPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label = (UILabel *)view;
if (!label) {
label = [[UILabel alloc] init];
label.textAlignment = NSTextAlignmentCenter;
}
label.textColor = kLightTextColor;
label.transform = CGAffineTransformIdentity;
label.text = self.items[row];
return label;
}
#pragma mark - STDPickerViewDelegate
//可在此方法及willDeselectRow中實現自定義的切換效果
- (void)pickerView:(STDPickerView *)pickerView willSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
UILabel *label = (UILabel *)[pickerView viewForRow:row forComponent:component];
[UIView animateWithDuration:0.25 animations:^{
label.transform = CGAffineTransformMakeScale(1.5, 1.5);
}];
label.textColor = kGlobalColor;
}
- (void)pickerView:(STDPickerView *)pickerView willDeselectRow:(NSInteger)row inComponent:(NSInteger)component
{
UILabel *label = (UILabel *)[pickerView viewForRow:row forComponent:component];
[UIView animateWithDuration:0.25 animations:^{
label.transform = CGAffineTransformIdentity;
}];
label.textColor = kLightTextColor;
}
複製程式碼
目前 STDPickerView 已經開源到GitHub上並支援CocoaPods整合,歡迎大家下載與star!
GitHub: https://github.com/XuQibin/STDPickerView