Ios UI按钮位于具有UIAPTgestureRecognitor的视图中
我有一个Ios UI按钮位于具有UIAPTgestureRecognitor的视图中,ios,objective-c,iphone,cocoa-touch,uitapgesturerecognizer,Ios,Objective C,Iphone,Cocoa Touch,Uitapgesturerecognizer,我有一个uitappesturerecognizer的视图。因此,当我点击视图时,另一个视图出现在该视图上方。这个新视图有三个按钮。当我现在按下其中一个按钮时,我没有得到按钮的动作,我只得到轻触手势的动作。所以我不能再使用这些按钮了。我该怎么做才能让事件通过这些按钮?奇怪的是按钮仍然会高亮显示 我不能在收到UITapgestureRecognitor的点击后将其删除。因为有了它,新视图也可以被删除。意味着我想要一种像全屏vide控件一样的行为您可以将控制器或视图(创建手势识别器的那一个)设置为U
uitappesturerecognizer
的视图。因此,当我点击视图时,另一个视图出现在该视图上方。这个新视图有三个按钮。当我现在按下其中一个按钮时,我没有得到按钮的动作,我只得到轻触手势的动作。所以我不能再使用这些按钮了。我该怎么做才能让事件通过这些按钮?奇怪的是按钮仍然会高亮显示
我不能在收到UITapgestureRecognitor的点击后将其删除。因为有了它,新视图也可以被删除。意味着我想要一种像全屏vide控件一样的行为您可以将控制器或视图(创建手势识别器的那一个)设置为
UITapGestureRecognitor
的代理。然后在代理中,您可以实现-手势识别器:shouldReceiveTouch:
。在您的实现中,您可以测试触摸是否属于新的子视图,如果属于新的子视图,则指示手势识别器忽略它。如下所示:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// test if our control subview is on-screen
if (self.controlSubview.superview != nil) {
if ([touch.view isDescendantOfView:self.controlSubview]) {
// we touched our control surface
return NO; // ignore the touch
}
}
return YES; // handle the touch
}
作为Kevin Ballard回答的后续,我遇到了同样的问题,并最终使用了以下代码:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIButton class]]){
return NO;
}
return YES;
}
它具有相同的效果,但这将适用于任何视图深度的任何UIButton(我的UIButton有多个视图深度,UIGestureRecognitor的代理没有对它的引用)。找到了另一种方法从中执行此操作。它检测触摸是否在每个按钮内 (一) (二)
作为凯西对凯文·巴拉德回答的后续行动:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIControl class]]) {
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
return YES; // handle the touch
}
这基本上使所有用户输入类型的控件(如按钮、滑块等)都能正常工作。在这里找到了这个答案:
你也可以使用
tapRecognizer.cancelsTouchesInView = NO;
这将防止抽头识别器成为唯一捕获所有抽头的识别器
更新-提到了描述此属性的文档链接:通过设置以下布尔值,可以阻止UITapGestureRecognitor取消其他事件(例如点击按钮):
[tapRecognizer setCancelsTouchesInView:NO];
如果您的场景是这样的:
您有一个简单的视图和一些UIButtons,UITextField控件作为子视图添加到该视图中。现在,当您触摸视图中除控件(添加的子视图)以外的任何其他位置时,您希望关闭键盘
那么解决办法是:
将以下方法添加到XYZViewController.m(其中包含您的视图)
这些答案是不完整的。关于如何使用这个布尔运算,我读了很多文章 在*.h文件中添加以下内容
@interface v1ViewController : UIViewController <UIGestureRecognizerDelegate>
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
NSLog(@"went here ...");
if ([touch.view isKindOfClass:[UIControl class]])
{
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
return YES; // handle the touch
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//tap gestrure
UITapGestureRecognizer *tapGestRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenTappedOnce)];
[tapGestRecog setNumberOfTapsRequired:1];
[self.view addGestureRecognizer:tapGestRecog];
// This line is very important. if You don't add it then your boolean operation will never get called
tapGestRecog.delegate = self;
}
-(IBAction) screenTappedOnce
{
NSLog(@"screenTappedOnce ...");
}
在iOS 6.0及更高版本中,默认控制动作可防止手势识别器行为重叠。例如,按钮的默认操作是单次点击。如果在按钮的父视图上附加了一个点击手势识别器,并且用户点击了按钮,则按钮的动作方法接收触摸事件,而不是手势识别器。这仅适用于与控件的默认操作重叠的手势识别,其中包括:
优化cdasher的答案,你会得到
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
return ![touch.view isKindOfClass:[UIControl class]];
}
以下是对我有效的快速版本:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if (scrollView.superview != nil) {
if ((touch.view?.isDescendantOfView(scrollView)) != nil) { return false }
}
return true
}
Swift 5 超视图上的按钮,带有轻触手势
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if let _ = touch.view as? UIButton { return false }
return true
}
在我的情况下,实施hitTest对我来说很有效。我用按钮查看了集合
此方法通过调用每个子视图的点(内部:with:)
方法来遍历视图层次结构,以确定哪个子视图应接收触摸事件。如果点(inside:with:)
返回true,则子视图的层次结构将被类似地遍历,直到找到包含指定点的最前面的视图为止
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isUserInteractionEnabled else { return nil }
guard !isHidden else { return nil }
guard alpha >= 0.01 else { return nil }
guard self.point(inside: point, with: event) else { return nil }
for eachImageCell in collectionView.visibleCells {
for eachImageButton in eachImageCell.subviews {
if let crossButton = eachImageButton as? UIButton {
if crossButton.point(inside: convert(point, to: crossButton), with: event) {
return crossButton
}
}
}
}
return super.hitTest(point, with: event)
}
在我的头文件中,我让我的视图实现uigestoregognizerdelegate,并在my.m中添加了上面的代码。点击永远不会进入这个方法,它直接进入我的处理程序。有什么想法吗?@kmehta您很可能忘记设置UIGestureRecognitizer委托属性。这个答案是否可以推广到处理涉及iAction的所有情况?@Martin iAction编译为
void
,这样在运行时就不会留下任何用于检测的信息。但是您可以做的是沿着视图层次结构走,测试UIControl
,如果您找到任何控件,则返回NO
。对于这一点,它可以帮助我。如果您的按钮位于UIImageView中,请确保imageView的userInteractionEnabled设置为YES。我不想在这里成为一个傻瓜,但它实际上是YES和NO。请使用Cocoa约定。TRUE/FALSE/NULL用于CoreFoundation-Layer。根据我阅读的内容,是和否实际上是为了可读性而创建的。可读性是主观的。它源于并非所有人都过分关注的方法和属性命名约定。如果您希望严格遵守命名约定,那么“是”对任何NSF都使用“是”和“否”。然而,我会说,如果你调查开发人员,你会对其中哪一个更具可读性有不同的看法[button setHidden:YES]-或-[按钮设置隐藏:真];我想我想说的是,如果命名约定的前提是可读性,那么我认为很难否认它在某些情况下是主观的。如果你是一个纯粹主义者,那么你就不会理解那句话。它可能看起来很主观,但经过一段时间的Cocoa编程后,你真正进入了语义更准确的代码流。。。经过多年的Objective-C之后,“TRUE”现在似乎真的错了,因为它与“hidden”不太匹配。从什么时候开始,您可以/是否可以将点击手势传递给UIButton作为UITouch事件(后者是通过点击UIButton生成的事件)中的触动?为已经有15个触摸事件与点击手势关联的按钮创建点击手势识别器似乎重复且不正确。我希望看到代码,而不是猜测。这应该是我所接受的答案。这让每个子视图都可以自己处理点击,并防止连接了TabRecognitor的视图“高举”点击。无需实施
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if let _ = touch.view as? UIButton { return false }
return true
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isUserInteractionEnabled else { return nil }
guard !isHidden else { return nil }
guard alpha >= 0.01 else { return nil }
guard self.point(inside: point, with: event) else { return nil }
for eachImageCell in collectionView.visibleCells {
for eachImageButton in eachImageCell.subviews {
if let crossButton = eachImageButton as? UIButton {
if crossButton.point(inside: convert(point, to: crossButton), with: event) {
return crossButton
}
}
}
}
return super.hitTest(point, with: event)
}