防止父视图 UIGestureRecongnizer 在 UITableVIew 子视图中执行

Posted

技术标签:

【中文标题】防止父视图 UIGestureRecongnizer 在 UITableVIew 子视图中执行【英文标题】:Preventing parent views UIGestureRecongnizer executing within a UITableVIew subview 【发布时间】:2012-10-10 09:49:05 【问题描述】:

问题:

我有一个UIView,它有一个UITableView 作为子视图。 UIView 配置了UITapGestureRecognizer。

我的问题是 UIView 的手势识别器会消耗桌面上的点击。结果是表格视图永远不会看到水龙头。

当一个点在表格的框架内时,如何让识别器失败,或者让表格成为点击的默认使用者。

我已经尝试(如代码示例所示)多种方法pointInside:withEvent、hitTest:withEvent,但不知道该怎么做。

这是代表问题的代码: 控制器:

#import <UIKit/UIKit.h>
#import "ABCDTableView.h"

@interface ABCDFirstView : UIView
@property (nonatomic,strong) ABCDTableView *tableView;
@end

#import "ABCDFirstView.h"

@implementation ABCDFirstView
@synthesize tableView;

- (id)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        [self awakeFromNib];
    
    return self;


- (void)awakeFromNib


    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
                                   initWithTarget:self action:@selector(viewTouch:)];

    [self addGestureRecognizer:tap];


- (void)viewTouch:(UIGestureRecognizer *)gesture 
    NSLog(@"view touched");



- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

    if (CGRectContainsPoint(self.tableView.bounds, point)) 
        NSLog(@"point in table point as well as view");
        return NO;
    
    else if (CGRectContainsPoint(self.bounds, point)) 
        NSLog(@"point only in view");
        return YES;
    
    NSLog(@"point not in view");
    return NO;



- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

    UIView *view    = [super hitTest:point withEvent:event];
    NSLog(@"view hittest res: %@",view);

    return view;

@end

表格视图

#import <UIKit/UIKit.h>

@interface ABCDTableView : UITableView
    <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) NSArray *list;


@end



#import "ABCDTableView.h"

@implementation ABCDTableView
@synthesize list;

- (id)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        [self awakeFromNib];
    
    return self;


- (void)awakeFromNib

    self.delegate   = self;
    self.dataSource = self;

    // create table list
    self.list       = [[NSArray alloc]
                       initWithObjects: @"one",@"two",@"three",@"four",@"five",
                       @"six", @"seven", @"eight", @"nine", @"ten", nil];





- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    return [self.list count];


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *cellID = @"cell";
    UITableViewCell *cell   = [self dequeueReusableCellWithIdentifier:cellID];

    if (cell == nil) 
        cell    = [[UITableViewCell alloc]
                   initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    

    cell.textLabel.text = [self.list objectAtIndex:[indexPath row]];

    return cell;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    NSLog(@"row selected");



@end

查看

#import <UIKit/UIKit.h>
#import "ABCDTableView.h"

@interface ABCDFirstView : UIView
@property (nonatomic,strong) ABCDTableView *tableView;
@end

#import "ABCDFirstView.h"

@implementation ABCDFirstView
@synthesize tableView;

- (id)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        [self awakeFromNib];
    
    return self;


- (void)awakeFromNib


    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
                                   initWithTarget:self action:@selector(viewTouch:)];

    [self addGestureRecognizer:tap];


- (void)viewTouch:(UIGestureRecognizer *)gesture 
    NSLog(@"view touched");



- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

    if (CGRectContainsPoint(self.tableView.bounds, point)) 
        NSLog(@"point in table point as well as view");
        return NO;
    
    else if (CGRectContainsPoint(self.bounds, point)) 
        NSLog(@"point only in view");
        return YES;
    
    NSLog(@"point not in view");
    return NO;



- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

    UIView *view    = [super hitTest:point withEvent:event];
    NSLog(@"view hittest res: %@",view);

    return view;

@end

【问题讨论】:

【参考方案1】:

使用 UIGestureRecognizerDelegate 方法

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;

并检查 touch.view 是否与应该接收手势识别器的视图相同。

【讨论】:

以上是关于防止父视图 UIGestureRecongnizer 在 UITableVIew 子视图中执行的主要内容,如果未能解决你的问题,请参考以下文章

防止父视图在子视图作用于它后接收触摸事件

Swift 4:防止UIView的子视图移动到它的父节点之外

Android:如何防止键盘在我的布局中向上推某个视图? [复制]

iOS10 UI教程视图和子视图的可见性

防止历史传播到父窗口

当父可调整大小时,如何防止嵌套DIV的内容溢出父级?