简体   繁体   English

添加到UIScrollView时UIPickerView不滚动!

[英]UIPickerView is not scrolling when added to UIScrollView!

I have added UIPickerView to the UIScrollView but now UPickerView is not scrolling. 我已将UIPickerView添加到UIScrollView,但现在UPickerView没有滚动。 When I add it to the self.view it scrolls smoothly. 当我将它添加到self.view时,它会顺利滚动。 Here i my code 这是我的代码

monthsArray = [[NSArray alloc] initWithObjects:@"Jan",@"Feb",@"Mar",@"Apr",@"May",@"Jun",@"Jul",@"Aug",@"Sep",@"Oct",@"Nov",@"Dec",nil];

UIPickerView *objPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(185,350,100,100)];
    objPickerView.userInteractionEnabled=YES;
    objPickerView.delegate = self;
    objPickerView.showsSelectionIndicator = YES; 
    [objScrollView addSubView:objPickerView];

I have included the delegete and its methods. 我已经包含了delegete及其方法。 have a look on this issue. 看看这个问题。 Thanks in advance. 提前致谢。
If I am not clear please tell me. 如果我不清楚请告诉我。

I am using a subclass of UIPickerView for the same purpose, but mine is much simpler: 我使用UIPickerView的子类用于相同的目的,但我的更简单:

@implementation ScrollablePickerView

- (UIScrollView *)findScrollableSuperview {

    UIView *parent = self.superview;
    while ((nil != parent) && (![parent isKindOfClass:[UIScrollView class]])) {
        parent = parent.superview;
    }
    UIScrollView* scrollView = (UIScrollView *)parent;

    return scrollView;
}

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event {
    UIScrollView* scrollView = [self findScrollableSuperview];

    if (CGRectContainsPoint(self.bounds, point)) {
        scrollView.canCancelContentTouches = NO;
        scrollView.delaysContentTouches = NO;
    } else {
        scrollView.canCancelContentTouches = YES;
        scrollView.delaysContentTouches = YES;
    }

    return [super hitTest:point withEvent:event];
}

@end

Works like a charm - at least for me. 像魅力一样 - 至少对我而言。

From the UIScrollView class documentation: 从UIScrollView类文档:

Important: You should not embed UIWebView or UITableView objects in UIScrollView objects. 重要提示:您不应在UIScrollView对象中嵌入UIWebView或UITableView对象。 If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled. 如果这样做,可能会导致意外行为,因为两个对象的触摸事件可能混淆和错误处理。

They don't mention UIPickerView there, but I wonder if it should have been added to that list. 他们没有在那里提到UIPickerView,但我想知道它是否应该被添加到该列表中。 It shares in common with the others the characteristic of using touches to scroll things. 它与其他人共同使用触摸来滚动事物的特征。

I guess this might solve your problem (be sure to check the comments too): 我想这可能会解决你的问题(一定要检查评论):

http://www.alexc.me/uiscrollview-and-uidatepicker/153/ http://www.alexc.me/uiscrollview-and-uidatepicker/153/

Basically you have to set DelaysContentTouches and CanCancelContentTouches to NO on the scroll view, as it steals the touch events from the picker. 基本上你必须在滚动视图上将DelaysContentTouches和CanCancelContentTouches设置为NO,因为它会从选择器中窃取触摸事件。

I've been running into a similar problem. 我一直遇到类似的问题。 I've got a UIPickerView that I turned horizontal by applying a transform ( which works pretty well), however inside of a scrollview, scrolling only works at the left hand side. 我有一个UIPickerView,我通过应用变换(它工作得很好)转向水平,但是在滚动视图内部,滚动仅在左侧工作。

What I think is happening is that the UIPicker looks up it's parent chain to see if there are any gesture recognisers, and sets itself as a delegate, so it can disable gesture recognition further up the chain for touches within it's boundaries, and while the transform changes the visual boundaries, it doesn't change the frame, is it is looking for touches within it's original bounds. 我认为正在发生的是UIPicker查找它的父链以查看是否有任何手势识别器,并将自己设置为委托,因此它可以禁止手势识别进一步向上链接触及其边界内的触摸,同时转换改变视觉边界,它不会改变框架,是否正在寻找其原始边界内的触摸。

If this isn't what is happening, you could use this to prevent the scroll view stealing your touches. 如果这不是正在发生的事情,您可以使用它来防止滚动视图窃取您的触摸。

I'm think I'm going to switch to a custom UISCrollView instead of my transformed UIPickerView. 我想我要切换到自定义的UISCrollView而不是我转换的UIPickerView。

UIPickerView is not designed to be scrolled or moved at all. UIPickerView根本不是为了滚动或移动而设计的。 You should place some text field instead and show UIPickerView when user taps on it. 您应该放置一些文本字段,并在用户点击它时显示UIPickerView。

On iOS 11 and iOS 12 changing canCancelContentTouches and delaysContentTouches when UIScrollView is already been dragging doesn't help. 在iOS 11和iOS 12上,当UIScrollView已被拖动时更改canCancelContentTouchesdelaysContentTouches没有帮助。 So I did the hack by intercepting some touches before scrollView.panGestureRecognizer receives them. 所以我通过在scrollView.panGestureRecognizer接收它们之前拦截一些触摸scrollView.panGestureRecognizer黑客攻击。

Here is Swift 4 code. 这是Swift 4代码。 Maybe we can check if touch is inside picker more elegantly. 也许我们可以更优雅地检查触摸是否在拾取器内部。 But it works good. 但它运作良好。

public class TableView: UITableView {

    /// Check if view is a picker's subview
    private func isInPickerView(_ view: UIView) -> Bool {
        var prev: UIView? = view
        while prev != nil {
            if prev is UIPickerView ||  prev is UIDatePicker {
                return true
            }
            prev = prev?.superview
        }
        return false
    }

    // UITableView is already UIGestureRecognizerDelegate internally, 
    // so we just need to overwrite 1 method here
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, 
                                  shouldReceive touch: UITouch) -> Bool {
        // we don't care about any recognizers except self.panGestureRecognizer
        guard gestureRecognizer == panGestureRecognizer else {
            return true
        }
        // if touch is inside picker - we don't pass this touch 
        // to panGestureRecognizer
        let location = touch.location(in: self)
        if let view = self.hitTest(location, with: nil), isInPickerView(view) {
            return false
        }
        return true
    }
}

I had a similar issue with a UIPickerView nested within a UIScrollView and solved it by subclassing UIPickerView. 我有一个类似的问题,UIPickerView嵌套在UIScrollView中,并通过子类化UIPickerView解决了它。 Changes to DelaysContentTouches/CanCancelContentTouches didn't help, and the other "answers" here that basically say "don't do it" -- well, that's no answer at all! 对DelaysContentTouches / CanCancelContentTouches的更改没有帮助,而这里的其他“答案”基本上都说“不要这样做” - 嗯,这根本就没有答案! It can be done and you can get a picker to behave within a scrollView. 它可以完成,你可以让一个选择器在scrollView中运行。

I answered the following question on subclassing UIPickerView, including some code at the end which may help you: 我在子类化UIPickerView时回答了以下问题,包括最后的一些代码可能对您有所帮助:

Responding to touchesBegan in UIPickerView instead of UIView 响应UIPickerView中的touchesBegan而不是UIView

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM