ONTapGesture 不适用于动态创建的视图

Posted

技术标签:

【中文标题】ONTapGesture 不适用于动态创建的视图【英文标题】:UITapGesture not working on dynamically created UIViews 【发布时间】:2016-04-18 12:00:32 【问题描述】:

我正在通过代码制作动态UIViews 并尝试在它们上添加UITapGestureRecogniser。但由于某种原因,他们没有回应。这是代码:

-(void)createRandomBlock
    UIView * block = [[UIView alloc] initWithFrame:CGRectMake([self getRandomPosition], 0-_heightOfBlock, _widthOfBlock, _heightOfBlock)];
    block.backgroundColor = [self randomColor];
    block.userInteractionEnabled=YES;

    UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(blockTapped:)];
    tapGesture.delegate = self;
    tapGesture.numberOfTouchesRequired = 1;
    tapGesture.numberOfTapsRequired=1;
    [block addGestureRecognizer:tapGesture];

    [self.view addSubview:block];

    [UIView animateWithDuration:_durationOfAnimation delay:0.0 options:options animations:^
        [block setFrame:CGRectMake(block.frame.origin.x, ScreenHeight, block.bounds.size.width, block.bounds.size.height)];
     completion:^(BOOL finished) 
        [block removeFromSuperview];
    ];


-(void)blockTapped:(UITapGestureRecognizer*)gesture
    NSLog(@"I am being called?");
    UIView * block = (UIView*)[gesture view];
    [block removeFromSuperview];

有人可以帮忙吗?

谢谢

【问题讨论】:

createRandomBlock 是否被调用过一次? 大概你可以看到屏幕上的视图?视图和超级视图上还有哪些其他手势? createRandomBlock 正在使用延迟为 3 秒的计时器调用。另外,我正在使用 uiviewanimate 为视图设置动画。 是的,我可以在那里看到 UIView。我还可以看到它是动画的。 代码已更新。我认为我的 UIViewAnimate 导致了这个问题。 【参考方案1】:

我尝试使用相同的代码,它对我有用。 只是改变存在,我没有为 tapGesture 设置代理

-(void)createRandomBlock
    UIView * block = [[UIView alloc] initWithFrame:randomPosition];
    block.backgroundColor = [self randomColor];
    block.userInteractionEnabled=YES;

    UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(blockTapped:)];
    tapGesture.numberOfTapsRequired=1;
    [block addGestureRecognizer:tapGesture];

    [self.view addSubview:block];


-(void)blockTapped:(UITapGestureRecognizer*)gesture
    NSLog(@"I am being called?");
    UIView * block = (UIView*)[gesture view];
    [block removeFromSuperview];

我猜是因为添加了委托,它会覆盖您指定的选择器并调用委托方法。

【讨论】:

你能试试更新的代码吗?我认为我的 UIViewAnimate 导致了这个问题。 @WarisAli:你能正确说出你在动画中想要做什么吗?通过查看代码,在我看来,您正在创建视图,然后在完成后为视图设置动画,然后将其删除。您想何时调用轻触选择器。能不能说的更清楚一点。 @WarisAli:这可能会有所帮助:***.com/questions/4311645/…【参考方案2】:

如果您的顶视图的用户交互被禁用,您的手势也将无法识别子视图上的交互。在调用 createRandomBlock 消息之前尝试在某处添加闲置线路。

self.view.userInteractionEnabled = YES;

【讨论】:

是的。启用顶视图交互。那里没有问题。 当然。这是所需的文件。 dropbox.com/sh/puwc6gv09tm0kb4/AAAMEI6mUfXhWplVmOXsBazDa?dl=0 好吧。您的手势不起作用,因为 UIView 的动画实际上在调用时立即设置了视图的框架。您看到的实际上是视图的表示层,而不是视图本身。 是的。我做了一些研究,我发现了这一点。因此,人们建议添加 UIViewAnimationOptionAllowUserInteraction 可以解决问题,但显然它没有做任何事情:(有什么建议吗? 我知道的唯一解决方案是删除表示层的动画。【参考方案3】:

你可以在框架集上犯一些小错误。请更改框架集,您可以解决您的问题。

-(void)createRandomBlock
    int x_coord = arc4random() % 200; //Random number from 0-320  // set random x position 
    int y_coord = arc4random() % 481; //Random number from 0-480  // set random y position

    UIView * block = [[UIView alloc] initWithFrame:CGRectMake(x_coord, y_coord, 100, 100)]; // for testing set width & height 100 * 100
    block.backgroundColor = [UIColor redColor]; // for fix color you can use your change color function
    block.userInteractionEnabled=YES;

    UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(blockTapped:)];
    tapGesture.delegate = self;
    tapGesture.numberOfTouchesRequired = 1;
    tapGesture.numberOfTapsRequired=1;
    [block addGestureRecognizer:tapGesture];

    [self.view addSubview:block];

