我有一个简单 - 平凡的 - UIView父/子层次结构。一位家长(UIView)。一个孩子(UIButton)。父母边界小于孩子的边界,因此孩子的一部分延伸到其父母的边界框之外。
问题在于:父母的bbox之外的孩子的那些部分不接收触摸。只有在父级的bbox内点击才允许子按钮接收触摸。
有人可以建议修复/解决方法吗?
对于那些关注这个问题的人,以下是我实施@Bastians最优秀答案的解决方案:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
BOOL isInside = [super pointInside:point withEvent:event];
// identify the button view subclass
UIButton *b = (UIButton *)[self viewWithTag:3232];
CGPoint inButtonSpace = [self convertPoint:point toView:b];
BOOL isInsideButton = [b pointInside:inButtonSpace withEvent:nil];
if (isInsideButton) {
return isInsideButton;
} // if (YES == isInsideButton)
return isInside;
}
答案 0 :(得分:25)
问题是响应者链。当你触摸显示屏时,它会从父母那里下到孩子身上。
所以......当你触摸屏幕时,父母会看到触摸超出了它自己的范围,所以孩子们甚至都不会问。
执行此操作的功能是hitTest。如果你有自己的UIView类,你可以覆盖它并自己返回按钮。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
答案 1 :(得分:4)
Per Apple’s own documentation,我发现这样做的最简单,最可靠的方法是覆盖剪切视图的超类中的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];
}
答案 2 :(得分:2)
前提条件:
UIButton
(命名为容器)中有一个UIView
(名为button1),而button1部分位于容器的边界之外。
<强>问题强>:
button1容器外的部分不会响应点击。
<强>解决方案强>:
从UIView中继承您的容器:
class Container: UIView {
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
let closeButton = viewWithTag(10086) as! UIButton //<-- note the tag value
if closeButton.pointInside(convertPoint(point, toView: closeButton), withEvent: event) {
return true
}
return super.pointInside(point, withEvent: event)
}
}
不要忘记给你的button1标记10086
答案 3 :(得分:2)
- @dugla,谢谢你的提问!
- @Bastian和@laoyur,谢谢你的回答!
Swift 4
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if yourChildView.point(inside: convert(point, to: yourChildView), with: event) {
return true
}
return super.point(inside: point, with: event)
}
答案 4 :(得分:-1)
我手头有同样的问题。您只需覆盖:
- (BOOL)pointInside:(CGPoint)指向withEvent:(UIEvent *)事件
以下是自定义UIView子类的工作代码,该子类仅为其越界子代创建。
@implementation ARQViewToRightmost
// We should not need to override this one !!!
/*-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if ([self isInside:point])
return self;
return nil;
}*/
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if ([self isInside:point])
return YES; // That answer will make hitTest continue recursively probing the view's subviews for hit
return NO;
}
// Check to see if the point is within the bounds of the view. We've extended the bounds to the max right
// Make sure you do not have any other sibling UIViews to the right of this one as they will never receive events
- (BOOL) isInside:(CGPoint)point
{
CGFloat maxWidth = CGFLOAT_MAX;
CGRect rect = CGRectMake(0, 0, maxWidth, self.frame.size.height);
if (CGRectContainsPoint(rect, point))
return YES;
return NO;
}
@end