![](/img/trans.png)
[英]Capturing touches on a subview outside the frame of its superview using hitTest:withEvent:
[英]Capturing touches on a subview outside the frame of its superview (over multiple layers)
我在这个帖子中描述了一个类似的问题: 使用hitTest:withEvent捕获其超级视图框架外的子视图的触摸:
情况
我们正在开发Xamarin iOS中的应用程序。 我们有一个自定义视图来创建一个自己的autoComplete输入字段,其中包含一个UiTextField和一个UiTableView以显示结果。
为了实现更好的模块化,我们有另一个名为LabeledContainer的自定义视图。 在其中,我可以设置标签并向底部视图添加内容,在这种情况下是autoComplete。
AutoComplete LabeledContainer
+---------------+ +---------------+
| UiView | | UiView |
|+-------------+| |+-------------+|
|| UiTextField || || UiLabel ||
|+-------------+| |+-------------+|
|+-------------+| |+-------------+|
|| UiTableView || || UiView ||
|+-------------+| |+-------------+|
+---------------+ +---------------+
The following gets rendered:
MAINVIEW
+------------------------------+
| |
| |
| |
| |
|+----------------------------+|
|| LabeledContainer ||
||+--------------------------+||
||| Label |||
||+--------------------------+||
||+--------------------------+||
||| Content |||
|||+------------------------+|||
|||| AutoComplete ||||
|||+------------------------+|||
||+--------------------------+||
|+----------------------------+|
| |
| |
| |
| |
+------------------------------+
问题
我遇到“hitarea”问题,因为autoComplete下拉列表(tableView)在自定义视图框架之外。 框架只占用输入字段的高度,下拉框架在底部重叠。 所以我添加了以下方法来将下拉列表添加到hitArea。
public override bool PointInside(CGPoint point, UIEvent uievent)
{
var bounds = Bounds;
bounds.Height += DROPDOWN.Bounds.Height;
return bounds.Contains(point);
}
但这只有在我将autoComplete添加为mainView的subChild时才有效,因为PointInside会在那里被触发。 如果我将autoComplete添加到labeledContainer,后者的标签高度为自动完成的input + inputfield,则PointsInnside方法永远不会被触发。 情况就是这样,因为带标签的容器不够高,对吧? 那么当superView被触摸时,一个视图的PointsInside会被触发? 但我无法使得labeledContainer或autoComplete更高,以防止推送其他视图。
我尝试将PointsInside方法也添加到labeledContainer,但它没有解决我的问题,因为它没有触及labeledContainer帧,并且从不调用autoComplete PointsInside。
默认情况下,UIViews不会在其超级视图之外接收触摸事件。 但是,您可以将容器视图子类化以检测其框架外的触摸。 容器视图应将未处理的触摸事件转发到其子视图。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
CGPoint pointForTargetView = [self.autoCompleteView convertPoint:point fromView:self];
if (CGRectContainsPoint(self.autoCompleteView.bounds, pointForTargetView)) {
return [self.autoCompleteView hitTest:pointForTargetView withEvent:event];
}
return [super hitTest:point withEvent:event];
}
来自Apple的文档 :
位于接收者界限之外的点永远不会被报告为命中,即使它们实际上位于接收者的子视图中。 如果当前视图的剪辑To Bounds属性设置为NO并且受影响的子视图超出视图的边界,则会发生这种情况。
巴图,非常感谢你的帮助。 我现在在你的建议的帮助下找到了类似的解决方案。
我没有直接在下拉列表边界中测试命中,而是将hitTest委托给自定义自动完成视图。 所以我没有公开dropdown属性,可以在我的自定义自动完成视图中测试它。
// Xamarin version - labeledContainer
public override UIView HitTest(CGPoint p, UIEvent e)
{
var translatedP = AutoComplete.ConvertPointFromView(p, this);
return AutoComplete.HitTest(translatedP, e) ?? base.HitTest(p, uievent);
}
此外,我必须像这样实现autoComplete的HitTest:
// Xamarin version - autoComplete
public override UIView HitTest(CGPoint p, UIEvent e)
{
var translatedP = DropDown.ConvertPointFromView(p, this);
return DropDown.HitTest(translatedP, e) ?? base.HitTest(p, uievent);
}
在这里,我翻译结果下拉列表的点,并检查它是否在里面。 如果没有,则调用默认HitTest来处理输入字段单击。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.