我有3个UIViews,分层在一个大的uiview之上。我想知道用户是否接触到最顶层而不关心其他用户。我将在第二个UIView中有几个按钮,在第三个UIView中有一个UITable。
问题是我在第一个视图上打开了userInteractionEngabled并且它可以正常工作,但即使我将其关闭,所有其他视图也会以相同的方式响应。如果我在self.view上禁用userInteractionEnabled,则它们都不会响应。我也无法检测touchesBegan委托方法中触摸了哪个视图。
我的代码:
UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 150)];
aView = userInteractionEnabled = YES;
[self.view addSubview:aView];
UIView *bView = [[UIView alloc] initWithFrame:CGRectMake(0, 150, 320, 50)];
bView.userInteractionEnabled = NO;
[self.view addSubview:bView];
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//This gets called for a touch anywhere
}
答案 0 :(得分:62)
为了检查是否触摸了另一个视图中的某个视图,您可以使用hitTest。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
在touchesBegan的自定义实现中,检查触摸设置中的每个触摸。 hitTest方法的点可以使用
获得- (CGPoint)locationInView:(UIView *)view;
方法,其中视图是您的superView(包含其他视图的视图)。
编辑:这是一个快速的自定义实现:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint locationPoint = [[touches anyObject] locationInView:self];
UIView* viewYouWishToObtain = [self hitTest:locationPoint withEvent:event];
}
我希望这很有帮助, 保罗
答案 1 :(得分:27)
在我的情况下,我想找到的UIView没有被hitTest返回。但是下面的代码效果更好:
CGPoint locationPoint = [[touches anyObject] locationInView:self.view];
CGPoint viewPoint = [myImage convertPoint:locationPoint fromView:self.view];
if ([myImage pointInside:viewPoint withEvent:event]) {
do something
}
答案 2 :(得分:14)
这也可以通过以下方式完成。
首先在您关注的视图中找到触摸的位置:
CGPoint location = [touches.anyObject locationInView:viewYouCareAbout];
然后查看该点是否在视图的范围内:
BOOL withinBounds = CGRectContainsPoint(viewYouCareAbout.bounds, location);
然后,如果它在界限范围内,请执行您的操作。
这可以通过一个语句完成,例如,可以直接在if语句中使用:
CGRectContainsPoint(viewYouCareAbout.bounds, [touches.anyObject locationInView:viewYouCareAbout])
答案 3 :(得分:13)
swift code:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let touch = touches.first {
if touch.view == self.view {
self.hideInView()
} else {
return
}
}
}
答案 4 :(得分:8)
在 touchesBegan 中检查触摸的视图是否是您想要的视图,当我尝试确定用户是否触摸了特定的 ImageView 时,我就解决了问题。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if ([touch view] == imageView ) {
... your code to handle the touch
}
...
如果您调整视图直径的内容,请确保相应地更改视图大小,否则即使在视图中具有此类内容的区域中也会识别触摸事件。在我的情况下,当我尝试使用 UIViewContentModeScaleAspectFit 保持图像比例时,尽管图像在“空白区域”区域中根据需要进行了调整,但也触摸了事件。
答案 5 :(得分:3)
我的swift版本检查触摸发生在infoView:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first, infoView.bounds.contains(touch.location(in: infoView)) else { return }
print("touchesBegan") // Replace by your own code
} // touchesBegan
答案 6 :(得分:0)
这对我有用:
<form action="turktry.php" accept-charset="ISO-8859-9">
First name: <input type="text" name="name"><br>
<input type="submit" value="Submit">
</form>
答案 7 :(得分:0)
当您的应用程序接收到触摸事件时,将启动命中测试过程,以确定哪个视图应接收该事件。该过程从视图层次结构的根开始,通常是应用程序的窗口,并以从前到后的顺序搜索子视图,直到找到触摸下方的最前面的视图。该视图将成为点击测试视图,并接收触摸事件。此过程中涉及的每个视图都首先测试事件位置是否在其范围内。仅在测试成功之后,视图才会将事件传递给子视图以进行进一步的命中测试。因此,如果您的视图在触摸下但位于其父视图的范围之外,则父视图将无法测试事件的位置,并且不会将touch事件传递给您的视图。
此问题的一种解决方案是修改视图层次结构的布局,以使您的视图位于其父视图的范围之内。如果由于某些原因必须保留现有布局,则可以更改父视图的点击测试行为,以使其不会忽略触摸事件。可以通过重写父视图类的-(UIView *)hitTest:withEvent:方法来完成
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// Convert the point to the target view's coordinate system.
// The target view isn't necessarily the immediate subview
CGPoint pointForTargetView = [self.targetView convertPoint:point fromView:self];
if (CGRectContainsPoint(self.targetView.bounds, pointForTargetView)) {
// The target view may have its view hierarchy,
// so call its hitTest method to return the right hit-test view
return [self.targetView hitTest:pointForTargetView withEvent:event];
}
return [super hitTest:point withEvent:event]; }
此问题的其他可能原因包括:
您的视图或其任何父视图的userInteractionEnabled属性设置为NO。 该应用程序调用了beginIgnoringInteractionEvents方法,而没有对其endIgnoringInteractionEvents方法进行匹配调用。 您应该确保将userInteractionEnabled属性设置为YES,并且如果您希望视图是交互式的,则应用程序不会忽略用户事件。
如果您的视图在动画过程中没有收到触摸事件,那是因为UIView的动画方法通常会在进行动画时禁用触摸事件。您可以通过在启动UIView动画时适当配置UIViewAnimationOptionAllowUserInteraction选项来更改该行为。
另一种解决方法是
在视图中添加您自己的自定义实现
class CustomView: YourParentView {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
super.hitTest(point, with: event)
return overlapHitTest(point: point, withEvent: event)
}
}
extension UIView {
func overlapHitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
// 1
if !self.isUserInteractionEnabled || self.isHidden || self.alpha == 0 {
return nil
}
// 2
var hitView: UIView? = self
if !self.point(inside: point, with: event) {
if self.clipsToBounds {
return nil
} else {
hitView = nil
}
}
// 3
for subview in self.subviews.reversed() {
let insideSubview = self.convert(point, to: subview)
if let sview = subview.overlapHitTest(point: insideSubview, withEvent: event) {
return sview
}
}
return hitView
}
}