del*_*any 115 cocoa-touch objective-c ios
是否有一种简单的方法允许与位于另一个UIView下的UIView中的按钮进行交互 - 在按钮顶部没有来自顶部UIView的实际对象?
例如,目前我有一个UIView(A),顶部有一个对象,屏幕底部有一个对象,中间没有任何东西.它位于另一个UIView的顶部,中间有按钮(B).但是,我似乎无法与B中间的按钮进行交互.
我可以看到B中的按钮 - 我已经将A的背景设置为clearColor - 但是B中的按钮似乎没有接收到触摸,尽管实际上在这些按钮的顶部没有来自A的对象.
编辑 - 我仍然希望能够与顶级UIView中的对象进行交互
当然有一种简单的方法可以做到这一点?
gyi*_*yim 97
您应该为顶视图创建一个UIView子类并覆盖以下方法:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
// UIView will be "transparent" for touch events if we return NO
return (point.y < MIDDLE_Y1 || point.y > MIDDLE_Y2);
}
Run Code Online (Sandbox Code Playgroud)
您还可以查看hitTest:event:方法.
Stu*_*art 40
虽然这里的许多答案都有效,但我有点惊讶地发现这里没有给出最方便,最通用和最简单的答案.@Ash最接近,除了返回超级视图有一些奇怪的事情......不要这样做.
这个答案来自我在这里给出类似问题的答案.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
if (hitView == self) return nil;
return hitView;
}
Run Code Online (Sandbox Code Playgroud)
[super hitTest:point withEvent:event]将返回该视图所触及的层次结构中最深的视图.如果hitView == self(即,如果有触摸点在无子视图),返回nil,指定,这种观点应该不接收触摸.响应者链的工作方式意味着将继续遍历此点上方的视图层次结构,直到找到将响应触摸的视图.不要返回超级视图,因为它不符合此视图是否应该接受触摸的超级视图!
这个解决方案是:
pointInside:withEvent:以返回特定的可触摸区域).我经常使用它,我已经将它抽象为一个子类,以便为一个覆盖保存无意义的视图子类.作为奖励,添加一个属性以使其可配置:
@interface ISView : UIView
@property(nonatomic, assign) BOOL onlyRespondToTouchesInSubviews;
@end
@implementation ISView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
if (hitView == self && onlyRespondToTouchesInSubviews) return nil;
return hitView;
}
@end
Run Code Online (Sandbox Code Playgroud)
然后狂野地使用此视图,无论您在哪里使用平原UIView.配置它是作为设置简单onlyRespondToTouchesInSubviews到YES.
Tyl*_*ler 31
有几种方法可以解决这个问题.我最喜欢的是覆盖hitTest:withEvent:在一个视图中,它是冲突视图的常见超视图(可能是间接的)(听起来就像你称之为A和B).例如,像这样的东西(这里A和B是UIView指针,其中B是"隐藏"指针,通常被忽略):
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
CGPoint pointInB = [B convertPoint:point fromView:self];
if ([B pointInside:pointInB withEvent:event])
return B;
return [super hitTest:point withEvent:event];
}
Run Code Online (Sandbox Code Playgroud)
您也可以pointInside:withEvent:像gyim建议的那样修改方法.这可以通过在A中有效地"戳一个洞"来实现基本相同的结果,至少对于触摸来说.
另一种方法是事件转发,这意味着覆盖touchesBegan:withEvent:和类似的方法(如touchesMoved:withEvent:等)将一些触摸发送到不同于它们第一次去的对象.例如,在A中,您可以编写如下内容:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if ([self shouldForwardTouches:touches]) {
[B touchesBegan:touches withEvent:event];
}
else {
// Do whatever A does with touches.
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这并不总是像你期望的那样工作!最重要的是像UIButton这样的内置控件总是会忽略转发的触摸.因此,第一种方法更可靠.
有一篇很好的博客文章更详细地解释了所有这些,以及一个小型的工作xcode项目来演示这些想法,可在此处获得:
http://bynomial.com/blog/?p=74
Ben*_*Cox 29
你必须设置upperView.userInteractionEnabled = NO;,否则上面的视图将拦截触摸.
Interface Builder版本是View Attributes面板底部的一个复选框,名为"User Interaction Enabled".取消选中它,你应该好好去.
sam*_*tte 11
pointInside的自定义实现:withEvent:确实似乎是要走的路,但处理硬编码坐标对我来说似乎很奇怪.所以我最后使用CGRectContainsPoint()函数检查CGPoint是否在按钮CGRect中:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
return (CGRectContainsPoint(disclosureButton.frame, point));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
64794 次 |
| 最近记录: |