是否有像scrollviewDidScroll这样的uipickerview委托方法?

时间:2011-10-02 09:40:46

标签: iphone uipickerview delegatecommand

我有一个自定义的UIPickerview,我不想使用datepicker。我想实现这样的功能:当用户向下/向上滚动小时时,AM / PM组件在小时滚动时切换。这意味着我需要在调用pickerView didSelectRow之前切换它。有没有办法做到这一点?

由于

5 个答案:

答案 0 :(得分:13)

使用以下方法,

- (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将被调用。

我希望这个技巧可以解决你的问题。尽管如此,请告诉我你对此的反馈。

答案 1 :(得分:3)

必须为事件使用这两个UIPickerView委托方法:

DID END SCROLL:

- (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或忽略第一个willstart滚动显示可见的piker行时你必须实现一个假的didendscroll事件

答案 2 :(得分:2)

有一个技巧可以检测到这个但是没有委托方法/属性来检测它是否滚动

  1. 以isScrolling
  2. 取得财产
  3. func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?或等效方法
  4. 中将isScrolling设置为true
  5. func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
  6. 中将isScrolling设置为false

    希望这会有所帮助,顺便说一句,这就是所有上述答案中所解释的内容

答案 3 :(得分:2)

不幸的是,上面的解决方案(在调用titleForRow等数据源方法时设置一个标志,并在调用didSelectRow时重置它)是粗略的,并且在许多情况下不起作用。在许多没有用户滚动的情况下可以调用数据源方法 - 例如UI更改导致更改视图布局,也可以在didSelectRow之后立即调用 - 您无法控制何时调用这些方法。 / p>

关于这个特定问题,这些解决方案可能有效,因为滚动时总是会调用这些方法 - 只是在滚动时才会调用。但是,需要注意不要假设用户必须在这些情况下滚动。此外,如果您使用此标志管理状态机(例如在滚动时禁用某个按钮并在之后启用它),您将遇到麻烦。

最后,这只允许检测滚动(具有上述警告),但它不会告诉您速度或当前值 - 因此很难判断何时切换AM / PM标签。

我能够可靠地检测滚动的唯一方法是通过我在UI更改时设置的一堆标志和其他丑陋的黑客(比如在尝试再次检测滚动之前在didSelectRow之后等待100毫秒,因为我注意到了在didSelectRow之后立即调用数据源。将willScroll / didScroll方法添加到委托似乎是Apple忽略添加的一个显而易见的事情。

答案 4 :(得分:0)

我刚刚找到一种实现“ 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];
}

尝试一下