[UIView animateKeyframesWithDuration:1.0 delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^
        [block setFrame:CGRectMake(block.frame.origin.x, 0, block.bounds.size.width, block.bounds.size.height)];
     completion:^(BOOL finished) 
//        [block removeFromSuperview];
    ];


-(void)blockTapped:(UITapGestureRecognizer*)gesture
    NSLog(@"I am being called?");
    UIView * block = (UIView*)[gesture view];
    [block removeFromSuperview];

【讨论】:

uiview的边框没有问题。我可以在我的主视图上看到 uiview。块的 x,y,width 和 height 正在其他代码中调整。 你的屏幕高度默认设备高度是多少??请检查我的代码 #define ScreenHeight [[UIScreen mainScreen] bounds].size.height 可以设置Y = ScreenHeight,这样就看不到视图控制器了。现在在我的代码中,您会看到自定义视图控制器从底部到顶部。【参考方案4】:

我不知道你的 [self getRandomPosition] 和 _widthOfBlock 等有什么价值,否则下面的代码在我的演示中可以正常工作。

 -(void)createRandomBlock

UIView * block = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
block.backgroundColor = [UIColor redColor];
block.userInteractionEnabled=YES;

UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(blockTapped:)];
tapGesture.delegate = self;
tapGesture.numberOfTouchesRequired = 1;
tapGesture.numberOfTapsRequired=1;
[block addGestureRecognizer:tapGesture];

[self.view addSubview:block];


-(void)blockTapped:(UITapGestureRecognizer*)gesture
NSLog(@"I am being called?");
UIView * block = (UIView*)[gesture view];
[block removeFromSuperview];

更新:

你应该使用touchesBegan来识别触摸,这是工作代码,

-(void)createRandomBlock

UIView * block = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
block.backgroundColor = [UIColor redColor];
block.userInteractionEnabled=YES;
block.tag = 100;
self.view.userInteractionEnabled =YES;

UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(blockTapped:)];
//  tapGesture.delegate = self;
// tapGesture.numberOfTouchesRequired = 1;
tapGesture.numberOfTapsRequired=1;


[block addGestureRecognizer:tapGesture];
[self.view addSubview:block];




 [UIView animateWithDuration:5.0 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^
    [block setFrame:CGRectMake(block.frame.origin.x, self.view.frame.size.height-200, block.bounds.size.width, block.bounds.size.height)];


 completion:^(BOOL finished) 
    [block removeFromSuperview];
];




-(void)blockTapped:(UITapGestureRecognizer*)gesture

NSLog(@"I am being called?");
UIView * block = (UIView*)[gesture view];
[block removeFromSuperview];



- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
UIView *tempView = [self.view viewWithTag:100];

if ([tempView.layer.presentationLayer hitTest:touchLocation]) 

    NSLog(@"call");
    [tempView removeFromSuperview];




【讨论】:

请忽略我正在使用的随机函数和变量。他们工作正常。 检查我更新的答案,它符合您的要求。 :)【参考方案5】:

您正在删除完成块中的视图,这意味着动画完成后您的视图将被删除。从完成块中删除以下行。

[block removeFromSuperview];

你不应该那样做。您的视图本身已被移除,点击手势将如何工作。

【讨论】:

视图离开屏幕后被移除。 我在动画期间点击它。 我试过把这条线去掉。什么都没做。手势仍然不起作用 [block setFrame:CGRectMake(block.frame.origin.x, ScreenHeight, block.bounds.size.width, block.bounds.size.height)]; ScreenHeight 已经是屏幕的高度,y 原点坐标是 ScreenHeight,这意味着它将从屏幕下方开始。将 Y 轴设置为要在显示视图中显示的内容。

以上是关于ONTapGesture 不适用于动态创建的视图的主要内容,如果未能解决你的问题,请参考以下文章

动态 PHP 变量不适用于使用 mPDF 的 codeigniter php 视图文件

iOS + Swift 2:UITableViewCell 中的动态高度不适用于空视图

为 android ListView 设置空视图不适用于在 Java 中创建的视图

Flutter RTL(本地化)不适用于网格视图小部件 - 阿拉伯语言

验证不适用于动态创建的值

动态创建的 Firebase 动态链接不适用于 Android