如何将触摸从 UITextView 传递到 UITableViewCell

Posted

技术标签:

【中文标题】如何将触摸从 UITextView 传递到 UITableViewCell【英文标题】:How to pass touch from a UITextView to a UITableViewCell 【发布时间】:2010-03-19 14:55:36 【问题描述】:

我在自定义 UITableViewCell 中有一个 UITextView。 textview 可以正常工作(滚动、显示文本等),但我需要用户能够点击表格单元格并转到另一个屏幕。现在,如果您点击表格单元格的边缘(即在 UItextView 之外),则会正确调用下一个视图。但很明显,在 uitextview 内部,触摸被捕获而不是转发到表格单元格。

我发现一篇文章谈到了继承 UITextView 以转发触摸。我没有运气就试过了。实现如下。我想知道是否可能a)我的textview的超级不是uitableviewcell,因此我需要以其他方式传递触摸或b)如果超级是uitableviewcell,如果我需要传递其他东西?任何帮助将不胜感激。

#import "ScrollableTextView.h"

@implementation ScrollableTextView

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
    if (parentScrollView) 
        [parentScrollView touchesBegan:touches withEvent:event];
    
    [super touchesBegan:touches withEvent:event];


- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 
    if (parentScrollView) 
        [parentScrollView touchesCancelled:touches withEvent:event];
    
    [super touchesCancelled:touches withEvent:event];


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
    if (parentScrollView) 
        [parentScrollView touchesEnded:touches withEvent:event];
    
    [super touchesEnded:touches withEvent:event];


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
    if (parentScrollView) 
        [parentScrollView touchesMoved:touches withEvent:event];
    
    [super touchesMoved:touches withEvent:event];


- (BOOL)canBecomeFirstResponder 
    return YES;


@end

【问题讨论】:

我使用这个答案找到了一个现代解决方案:***.com/a/41884532/4991890 【参考方案1】:

试试[theTextView setUserInteractionEnabled:NO]; 如果用户需要能够编辑TextView的内容,那么你可能在这里遇到了设计问题。

斯威夫特 3:theTextView.isUserInteractionEnabled = false

故事板:勾选“启用用户交互”复选框。

【讨论】:

这可能有点老了,但我遇到了同样的问题,这条线解决了它。谢谢:) 非常感谢!顺便说一句,如果有人喜欢在 Interface Builder 中进行设置:在检查器中打开 UITextView 的属性窗格,滚动到“视图”窗格所在的底部,然后取消选中“启用用户交互”。 我遇到的问题是我希望用户能够触摸电话号码,但我也需要继续。我仍在寻找两者兼得的方法。如果有人有任何建议,请告诉我。如果我发现我会在这里发布。 @DirectX 你找到解决方案了吗? @DirectX 为什么电话号码在可编辑字段中?也许把它放在UILabel,接受触摸,做你需要做的事情,然后将触摸转发给响应者链中的下一个响应者。如果不是这种情况,请在此处打开一个新问题。【参考方案2】:

我知道这个问题在 5 年前就已经被问过了,但是对于某些应用程序来说,仍然非常需要这种行为才能拥有带有 UIDataDetectors 的可点击单元格。

这是我为适应 UITableView 中的这种特殊行为而编写的 UITextView 子类

-(id) initWithFrame:(CGRect)frame 
    self = [super initWithFrame:frame];
    if (self) 
        self.delegate = self;
    
    return self;


- (BOOL)canBecomeFirstResponder 
    return NO;


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
    UIView *obj = self;

    do 
        obj = obj.superview;
     while (![obj isKindOfClass:[UITableViewCell class]]);
    UITableViewCell *cell = (UITableViewCell*)obj;

    do 
        obj = obj.superview;
     while (![obj isKindOfClass:[UITableView class]]);
    UITableView *tableView = (UITableView*)obj;

    NSIndexPath *indePath = [tableView indexPathForCell:cell];
    [[tableView delegate] tableView:tableView didSelectRowAtIndexPath:indePath];


- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange 
    return YES;

您可以修改它以满足您的需要...

希望对某人有所帮助。

【讨论】:

聪明的解决方法。虽然,当用户只是滚动UITextView 时,此代码也会触发委托,这不是预期的。以您的解决方案为首,我提出了我的另一个答案。 @IkhsanAssaat 即使用手指仔细触摸 TextView 以开始滚动,滚动也没有任何问题...在我的应用程序中它不会滚动和触发的唯一方法是单击TextView 上存在 URL,但最好有更多案例研究,用于不同的实现,谢谢。【参考方案3】:

您的解决方案的问题是,如果您将UITextView 放在UITableViewCell 中,它的超级视图将不是实际的单元格。在单元格的视图结构上,ios 7 和 iOS 8 之间甚至存在细微差别。您需要做的是向下钻取(或向上钻取)层次结构以获取 UITableViewCell 实例。

我正在使用和修改@TheSquad 的while 循环来获取UITableViewCell,并将其分配给一个属性。然后重写这些 touch 方法,在需要时使用单元格的 touches 方法,并且只需使用 super 的 touch 方法的实现即可获得默认行为。

// set the cell as property
@property (nonatomic, assign) UITableViewCell *superCell;

- (UITableViewCell *)superCell 
    if (!_superCell) 
        UIView *object = self;

        do 
            object = object.superview;
         while (![object isKindOfClass:[UITableViewCell class]] && (object != nil));

        if (object) 
            _superCell = (UITableViewCell *)object;
        
    

    return _superCell;


#pragma mark - Touch overrides

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
    if (self.superCell) 
        [self.superCell touchesBegan:touches withEvent:event];
     else 
        [super touchesBegan:touches withEvent:event];
    


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
    if (self.superCell) 
        [self.superCell touchesMoved:touches withEvent:event];
     else 
        [super touchesMoved:touches withEvent:event];
    


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
    if (self.superCell) 
        [self.superCell touchesEnded:touches withEvent:event];
     else 
        [super touchesEnded:touches withEvent:event];
    


- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 
    if (self.superCell) 
        [self.superCell touchesEnded:touches withEvent:event];
     else 
        [super touchesCancelled:touches withEvent:event];
    


【讨论】:

以上是关于如何将触摸从 UITextView 传递到 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章

除了双击到 UITextView 之外的前向触摸

将 UITapGestureRecognizer 触摸传递到底层 UITableViewCell

将光标放在用户触摸的 UITextView 上

如何将触摸事件从一个视图传递到另一个视图

如何将触摸事件从 ScrollView 子视图传递到它的父视图

如何从 UIPopover 中的 UIButton 在主 UIView 中创建 UITextView?