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

发布于 2024-12-07 15:04:59 字数 143 浏览 2 评论 0原文

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

谢谢

I have a customized UIPickerview and I do not want to use a datepicker. I want to implement the feature where when a user scrolls down/up the hours, the AM/PM component switches while the hour is scrolling. This means that I need to switch it before pickerView didSelectRow is called. Is there a way to do this?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

苍风燃霜 2024-12-14 15:04:59

使用以下方法,

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

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

Use following method,

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
     // put your logic here.
}

Above method is from UIPickerViewDelegate, If user selects any element using pickerview, this method is automatically triggered.

Hope it helps to you.

Edit :

I think you should use following method for detecting - in which direction user is scrolling ?

- (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];
}

whenever user is scrolling up/down above method is triggered automatically which is similar to UITableView. Remember UIPickerView is using UIPickerTableView which is private, so we can not detect the scrolling the way you want to have.

Let me explain the detecting the direction in pickerview.

Example. Visible rows are index_4,index_5,index_6,index_7. Now if user is scrolling down index_8 will be called. Similarly if user is scrolling to up index_3 will be called.

I hope this trick will solve your problem. Even-though let me know your feedback on this.

若言繁花未落 2024-12-14 15:04:59

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

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

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

There is a trick to detect this but there is no delegate method/ property to detect if its scrolling or not

  1. take a property as isScrolling
  2. set isScrolling to true in func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? or equivalent method
  3. set isScrolling to false in func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)

hope this helps, BTW this is what is explained in all the above mentioned answers

幸福不弃 2024-12-14 15:04:59

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

WILL START SCROLLING:

- (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 事件,或者忽略第一个 willstart 滚动可见的 piker 行

have to use this two UIPickerView delegate method for event:

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!!
}

WILL START SCROLLING:

- (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;
}

obviosly except for the building of UIPickerview (firstTIME!); so u have to implement a fake didendscroll event when you finish to build you piker or ignore first willstart scroll for the visible piker row

可可 2024-12-14 15:04:59

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

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

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

我能够可靠地检测滚动的唯一方法是通过在进行 UI 更改和其他丑陋的黑客时设置的一堆标志(例如在 didSelectRow 之后等待 100 毫秒,然后再次尝试检测滚动,因为我注意到对紧接在 didSelectRow 之后的数据源)。向委托添加 willScroll/didScroll 方法似乎是苹果忽略添加的一个明显的事情。

Unfortunately, the above solutions (setting a flag when data source methods such as titleForRow are called and resetting it when didSelectRow is called) are sketchy and won't work in many cases. The data source methods may be called in many cases where there is no scrolling by the user - such as UI changes resulting in changing view layouts, and also may be called immediately after didSelectRow - you have no control over when these methods are called.

In relation to this particular question, these solutions may work, since these methods are always called when scrolling - just not ONLY when scrolling. However, care needs to be taken not to assume that the user MUST be scrolling in these cases. Also, if you manage a state machine with this flag (like disabling some button when scrolling and enabling it after), you'll get in trouble.

Finally, this only allows detecting a scroll (with the above caveats), but it won't tell you the speed or current values - so it would be difficult to tell when to switch the AM/PM label.

The only way I was able to reliably detect a scroll was through a mess of flags that I set when UI changes are made and other ugly hacks (like waiting 100 ms after a didSelectRow before trying to detect scrolls again, because I noticed calls to the data source immediately after didSelectRow). Adding willScroll/didScroll methods to the delegate seems like an obvious thing Apple neglected to add.

雪若未夕 2024-12-14 15:04:59

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

尝试一下

I just found a way to achieve "pickerDidScroll",it work fine. The key point is add KVO to the row view. Here is my code:

//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];
            }
        }
    }
}

The "RatchetScrollUnit" class :

@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];
}

Have a try

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文