我有一个自定义的 UIPickerview,我不想使用日期选择器。我想实现当用户向下/向上滚动小时时,AM/PM 组件在小时滚动时切换的功能。这意味着我需要在调用 pickerView didSelectRow 之前切换它。有没有办法做到这一点?
谢谢
我有一个自定义的 UIPickerview,我不想使用日期选择器。我想实现当用户向下/向上滚动小时时,AM/PM 组件在小时滚动时切换的功能。这意味着我需要在调用 pickerView didSelectRow 之前切换它。有没有办法做到这一点?
谢谢
使用以下方法,
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
// put your logic here.
}
以上方法来自 UIPickerViewDelegate,如果用户使用 pickerview 选择任何元素,该方法会自动触发。
希望对您有所帮助。
编辑:
我认为您应该使用以下方法来检测 - 用户在哪个方向滚动?
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
NSLog(@"scrolling to row is %@",[NSString stringWithFormat:@"index_%i",row]);
return [NSString stringWithFormat:@"index_%i",row];
}
每当用户向上/向下滚动时,上述方法都会自动触发,类似于UITableView
. 请记住UIPickerView
使用UIPickerTableView
哪个是私有的,因此我们无法检测到您想要的滚动方式。
让我解释一下在pickerview中检测方向。
例子。可见行是index_4,index_5,index_6,index_7
. 现在如果用户向下滚动index_8
将被调用。同样,如果用户向上滚动index_3
将被调用。
我希望这个技巧能解决你的问题。即使让我知道您对此的反馈。
有一个技巧可以检测到这一点,但是没有委托方法/属性来检测它是否滚动
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
或等效方法中将 isScrolling 设置为 truefunc pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
希望这会有所帮助,顺便说一句,这是上述所有答案中所解释的
必须对事件使用这两个 UIPickerView 委托方法:
是否结束滚动:
- (void)pickerView:(UIPickerView *)pV didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSLog(@"pickerView didSelectRow %zd",row);
// DID END SCROLL: CALL YOUR HEANDLER METHOD!!
}
将开始滚动:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
// WILL START SCROLLING: CALL YOUR HEANDLER METHOD!!
UILabel* label = (UILabel*)view;
if (!label){
label = [UILabel new];
[label setFrame:frame];
[label setBackgroundColor:[UIColor clearColor]];
[label setFont:[UIFont fontWithName:FONT_QUICKSAND_BOLD size:12]];
[label setTextAlignment:NSTextAlignmentRight];
[label setLineBreakMode:NSLineBreakByTruncatingMiddle];
[label setTextColor:UIColorFromRGB(0X2692ff)];
}
//Update labeltext here
[label setText:[NSString stringWithFormat:@"row %zd",row]];
return label;
}
显然,除了 UIPickerview 的构建(firstTIME!);所以当你完成构建你的 piker 时你必须实现一个假的 didendscroll 事件,或者首先忽略将开始滚动可见的 piker 行
不幸的是,上述解决方案(在调用 titleForRow 等数据源方法时设置标志并在调用 didSelectRow 时重置它)是粗略的,并且在许多情况下都不起作用。在用户没有滚动的许多情况下,可能会调用数据源方法 - 例如 UI 更改导致更改视图布局,也可能在 didSelectRow 之后立即调用 - 您无法控制何时调用这些方法。
关于这个特定问题,这些解决方案可能会起作用,因为这些方法总是在滚动时调用 - 不仅仅是在滚动时。但是,需要注意不要假设用户必须在这些情况下滚动。此外,如果您使用此标志管理状态机(例如在滚动时禁用某些按钮并在之后启用它),您将遇到麻烦。
最后,这只允许检测滚动(带有上述警告),但它不会告诉您速度或当前值 - 因此很难判断何时切换 AM/PM 标签。
我能够可靠地检测到滚动的唯一方法是通过我在进行 UI 更改时设置的一堆标志和其他丑陋的 hack(比如在 didSelectRow 之后等待 100 毫秒,然后再尝试再次检测滚动,因为我注意到调用紧接在 didSelectRow 之后的数据源)。向委托添加 willScroll/didScroll 方法似乎是 Apple 忽略添加的一个明显的事情。
我刚刚找到了一种实现“pickerDidScroll”的方法,它工作正常。关键点是将 KVO 添加到行视图中。这是我的代码:
//picker view delegate
- (UIView*)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
if (!view) {
view = [[RatchetScrollUnit alloc] initWithFrame:CGRectZero];
//
[((RatchetScrollUnit*)view) addRatchetObserver:self];
}
return view;
}
//KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if (self.ratchet) {
NSInteger row = [self.ratchet selectedRowInComponent:0];
if (row != _lastRow) {
_lastRow = row;
if (self.delegate && [self.delegate respondsToSelector:@selector(ratchetScrollerDidRatchetedToTooth:)]) {
[self.delegate ratchetScrollerDidRatchetedToTooth:row];
}
}
}
}
“RatchetScrollUnit”类:
@interface RatchetScrollUnit ()
@property (nonatomic,assign) BOOL observed;
@property (nonatomic,weak) NSObject *myObserver;
@end
@implementation RatchetScrollUnit
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_observed = NO;
self.backgroundColor = [UIColor clearColor];
}
return self;
}
- (void)dealloc {
if (self.observed) {
[self removeObserver:self.myObserver forKeyPath:@"frame" context:nil];
}
}
- (void)addRatchetObserver:(NSObject*)observer {
if (self.observed) {
return;
}
self.observed = YES;
self.myObserver = observer;
//
[self addObserver:observer
forKeyPath:@"frame"
options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew
context:nil];
}
试试