UIPickerView,检测“滚轮”开始和停止?

发布于 2025-01-03 10:12:21 字数 365 浏览 3 评论 0原文

我刚刚发现,如果我执行以下操作:

  1. 单击将 UIPickerView 动画化到我的视图中的按钮
  2. 快速启动轮子滚动到最后一个项目 然后
  3. 通过按钮关闭视图

然后它还没有尚未选择最后一项。

我通过简单地在 didSelectRow 方法被触发时输出到控制台来尝试此操作,并且当轮子稳定在最后一个项目上时它会触发。

我是否可以检测到车轮仍在滚动,以便我可以延迟检查所选值,直到它稳定为止?

如果重要的话,我正在使用 MonoTouch 进​​行编程,但是如果您有代码示例,我可以很好地阅读 Objective-C 代码来重新实现它。

I just discovered that if I do the following:

  1. Click the button that animates a UIPickerView into my view
  2. Quickly start the wheel rolling towards, then past, the last item
  3. Dismiss the view with a button

Then it has not yet selected the last item yet.

I tried this by simply outputting to the console whenever the didSelectRow method was fired, and it fires when the wheel stabilizes on the last item.

Can I detect that the wheel is still rolling, so that I can delay checking it for a selected value until it stabilizes?

If it matters, I'm programming in MonoTouch, but I can read Objective-C code well enough to reimplement it, if you have a code example that is.

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

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

发布评论

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

评论(7

独享拥抱 2025-01-10 10:12:21

由于动画键不起作用,我编写了这个简单的函数,用于检测 UIPickerView 当前是否正在移动。

-(bool) anySubViewScrolling:(UIView*)view
{
    if( [ view isKindOfClass:[ UIScrollView class ] ] )
    {
        UIScrollView* scroll_view = (UIScrollView*) view;
        if( scroll_view.dragging || scroll_view.decelerating )
        {
            return true;
        }
    }

    for( UIView *sub_view in [ view subviews ] )
    {
        if( [ self anySubViewScrolling:sub_view ] )
        {
            return true;
        }
    }

    return false;
}

它最终返回真正的五层深度。

As animation keys don't work, I wrote this simple function that works for detecting if a UIPickerView is currently moving.

-(bool) anySubViewScrolling:(UIView*)view
{
    if( [ view isKindOfClass:[ UIScrollView class ] ] )
    {
        UIScrollView* scroll_view = (UIScrollView*) view;
        if( scroll_view.dragging || scroll_view.decelerating )
        {
            return true;
        }
    }

    for( UIView *sub_view in [ view subviews ] )
    {
        if( [ self anySubViewScrolling:sub_view ] )
        {
            return true;
        }
    }

    return false;
}

It ends up returning true five levels deep.

夜空下最亮的亮点 2025-01-10 10:12:21

Swift 4(更新) 版本,带有 @DrainBoy 答案的扩展

extension UIView  {
 func isScrolling () -> Bool {

    if let scrollView = self as? UIScrollView {
        if  (scrollView.isDragging || scrollView.isDecelerating) {
            return true
        }
    }

    for subview in self.subviews {
        if ( subview.isScrolling() ) {
            return true
        }
    }
    return false
 }
}

Swift 4 (updated) version with extension of @DrainBoy answers

extension UIView  {
 func isScrolling () -> Bool {

    if let scrollView = self as? UIScrollView {
        if  (scrollView.isDragging || scrollView.isDecelerating) {
            return true
        }
    }

    for subview in self.subviews {
        if ( subview.isScrolling() ) {
            return true
        }
    }
    return false
 }
}
弥枳 2025-01-10 10:12:21

由于 animationKeys 似乎不再起作用,我有另一个解决方案。如果您检查 UIPickerView 的子视图,您将看到每个组件都有一个 UIPickerTableView

这个UIPickerTableView确实是UITableView的子类,当然也是UIScrollView的子类。因此,您可以检查其 contentOffset 值来检测差异。

此外,其 scrollViewDelegate 默认情况下为 nil,因此我假设您可以安全地设置一个对象来检测 scrollViewWillBeginDraggingscrollViewDidEndDecelerating

。保留对每个 UIPickerTableView 的引用,您应该能够实现高效的 isWheelRolling 方法。

Since animationKeys seems to not work anymore, I have another solution. If you check the subviews of UIPickerView, you'll see that there is a UIPickerTableView for each component.

This UIPickerTableView is indeed a subclass of UITableView and of course of UIScrollView. Therefore, you can check its contentOffset value to detect a difference.

Besides, its scrollViewDelegate is nil by default, so I assume you can safely set an object of yours to detect scrollViewWillBeginDragging, scrollViewDidEndDecelerating, etc.

By keeping a reference to each UIPickerTableView, you should be able to implement an efficient isWheelRolling method.

星光不落少年眉 2025-01-10 10:12:21

扩展@iluvatar_GR 答案

extension UIView { 
func isScrolling () -> Bool {

    if let scrollView = self as? UIScrollView {
        if (scrollView.isDragging || scrollView.isDecelerating) {
            return true
        }
    }

    for subview in self.subviews {
        if ( subview.isScrolling() ) {
            return true
        }
    }
    return false
}
func waitTillDoneScrolling (completion: @escaping () -> Void) {
    var isMoving = true
    DispatchQueue.global(qos: .background).async {
    while isMoving == true {
        isMoving = self.isScrolling()
    }
        DispatchQueue.main.async {
            completion()}

    }
}
}

Expanded @iluvatar_GR answer

extension UIView { 
func isScrolling () -> Bool {

    if let scrollView = self as? UIScrollView {
        if (scrollView.isDragging || scrollView.isDecelerating) {
            return true
        }
    }

    for subview in self.subviews {
        if ( subview.isScrolling() ) {
            return true
        }
    }
    return false
}
func waitTillDoneScrolling (completion: @escaping () -> Void) {
    var isMoving = true
    DispatchQueue.global(qos: .background).async {
    while isMoving == true {
        isMoving = self.isScrolling()
    }
        DispatchQueue.main.async {
            completion()}

    }
}
}
城歌 2025-01-10 10:12:21

扩展@iluvatar_GR、@Robert_at_Nextgensystems 回答

使用的手势、UIScrollView isDragging 或 isDecelerating。

// Call it every time when Guesture action.
@objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {
    // Changes the button name to scrolling at the start of scrolling.
    DispatchQueue.main.async {
       self._button.setTitle("Scrolling...", for: .normal)
       self._button.isEnabled = false
       self._button.backgroundColor = Utils.hexStringToUIColor(hex: "FF8FAE")
    }

    // Indication according to scrolling status
    _datePicker.waitTillDoneScrolling(completion: {
        print("completion")
        DispatchQueue.main.async {
           self._button.setTitle("Completion", for: .normal)
           self._button.isEnabled = true
           self._button.backgroundColor = Utils.hexStringToUIColor(hex: "7CB0FF")
        }
    })
}

[SWIFT4] 分享示例源链接!

输入示例源链接

Expanded @iluvatar_GR, @Robert_at_Nextgensystems answer

Used Gesture, UIScrollView isDragging or isDecelerating.

// Call it every time when Guesture action.
@objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {
    // Changes the button name to scrolling at the start of scrolling.
    DispatchQueue.main.async {
       self._button.setTitle("Scrolling...", for: .normal)
       self._button.isEnabled = false
       self._button.backgroundColor = Utils.hexStringToUIColor(hex: "FF8FAE")
    }

    // Indication according to scrolling status
    _datePicker.waitTillDoneScrolling(completion: {
        print("completion")
        DispatchQueue.main.async {
           self._button.setTitle("Completion", for: .normal)
           self._button.isEnabled = true
           self._button.backgroundColor = Utils.hexStringToUIColor(hex: "7CB0FF")
        }
    })
}

[SWIFT4] Share Example Source link!

enter Sample Source link

你是我的挚爱i 2025-01-10 10:12:21

我认为你可以检查 UIPickerView 是否处于动画状态并等待它停止。此处回答了这个问题链接

I think you can just check if the UIPickerView is in the middle of animating and wait for it to stop. This was answered here link

↙温凉少女 2025-01-10 10:12:21

您可以在选择器上使用 SwipeGestureRecognizer。
我认为这根本不是一个完美的解决方案。

- (void)viewDidLoad
{
    [super viewDidLoad];

    _pickerSwipeGestureRecognizer.delegate = self;
    [_pickerSwipeGestureRecognizer setDirection:(UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp)];
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if([gestureRecognizer isEqual:_pickerSwipeGestureRecognizer]){
        NSLog(@"start");
    }
}

- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    NSLog(@"end");
}

You can use a SwipeGestureRecognizer on the picker.
I assume this is not a perfect solution at all.

- (void)viewDidLoad
{
    [super viewDidLoad];

    _pickerSwipeGestureRecognizer.delegate = self;
    [_pickerSwipeGestureRecognizer setDirection:(UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp)];
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if([gestureRecognizer isEqual:_pickerSwipeGestureRecognizer]){
        NSLog(@"start");
    }
}

- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    NSLog(@"end");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文