ios - 捕获其父 View 框架外的 subview 上的触摸(在多个层上)

标签 ios objective-c xamarin uiview

我在这个线程中描述了一个类似的问题:Capturing touches on a subview outside the frame of its superview using hitTest:withEvent:

情况

我们正在 Xamarin iOS 中开发应用程序。我们有一个自定义 View 来创建自己的自动完成输入字段,其中包含一个 UiTextField 和一个 UiTableView,用于显示结果。

为了实现更好的模块化,我们有另一个名为 LabeledContainer 的自定义 View 。在其中,我可以设置一个标签并将内容添加到底部 View ,在本例中是自动完成。

AutoComplete               LabeledContainer
+---------------+          +---------------+
| UiView        |          | UiView        |
|+-------------+|          |+-------------+|
|| UiTextField ||          || UiLabel     ||
|+-------------+|          |+-------------+|
|+-------------+|          |+-------------+|
|| UiTableView ||          || UiView      ||
|+-------------+|          |+-------------+|
+---------------+          +---------------+

The following gets rendered:
MAINVIEW
+------------------------------+
|                              |
|                              |
|                              |
|                              |
|+----------------------------+|
|| LabeledContainer           ||
||+--------------------------+||
||| Label                    |||
||+--------------------------+||
||+--------------------------+||
||| Content                  |||
|||+------------------------+|||
|||| AutoComplete           ||||
|||+------------------------+|||
||+--------------------------+||
|+----------------------------+|
|                              |
|                              |
|                              |
|                              |
+------------------------------+

问题

我在使用“hitarea”时遇到问题,因为自动完成下拉列表 (tableView) 在自定义 View 框架之外。框架仅采用输入字段的高度,下拉菜单在底部与它重叠。所以我添加了以下方法来将下拉列表添加到 hitArea。

public override bool PointInside(CGPoint point, UIEvent uievent)
{
    var bounds = Bounds;
    bounds.Height += DROPDOWN.Bounds.Height;   
    return bounds.Contains(point);
}

但这只有在我将自动完成添加为 mainView 的 subChild 时才有效,因为 PointInside 会在那里被触发。如果我将 autoComplete 添加到 labeledContainer,之后它的框架高度为标签 + 自动完成的输入字段,则永远不会触发 PointsInside 方法。出现这种情况是因为 labeledContainer 不够高吧?那么当 superView 被触摸时, View 的 PointsInside 就会被触发?但我无法将 labeledContainer 或 autoComplete 设置得更高,以防止推送其他 View 。

我尝试将 PointsInside 方法也添加到 labeledContainer,但它没有解决我的问题,因为它没有触及 labeledContainer 框架并且从未调用过 autoComplete PointsInside。

最佳答案

默认情况下,UIView 不会接收其父 View 之外的触摸事件。但是,您可以将容器 View 子类化以检测其框架之外的触摸。容器 View 应将未处理的触摸事件转发到其 subview 。

- (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's documentation :

Points that lie outside the receiver’s bounds are never reported as hits, even if they actually lie within one of the receiver’s subviews. This can occur if the current view’s clips​To​Bounds property is set to NO and the affected subview extends beyond the view’s bounds.

关于ios - 捕获其父 View 框架外的 subview 上的触摸(在多个层上),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42928594/

相关文章:

c# - 将 API 写入文件

xamarin - 我们如何处理 Xamarin Forms Picker 的完成按钮单击事件?

ios - 为什么 UIScrollView 的内容不居中?

html - WKWebView 未打开某些目标 ="_blank"链接

ios - 如何在 Objective-C 的框架中设置常量文件

objective-c - Apple 推送通知徽章编号

dll - 为什么 Xamarin.Android 重新映射程序集请求?

javascript - 在 Cordova/Phonegap 下运行时,点击 contenteditable div 无法定位光标

ios - 将NSString转换为NSDate-格式错误

ios - 默认 UISwitch 为 YES 然后使用 NSUserDefaults 保存状态