Skip to content

Commit 09e82e1

Browse files
committed
fix #304 #305
1 parent 3a65de1 commit 09e82e1

File tree

8 files changed

+159
-23
lines changed

8 files changed

+159
-23
lines changed

BRPickerView/AddressPickerView/BRAddressPickerView.h

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ typedef void(^BRAddressResultBlock)(BRProvinceModel * _Nullable province, BRCity
4848
/** 滚动选择时触发的回调 */
4949
@property (nullable, nonatomic, copy) BRAddressResultBlock changeBlock;
5050

51+
/** 判断选择器是否处于滚动中。可以用于解决快速滑动选择器,在滚动结束前秒选确定按钮,出现显示不对的问题。*/
52+
@property (nonatomic, readonly, assign, getter=isRolling) BOOL rolling;
53+
5154
/**
5255
* 地区数据源(不传或为nil,默认就获取本地 BRCity.json 文件的数据)
5356
* 1.可以传 JSON数组,要注意 层级结构 和 key 要与 BRCity.json 保持一致

BRPickerView/AddressPickerView/BRAddressPickerView.m

+47-3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ @interface BRAddressPickerView ()<UIPickerViewDataSource, UIPickerViewDelegate>
3232
// 记录区选中的位置
3333
@property(nonatomic, assign) NSInteger areaIndex;
3434

35+
// 记录滚动中的位置
36+
@property(nonatomic, assign) NSInteger rollingComponent;
37+
@property(nonatomic, assign) NSInteger rollingRow;
38+
3539
@property (nonatomic, copy) NSArray <NSString *>* mSelectValues;
3640

3741
@end
@@ -256,7 +260,7 @@ - (UIPickerView *)pickerView {
256260
}
257261

258262
#pragma mark - UIPickerViewDataSource
259-
// 1.设置 pickerView 的列数
263+
// 1.返回组件数量
260264
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
261265
switch (self.pickerMode) {
262266
case BRAddressPickerModeProvince:
@@ -274,7 +278,7 @@ - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
274278
}
275279
}
276280

277-
// 2.设置 pickerView 每列的行数
281+
// 2.返回每个组件的行数
278282
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
279283
if (component == 0) {
280284
// 返回省个数
@@ -321,9 +325,41 @@ - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forC
321325
// 2.设置选择器中间选中行的样式
322326
[self.pickerStyle setupPickerSelectRowStyle:pickerView titleForRow:row forComponent:component];
323327

328+
// 3.记录选择器滚动过程中选中的列和行
329+
// 获取选择器组件滚动中选中的行
330+
NSInteger selectRow = [pickerView selectedRowInComponent:component];
331+
if (selectRow >= 0) {
332+
self.rollingComponent = component;
333+
self.rollingRow = selectRow;
334+
}
335+
324336
return label;
325337
}
326338

339+
// 获取选择器是否滚动中状态
340+
- (BOOL)getRollingStatus:(UIView *)view {
341+
if ([view isKindOfClass:[UIScrollView class]]) {
342+
UIScrollView *scrollView = (UIScrollView *)view;
343+
if (scrollView.dragging || scrollView.decelerating) {
344+
// 如果 UIPickerView 正在拖拽或正在减速,返回YES
345+
return YES;
346+
}
347+
}
348+
349+
for (UIView *subView in view.subviews) {
350+
if ([self getRollingStatus:subView]) {
351+
return YES;
352+
}
353+
}
354+
355+
return NO;
356+
}
357+
358+
// 选择器是否正在滚动
359+
- (BOOL)isRolling {
360+
return [self getRollingStatus:self.pickerView];
361+
}
362+
327363
// 4.滚动 pickerView 执行的回调方法
328364
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
329365
if (component == 0) { // 选择省
@@ -461,8 +497,16 @@ - (void)addPickerToView:(UIView *)view {
461497
[self reloadData];
462498

463499
__weak typeof(self) weakSelf = self;
500+
// 点击确定按钮的回调:点击确定按钮后,执行这个block回调
464501
self.doneBlock = ^{
465-
// 点击确定按钮后,执行block回调
502+
if (weakSelf.isRolling) {
503+
NSLog(@"选择器滚动还未结束");
504+
// 问题:如果滚动选择器过快,然后在滚动过程中快速点击确定按钮,会导致 didSelectRow 代理方法还没有执行,出现没有选中的情况。
505+
// 解决:这里手动处理一下,如果滚动还未结束,强制执行一次 didSelectRow 代理方法,选择当前滚动的行。
506+
[weakSelf pickerView:weakSelf.pickerView didSelectRow:weakSelf.rollingRow inComponent:weakSelf.rollingComponent];
507+
}
508+
509+
// 执行选择结果回调
466510
if (weakSelf.resultBlock) {
467511
weakSelf.resultBlock(weakSelf.selectProvinceModel, weakSelf.selectCityModel, weakSelf.selectAreaModel);
468512
}

BRPickerView/DatePickerView/BRDatePickerView.h

+3
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ typedef void (^BRDateResultRangeBlock)(NSDate * _Nullable selectStartDate, NSDat
102102
/** 滚动选择范围时触发的回调:for `BRDatePickerModeYQ`、`BRDatePickerModeYMW`、`BRDatePickerModeYW`, ignored otherwise. */
103103
@property (nullable, nonatomic, copy) BRDateResultRangeBlock changeRangeBlock;
104104

105+
/** 判断选择器是否处于滚动中。可以用于解决快速滑动选择器,在滚动结束前秒选确定按钮,出现显示不对的问题。*/
106+
@property (nonatomic, readonly, assign, getter=isRolling) BOOL rolling;
107+
105108
/** 日期单位显示类型 */
106109
@property (nonatomic, assign) BRShowUnitType showUnitType;
107110

BRPickerView/DatePickerView/BRDatePickerView.m

+54-4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ @interface BRDatePickerView ()<UIPickerViewDataSource, UIPickerViewDelegate>
5454
@property(nonatomic, assign) NSInteger yearWeekIndex;
5555
@property(nonatomic, assign) NSInteger quarterIndex;
5656

57+
// 记录滚动中的位置
58+
@property(nonatomic, assign) NSInteger rollingComponent;
59+
@property(nonatomic, assign) NSInteger rollingRow;
60+
5761
// 记录选择的值
5862
@property (nonatomic, strong) NSDate *mSelectDate;
5963
@property (nonatomic, copy) NSString *mSelectValue;
@@ -757,7 +761,7 @@ - (UIPickerView *)pickerView {
757761
}
758762

759763
#pragma mark - UIPickerViewDataSource
760-
// 1.设置 pickerView 的列数
764+
// 1.返回组件数量
761765
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
762766
if (self.pickerMode == BRDatePickerModeYMDHMS) {
763767
return 6;
@@ -791,7 +795,7 @@ - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
791795
return 0;
792796
}
793797

794-
// 2.设置 pickerView 每列的行数
798+
// 2.返回每个组件的行数
795799
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
796800
NSArray *rowsArr = [NSArray array];
797801
if (self.pickerMode == BRDatePickerModeYMDHMS) {
@@ -857,10 +861,19 @@ - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forC
857861

858862
// 2.设置选择器中间选中行的样式
859863
[self.pickerStyle setupPickerSelectRowStyle:pickerView titleForRow:row forComponent:component];
864+
865+
// 3.记录选择器滚动过程中选中的列和行
866+
// 获取选择器组件滚动中选中的行
867+
NSInteger selectRow = [pickerView selectedRowInComponent:component];
868+
if (selectRow >= 0) {
869+
self.rollingComponent = component;
870+
self.rollingRow = selectRow;
871+
}
860872

861873
return label;
862874
}
863875

876+
// 返回每行的标题
864877
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
865878
NSString *titleString = @"";
866879
if (self.pickerMode == BRDatePickerModeYMDHMS) {
@@ -978,7 +991,36 @@ - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row f
978991
return titleString;
979992
}
980993

981-
// 4.滚动 pickerView 执行的回调方法
994+
// 获取选择器是否滚动中状态
995+
- (BOOL)getRollingStatus:(UIView *)view {
996+
if ([view isKindOfClass:[UIScrollView class]]) {
997+
UIScrollView *scrollView = (UIScrollView *)view;
998+
if (scrollView.dragging || scrollView.decelerating) {
999+
// 如果 UIPickerView 正在拖拽或正在减速,返回YES
1000+
return YES;
1001+
}
1002+
}
1003+
1004+
for (UIView *subView in view.subviews) {
1005+
if ([self getRollingStatus:subView]) {
1006+
return YES;
1007+
}
1008+
}
1009+
1010+
return NO;
1011+
}
1012+
1013+
// 选择器是否正在滚动
1014+
- (BOOL)isRolling {
1015+
if (self.style == BRDatePickerStyleSystem) {
1016+
return [self getRollingStatus:self.datePicker];
1017+
} else if (self.style == BRDatePickerStyleCustom) {
1018+
return [self getRollingStatus:self.pickerView];
1019+
}
1020+
return NO;
1021+
}
1022+
1023+
// 4.滚动 pickerView 完成,执行的回调方法
9821024
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
9831025
NSString *lastSelectValue = self.mSelectValue;
9841026
NSDate *lastSelectDate = self.mSelectDate;
@@ -1626,8 +1668,16 @@ - (void)addPickerToView:(UIView *)view {
16261668
[self reloadData];
16271669

16281670
__weak typeof(self) weakSelf = self;
1671+
// 点击确定按钮的回调:点击确定按钮后,执行这个block回调
16291672
self.doneBlock = ^{
1630-
// 点击确定按钮后,执行block回调
1673+
if (weakSelf.isRolling) {
1674+
NSLog(@"选择器滚动还未结束");
1675+
// 问题:如果滚动选择器过快,然后在滚动过程中快速点击确定按钮,会导致 didSelectRow 代理方法还没有执行,出现没有选中的情况。
1676+
// 解决:这里手动处理一下,如果滚动还未结束,强制执行一次 didSelectRow 代理方法,选择当前滚动的行。
1677+
[weakSelf pickerView:weakSelf.pickerView didSelectRow:weakSelf.rollingRow inComponent:weakSelf.rollingComponent];
1678+
}
1679+
1680+
// 执行选择结果回调
16311681
if (weakSelf.resultBlock) {
16321682
weakSelf.resultBlock(weakSelf.mSelectDate, weakSelf.mSelectValue);
16331683
}

BRPickerView/StringPickerView/BRStringPickerView.h

+3
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ typedef void(^BRStringResultModelArrayBlock)(NSArray <BRResultModel *> * _Nullab
7777
/** 滚动选择时触发的回调【多列】 */
7878
@property (nullable, nonatomic, copy) BRStringResultModelArrayBlock changeModelArrayBlock;
7979

80+
/** 判断选择器是否处于滚动中。可以用于解决快速滑动选择器,在滚动结束前秒选确定按钮,出现显示不对的问题。*/
81+
@property (nonatomic, readonly, assign, getter=isRolling) BOOL rolling;
82+
8083
/**
8184
* 最大层级数(列数) for `BRStringPickerComponentLinkage`, ignored otherwise.
8285
* 使用场景:默认可选,当数据源中有 key 等于 parentKey 情况时,必须要设置

BRPickerView/StringPickerView/BRStringPickerView.m

+47-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ @interface BRStringPickerView ()<UIPickerViewDelegate, UIPickerViewDataSource>
2020
/** 多列选择的值 */
2121
@property (nonatomic, copy) NSArray <NSString *>* mSelectValues;
2222

23+
// 记录滚动中的位置
24+
@property(nonatomic, assign) NSInteger rollingComponent;
25+
@property(nonatomic, assign) NSInteger rollingRow;
26+
2327
/** 数据源 */
2428
@property (nullable, nonatomic, copy) NSArray *mDataSourceArr;
2529

@@ -249,7 +253,7 @@ - (UIPickerView *)pickerView {
249253
}
250254

251255
#pragma mark - UIPickerViewDataSource
252-
// 1.设置 pickerView 的列数
256+
// 1.返回组件数量
253257
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
254258
switch (self.pickerMode) {
255259
case BRStringPickerComponentSingle:
@@ -265,7 +269,7 @@ - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
265269
}
266270
}
267271

268-
// 2.设置 pickerView 每列的行数
272+
// 2.返回每个组件的行数
269273
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
270274
switch (self.pickerMode) {
271275
case BRStringPickerComponentSingle:
@@ -322,9 +326,41 @@ - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forC
322326
// 2.设置选择器中间选中行的样式
323327
[self.pickerStyle setupPickerSelectRowStyle:pickerView titleForRow:row forComponent:component];
324328

329+
// 3.记录选择器滚动过程中选中的列和行
330+
// 获取选择器组件滚动中选中的行
331+
NSInteger selectRow = [pickerView selectedRowInComponent:component];
332+
if (selectRow >= 0) {
333+
self.rollingComponent = component;
334+
self.rollingRow = selectRow;
335+
}
336+
325337
return label;
326338
}
327339

340+
// 获取选择器是否滚动中状态
341+
- (BOOL)getRollingStatus:(UIView *)view {
342+
if ([view isKindOfClass:[UIScrollView class]]) {
343+
UIScrollView *scrollView = (UIScrollView *)view;
344+
if (scrollView.dragging || scrollView.decelerating) {
345+
// 如果 UIPickerView 正在拖拽或正在减速,返回YES
346+
return YES;
347+
}
348+
}
349+
350+
for (UIView *subView in view.subviews) {
351+
if ([self getRollingStatus:subView]) {
352+
return YES;
353+
}
354+
}
355+
356+
return NO;
357+
}
358+
359+
// 选择器是否正在滚动
360+
- (BOOL)isRolling {
361+
return [self getRollingStatus:self.pickerView];
362+
}
363+
328364
// 4.滚动 pickerView 执行的回调方法
329365
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
330366
switch (self.pickerMode) {
@@ -492,8 +528,16 @@ - (void)addPickerToView:(UIView *)view {
492528
[self reloadData];
493529

494530
__weak typeof(self) weakSelf = self;
531+
// 点击确定按钮的回调:点击确定按钮后,执行这个block回调
495532
self.doneBlock = ^{
496-
// 点击确定按钮后,执行block回调
533+
if (weakSelf.isRolling) {
534+
NSLog(@"选择器滚动还未结束");
535+
// 问题:如果滚动选择器过快,然后在滚动过程中快速点击确定按钮,会导致 didSelectRow 代理方法还没有执行,出现没有选中的情况。
536+
// 解决:这里手动处理一下,如果滚动还未结束,强制执行一次 didSelectRow 代理方法,选择当前滚动的行。
537+
[weakSelf pickerView:weakSelf.pickerView didSelectRow:weakSelf.rollingRow inComponent:weakSelf.rollingComponent];
538+
}
539+
540+
// 执行选择结果回调
497541
if (weakSelf.pickerMode == BRStringPickerComponentSingle) {
498542
if (weakSelf.resultModelBlock) {
499543
weakSelf.resultModelBlock([weakSelf getResultModel]);

BRPickerViewDemo/Classes/Demo/Controller/TestViewController.m

+1-12
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,9 @@ - (void)handlerTextFieldSelect:(UITextField *)textField {
318318
self.birthdaySelectDate = selectDate;
319319
self.infoModel.birthdayStr = selectValue;
320320
textField.text = selectValue;
321-
322321
NSLog(@"selectValue=%@", selectValue);
323322
NSLog(@"selectDate=%@", selectDate);
324323
NSLog(@"---------------------------------");
325-
326324
};
327325

328326
datePickerView.resultRangeBlock = ^(NSDate * _Nullable selectStartDate, NSDate * _Nullable selectEndDate, NSString * _Nullable selectValue) {
@@ -713,7 +711,7 @@ - (UIView *)footerView {
713711
_footerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
714712

715713
// 1.切换日期选择器的显示模式
716-
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"年月日时", @"年月日", @"年月", @"月周", @"年周", @"季 度"]];
714+
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"年月日时", @"年月日", @"年月"]];
717715
segmentedControl.frame = CGRectMake(40, 50, self.view.bounds.size.width - 80, 36);
718716
segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
719717
segmentedControl.apportionsSegmentWidthsByContent = YES;
@@ -838,15 +836,6 @@ - (void)pickerModeSegmentedControlAction:(UISegmentedControl *)sender {
838836
} else if (selecIndex == 2) {
839837
NSLog(@"年月");
840838
self.datePickerView.pickerMode = BRDatePickerModeYM;
841-
} else if (selecIndex == 3) {
842-
NSLog(@"年月");
843-
self.datePickerView.pickerMode = BRDatePickerModeYMW;
844-
} else if (selecIndex == 4) {
845-
NSLog(@"年月");
846-
self.datePickerView.pickerMode = BRDatePickerModeYW;
847-
} else if (selecIndex == 5) {
848-
NSLog(@"年月");
849-
self.datePickerView.pickerMode = BRDatePickerModeYQ;
850839
}
851840

852841
// 重置选择的值

BRPickerViewDemo/Classes/Other/BRMutableDatePickerView/BRMutableDatePickerView.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ - (void)scrollToSelectDate:(NSDate *)selectDate animated:(BOOL)animated {
569569
}
570570

571571
#pragma mark - UIPickerViewDataSource
572-
// 1. 设置 picker 的列数
572+
// 1.返回组件数量
573573
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
574574
return 3;
575575
}

0 commit comments

Comments
 (0)