UITableViewCell中的UIScrollView - No didSelect调用

时间:2022-10-30 08:42:04

I have a tableviewCell, where the user can scroll horizontally. Since the scrollView covers nearly the whole cell, the tableView method didSelectRow gets not called if the user clicks the cell.

我有一个tableviewCell,用户可以在其中水平滚动。由于scrollView几乎覆盖了整个单元格,因此如果用户单击单元格,则不会调用tableView方法didSelectRow。

So I thought, I could pass the touch event of the UIScrollView to the cell, but still the didSelectRow doesnt gets called. I subclassed UIScrollView to pass the touch event only, if the touch was not a drag:

所以我想,我可以将UIScrollView的touch事件传递给单元格,但是didSelectRow不会被调用。我将UIScrollView细分为仅传递触摸事件,如果触摸不是拖动:

- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event
{
    NSLog(@"touch scroll");
    // If not dragging, send event to next responder
    if (!self.dragging)
        [self.superview touchesEnded: touches withEvent:event];
    else
        [super touchesEnded: touches withEvent: event];
}

Any ideas on how to pass the click to the table, to get the delegate-methods called and keep the scrolling inside the scrollview?

任何关于如何通过单击到表的想法,以获得被调用的方法,并保持滚动视图内的滚动?

5 个解决方案

#1


11  

You can actually do this without subclassing UIScrollView. Whether you have a custom cell, or are setting properties in cellForRowAtIndexPath in the UITableView, you can do the following:

实际上,您不需要子类化UIScrollView就可以做到这一点。无论您有一个自定义单元格,还是正在UITableView中使用cellForRowAtIndexPath设置属性,您都可以执行以下操作:

[cell.contentView addSubview:yourScrollView];
yourScrollView.userInteractionEnabled = NO;
[cell.contentView addGestureRecognizer:yourScrollView.panGestureRecognizer];

The reason you can do this is because scrollView has its own panGestureRecognizer that's accessible to the programmer. So, just adding it to the cell's view will trigger the scrollview's gesture delegates.

这样做的原因是scrollView有自己的panGestureRecognizer,程序员可以访问它。因此,只要将它添加到单元格的视图中,就会触发scrollview的手势委托。

The only drawback of this approach is that subviews of the scroll view are unable to receive any touch input. If you need this you will have to chose a different approach.

这种方法的唯一缺点是,滚动视图的子视图不能接收任何触摸输入。如果您需要这个,您将不得不选择另一种方法。

#2


7  

I just encountered the same problem.
In your subclass make sure to include the full set of methods:

我遇到了同样的问题。在您的子类中,确保包含完整的方法集:

-(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesCancelled: touches withEvent:event];
    else
        [super touchesCancelled: touches withEvent: event];
}

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesMoved: touches withEvent:event];
    else
        [super touchesMoved: touches withEvent: event];
}

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesBegan: touches withEvent:event];
    else
        [super touchesBegan: touches withEvent: event];
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesEnded: touches withEvent:event];
    else
        [super touchesEnded: touches withEvent: event];
}

#3


0  

try set this

尝试设置这个

_scrollView.canCancelContentTouches = NO

also, it is bad to partially forward touch events

此外,部分转发触摸事件也不好

#4


0  

The selected answer is correct, but I updated the code based on a bug I was getting.

所选的答案是正确的,但是我根据得到的错误更新了代码。

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.dragging) {
        [super touchesMoved:touches withEvent:event];
    } else {
        if ([self.delegate isKindOfClass:[UITableViewCell class]]) {
            [(UITableViewCell *)self.delegate touchesCancelled:touches withEvent:event];
        }

        [self.superview touchesMoved:touches withEvent:event];
    }
}

If your self.delegate is not the UITableViewCell, than replace that property with a property to your cell.

如果您的self.delegate不是UITableViewCell,而是用单元格的属性替换该属性。

The cell needs to retrieve the cancel touch event during movement to prevent the undesired results. It can be easily reproducible as follows.

单元格需要在移动过程中检索取消触摸事件,以防止不希望的结果。它可以很容易再现如下。

  • Highlight the cell (assuming the scroll view is over the whole cell, if not highlight the scroll view)
  • 高亮显示单元格(假设滚动视图位于整个单元格之上,如果不突出显示滚动视图)
  • While the cell is highlighted, drag the table view
  • 当突出显示单元格时,拖动表视图
  • Select any other cell and now the previously highlighted cell will retrieve the didSelectCell state
  • 选择任何其他单元格,现在前面突出显示的单元格将检索didSelectCell状态

