Skip to content

Commit

Permalink
fix #304 #305
Browse files Browse the repository at this point in the history
  • Loading branch information
agiapp committed Apr 26, 2024
1 parent 3a65de1 commit 09e82e1
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 23 deletions.
3 changes: 3 additions & 0 deletions BRPickerView/AddressPickerView/BRAddressPickerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ typedef void(^BRAddressResultBlock)(BRProvinceModel * _Nullable province, BRCity
/** 滚动选择时触发的回调 */
@property (nullable, nonatomic, copy) BRAddressResultBlock changeBlock;

/** 判断选择器是否处于滚动中。可以用于解决快速滑动选择器,在滚动结束前秒选确定按钮,出现显示不对的问题。*/
@property (nonatomic, readonly, assign, getter=isRolling) BOOL rolling;

/**
* 地区数据源(不传或为nil,默认就获取本地 BRCity.json 文件的数据)
* 1.可以传 JSON数组,要注意 层级结构 和 key 要与 BRCity.json 保持一致
Expand Down
50 changes: 47 additions & 3 deletions BRPickerView/AddressPickerView/BRAddressPickerView.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ @interface BRAddressPickerView ()<UIPickerViewDataSource, UIPickerViewDelegate>
// 记录区选中的位置
@property(nonatomic, assign) NSInteger areaIndex;

// 记录滚动中的位置
@property(nonatomic, assign) NSInteger rollingComponent;
@property(nonatomic, assign) NSInteger rollingRow;

@property (nonatomic, copy) NSArray <NSString *>* mSelectValues;

@end
Expand Down Expand Up @@ -256,7 +260,7 @@ - (UIPickerView *)pickerView {
}

#pragma mark - UIPickerViewDataSource
// 1.设置 pickerView 的列数
// 1.返回组件数量
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
switch (self.pickerMode) {
case BRAddressPickerModeProvince:
Expand All @@ -274,7 +278,7 @@ - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
}
}

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

// 3.记录选择器滚动过程中选中的列和行
// 获取选择器组件滚动中选中的行
NSInteger selectRow = [pickerView selectedRowInComponent:component];
if (selectRow >= 0) {
self.rollingComponent = component;
self.rollingRow = selectRow;
}

return label;
}

// 获取选择器是否滚动中状态
- (BOOL)getRollingStatus:(UIView *)view {
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollView = (UIScrollView *)view;
if (scrollView.dragging || scrollView.decelerating) {
// 如果 UIPickerView 正在拖拽或正在减速,返回YES
return YES;
}
}

for (UIView *subView in view.subviews) {
if ([self getRollingStatus:subView]) {
return YES;
}
}

return NO;
}

// 选择器是否正在滚动
- (BOOL)isRolling {
return [self getRollingStatus:self.pickerView];
}

// 4.滚动 pickerView 执行的回调方法
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if (component == 0) { // 选择省
Expand Down Expand Up @@ -461,8 +497,16 @@ - (void)addPickerToView:(UIView *)view {
[self reloadData];

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

// 执行选择结果回调
if (weakSelf.resultBlock) {
weakSelf.resultBlock(weakSelf.selectProvinceModel, weakSelf.selectCityModel, weakSelf.selectAreaModel);
}
Expand Down
3 changes: 3 additions & 0 deletions BRPickerView/DatePickerView/BRDatePickerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ typedef void (^BRDateResultRangeBlock)(NSDate * _Nullable selectStartDate, NSDat
/** 滚动选择范围时触发的回调:for `BRDatePickerModeYQ`、`BRDatePickerModeYMW`、`BRDatePickerModeYW`, ignored otherwise. */
@property (nullable, nonatomic, copy) BRDateResultRangeBlock changeRangeBlock;

/** 判断选择器是否处于滚动中。可以用于解决快速滑动选择器,在滚动结束前秒选确定按钮,出现显示不对的问题。*/
@property (nonatomic, readonly, assign, getter=isRolling) BOOL rolling;

/** 日期单位显示类型 */
@property (nonatomic, assign) BRShowUnitType showUnitType;

Expand Down
58 changes: 54 additions & 4 deletions BRPickerView/DatePickerView/BRDatePickerView.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ @interface BRDatePickerView ()<UIPickerViewDataSource, UIPickerViewDelegate>
@property(nonatomic, assign) NSInteger yearWeekIndex;
@property(nonatomic, assign) NSInteger quarterIndex;

// 记录滚动中的位置
@property(nonatomic, assign) NSInteger rollingComponent;
@property(nonatomic, assign) NSInteger rollingRow;

// 记录选择的值
@property (nonatomic, strong) NSDate *mSelectDate;
@property (nonatomic, copy) NSString *mSelectValue;
Expand Down Expand Up @@ -757,7 +761,7 @@ - (UIPickerView *)pickerView {
}

#pragma mark - UIPickerViewDataSource
// 1.设置 pickerView 的列数
// 1.返回组件数量
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
if (self.pickerMode == BRDatePickerModeYMDHMS) {
return 6;
Expand Down Expand Up @@ -791,7 +795,7 @@ - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 0;
}

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

// 2.设置选择器中间选中行的样式
[self.pickerStyle setupPickerSelectRowStyle:pickerView titleForRow:row forComponent:component];

// 3.记录选择器滚动过程中选中的列和行
// 获取选择器组件滚动中选中的行
NSInteger selectRow = [pickerView selectedRowInComponent:component];
if (selectRow >= 0) {
self.rollingComponent = component;
self.rollingRow = selectRow;
}

return label;
}

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

// 4.滚动 pickerView 执行的回调方法
// 获取选择器是否滚动中状态
- (BOOL)getRollingStatus:(UIView *)view {
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollView = (UIScrollView *)view;
if (scrollView.dragging || scrollView.decelerating) {
// 如果 UIPickerView 正在拖拽或正在减速,返回YES
return YES;
}
}

for (UIView *subView in view.subviews) {
if ([self getRollingStatus:subView]) {
return YES;
}
}

return NO;
}

// 选择器是否正在滚动
- (BOOL)isRolling {
if (self.style == BRDatePickerStyleSystem) {
return [self getRollingStatus:self.datePicker];
} else if (self.style == BRDatePickerStyleCustom) {
return [self getRollingStatus:self.pickerView];
}
return NO;
}

// 4.滚动 pickerView 完成,执行的回调方法
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *lastSelectValue = self.mSelectValue;
NSDate *lastSelectDate = self.mSelectDate;
Expand Down Expand Up @@ -1626,8 +1668,16 @@ - (void)addPickerToView:(UIView *)view {
[self reloadData];

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

// 执行选择结果回调
if (weakSelf.resultBlock) {
weakSelf.resultBlock(weakSelf.mSelectDate, weakSelf.mSelectValue);
}
Expand Down
3 changes: 3 additions & 0 deletions BRPickerView/StringPickerView/BRStringPickerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ typedef void(^BRStringResultModelArrayBlock)(NSArray <BRResultModel *> * _Nullab
/** 滚动选择时触发的回调【多列】 */
@property (nullable, nonatomic, copy) BRStringResultModelArrayBlock changeModelArrayBlock;

/** 判断选择器是否处于滚动中。可以用于解决快速滑动选择器,在滚动结束前秒选确定按钮,出现显示不对的问题。*/
@property (nonatomic, readonly, assign, getter=isRolling) BOOL rolling;

/**
* 最大层级数(列数) for `BRStringPickerComponentLinkage`, ignored otherwise.
* 使用场景:默认可选,当数据源中有 key 等于 parentKey 情况时,必须要设置
Expand Down
50 changes: 47 additions & 3 deletions BRPickerView/StringPickerView/BRStringPickerView.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ @interface BRStringPickerView ()<UIPickerViewDelegate, UIPickerViewDataSource>
/** 多列选择的值 */
@property (nonatomic, copy) NSArray <NSString *>* mSelectValues;

// 记录滚动中的位置
@property(nonatomic, assign) NSInteger rollingComponent;
@property(nonatomic, assign) NSInteger rollingRow;

/** 数据源 */
@property (nullable, nonatomic, copy) NSArray *mDataSourceArr;

Expand Down Expand Up @@ -249,7 +253,7 @@ - (UIPickerView *)pickerView {
}

#pragma mark - UIPickerViewDataSource
// 1.设置 pickerView 的列数
// 1.返回组件数量
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
switch (self.pickerMode) {
case BRStringPickerComponentSingle:
Expand All @@ -265,7 +269,7 @@ - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
}
}

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

// 3.记录选择器滚动过程中选中的列和行
// 获取选择器组件滚动中选中的行
NSInteger selectRow = [pickerView selectedRowInComponent:component];
if (selectRow >= 0) {
self.rollingComponent = component;
self.rollingRow = selectRow;
}

return label;
}

