【问题标题】:is there a uipickerview delegate method like scrollviewDidScroll?是否有像 scrollviewDidScroll 这样的 uipickerview 委托方法?
【发布时间】:2011-10-02 09:40:46
【问题描述】:

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

谢谢

【问题讨论】:

    标签: iphone uipickerview delegatecommand


    【解决方案1】:

    使用以下方法,

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

    我希望这个技巧能解决你的问题。尽管让我知道您对此的反馈。

    【讨论】:

    • 我已经知道这种方法了。问题是它在选择器停止滚动时触发,我需要在它仍在滚动时回调。
    • 谢谢!我不知道 titleForRow 在滚动时被调用了。
    • 当我使用viewForRow - titleForRow 没有被调用,所以我使用viewForRow 来检测滚动。有效!
    【解决方案2】:

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

    1. 将属性作为isScrolling
    2. func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? 或等效方法中将isScrolling 设置为true
    3. func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) 中设置 isScrolling 为 false

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

    【讨论】:

    • 将第(3)号中的“Set isScrolling to true”修复为“Set isScrolling to false”。
    【解决方案3】:

    必须使用这两个 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行

    【讨论】:

      【解决方案4】:

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

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

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

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

      【讨论】:

        【解决方案5】:

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

        试一试

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-24
          相关资源
          最近更新 更多