Another point to mention is that order matters! If the self.delegate is not called before the self.superview then the highlighted state wont happen.

另一点要注意的是秩序很重要!如果self。delegate没有被调用。然后高亮显示的状态不会发生。

#5


0  

Swift 3

斯威夫特3

scrollView.isUserInteractionEnabled = false
contentView.addGestureRecognizer(scrollView.panGestureRecognizer)

#1


11  

You can actually do this without subclassing UIScrollView. Whether you have a custom cell, or are setting properties in cellForRowAtIndexPath in the UITableView, you can do the following:

实际上,您不需要子类化UIScrollView就可以做到这一点。无论您有一个自定义单元格,还是正在UITableView中使用cellForRowAtIndexPath设置属性,您都可以执行以下操作:

[cell.contentView addSubview:yourScrollView];
yourScrollView.userInteractionEnabled = NO;
[cell.contentView addGestureRecognizer:yourScrollView.panGestureRecognizer];

The reason you can do this is because scrollView has its own panGestureRecognizer that's accessible to the programmer. So, just adding it to the cell's view will trigger the scrollview's gesture delegates.

这样做的原因是scrollView有自己的panGestureRecognizer,程序员可以访问它。因此,只要将它添加到单元格的视图中,就会触发scrollview的手势委托。

The only drawback of this approach is that subviews of the scroll view are unable to receive any touch input. If you need this you will have to chose a different approach.

这种方法的唯一缺点是,滚动视图的子视图不能接收任何触摸输入。如果您需要这个,您将不得不选择另一种方法。

#2


7  

I just encountered the same problem.
In your subclass make sure to include the full set of methods:

我遇到了同样的问题。在您的子类中,确保包含完整的方法集:

-(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesCancelled: touches withEvent:event];
    else
        [super touchesCancelled: touches withEvent: event];
}

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesMoved: touches withEvent:event];
    else
        [super touchesMoved: touches withEvent: event];
}

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesBegan: touches withEvent:event];
    else
        [super touchesBegan: touches withEvent: event];
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesEnded: touches withEvent:event];
    else
        [super touchesEnded: touches withEvent: event];
}

#3


0  

try set this

尝试设置这个

_scrollView.canCancelContentTouches = NO

also, it is bad to partially forward touch events

此外,部分转发触摸事件也不好

#4


0  

The selected answer is correct, but I updated the code based on a bug I was getting.

所选的答案是正确的,但是我根据得到的错误更新了代码。

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.dragging) {
        [super touchesMoved:touches withEvent:event];
    } else {
        if ([self.delegate isKindOfClass:[UITableViewCell class]]) {
            [(UITableViewCell *)self.delegate touchesCancelled:touches withEvent:event];
        }

        [self.superview touchesMoved:touches withEvent:event];
    }
}

If your self.delegate is not the UITableViewCell, than replace that property with a property to your cell.

如果您的self.delegate不是UITableViewCell,而是用单元格的属性替换该属性。

The cell needs to retrieve the cancel touch event during movement to prevent the undesired results. It can be easily reproducible as follows.

单元格需要在移动过程中检索取消触摸事件,以防止不希望的结果。它可以很容易再现如下。

  • Highlight the cell (assuming the scroll view is over the whole cell, if not highlight the scroll view)
  • 高亮显示单元格(假设滚动视图位于整个单元格之上,如果不突出显示滚动视图)
  • While the cell is highlighted, drag the table view
  • 当突出显示单元格时,拖动表视图
  • Select any other cell and now the previously highlighted cell will retrieve the didSelectCell state
  • 选择任何其他单元格,现在前面突出显示的单元格将检索didSelectCell状态

Another point to mention is that order matters! If the self.delegate is not called before the self.superview then the highlighted state wont happen.

另一点要注意的是秩序很重要!如果self。delegate没有被调用。然后高亮显示的状态不会发生。

#5


0  

Swift 3

斯威夫特3

scrollView.isUserInteractionEnabled = false
contentView.addGestureRecognizer(scrollView.panGestureRecognizer)