// 获取选择器是否滚动中状态
- (BOOL)getRollingStatus:(UIView *)view {
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollView = (UIScrollView *)view;
if (scrollView.dragging || scrollView.decelerating) {
// 如果 UIPickerView 正在拖拽或正在减速,返回YES
return YES;
}
}

for (UIView *subView in view.subviews) {
if ([self getRollingStatus:subView]) {
return YES;
}
}

return NO;
}

// 选择器是否正在滚动
- (BOOL)isRolling {
return [self getRollingStatus:self.pickerView];
}

// 4.滚动 pickerView 执行的回调方法
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
switch (self.pickerMode) {
Expand Down Expand Up @@ -492,8 +528,16 @@ - (void)addPickerToView:(UIView *)view {
[self reloadData];

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

// 执行选择结果回调
if (weakSelf.pickerMode == BRStringPickerComponentSingle) {
if (weakSelf.resultModelBlock) {
weakSelf.resultModelBlock([weakSelf getResultModel]);
Expand Down
13 changes: 1 addition & 12 deletions BRPickerViewDemo/Classes/Demo/Controller/TestViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,9 @@ - (void)handlerTextFieldSelect:(UITextField *)textField {
self.birthdaySelectDate = selectDate;
self.infoModel.birthdayStr = selectValue;
textField.text = selectValue;

NSLog(@"selectValue=%@", selectValue);
NSLog(@"selectDate=%@", selectDate);
NSLog(@"---------------------------------");

};

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

// 1.切换日期选择器的显示模式
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"年月日时", @"年月日", @"年月", @"月周", @"年周", @"季 度"]];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"年月日时", @"年月日", @"年月"]];
segmentedControl.frame = CGRectMake(40, 50, self.view.bounds.size.width - 80, 36);
segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
segmentedControl.apportionsSegmentWidthsByContent = YES;
Expand Down Expand Up @@ -838,15 +836,6 @@ - (void)pickerModeSegmentedControlAction:(UISegmentedControl *)sender {
} else if (selecIndex == 2) {
NSLog(@"年月");
self.datePickerView.pickerMode = BRDatePickerModeYM;
} else if (selecIndex == 3) {
NSLog(@"年月");
self.datePickerView.pickerMode = BRDatePickerModeYMW;
} else if (selecIndex == 4) {
NSLog(@"年月");
self.datePickerView.pickerMode = BRDatePickerModeYW;
} else if (selecIndex == 5) {
NSLog(@"年月");
self.datePickerView.pickerMode = BRDatePickerModeYQ;
}

// 重置选择的值
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ - (void)scrollToSelectDate:(NSDate *)selectDate animated:(BOOL)animated {
}

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

0 comments on commit 09e82e1

Please sign in to comment.