如何在 iOS 中增加 UIView 的触摸区域
Posted
技术标签:
【中文标题】如何在 iOS 中增加 UIView 的触摸区域【英文标题】:How to increase an UIView's touch area in iOS 【发布时间】:2012-08-09 00:27:47 【问题描述】:根据 Apple 的 Document,任何可触摸视图至少应具有 44 x 44 点的可触摸区域。
我做了一些调查,看起来一个很好的解决方案是覆盖 pointInside,如下所示:
- (BOOL) pointInside:(CGPoint)point withEvent:(UIEvent *)event
CGRect l_bounds = self.bounds;
float lengthOf44 = [self convertLengthFromScreen:44];
CGFloat l_widthDelta = lengthOf44 - l_bounds.size.width;
CGFloat l_heightDelta = lengthOf44 - l_bounds.size.height;
if (l_widthDelta < 0)
l_widthDelta = 0;
if (l_heightDelta < 0)
l_heightDelta = 0;
l_bounds = CGRectInset(l_bounds, -0.5 * l_widthDelta, -0.5 * l_heightDelta);
if (CGRectContainsPoint(l_bounds, point))
return YES;
return NO;
但是,这个解决方案有很多缺点。给定一个 5 x 5 像素大小的小视图。
假设小视图非常靠近超级视图的边缘,那么这种方法会导致一半的可触摸区域延伸到超级视图之外,而可触摸区域实际上是22×44。在那种情况下我需要进一步覆盖superview的pointInside。
假设我们有三个小视图,它们彼此非常接近,那么上视图总是会赢得触摸。 理想情况下,我希望最接近接触点的视图获胜。
请问还有比这更好或更优雅的解决方案吗?
为了更好地说明我的担忧,让我举个例子:每个人都应该熟悉 ios 的 Copy Blue Hint Dot(不确定我是否使用了正确的词,但请看图片)。 http://i.stack.imgur.com/FtjYi.png
假设我们要实现它(复制蓝点)。对于那个蓝点,我不知道 Apple 是如何实现的。但是,我假设蓝点是一种 UIImageView,并假设它是一些 UITextView 的子视图(这可能不确定)。 UIImageView 可以响应触摸吗?在我的解决方案中,它可以通过覆盖 pointInSide 来响应触摸。 在这种情况下,我的两个问题可以翻译为:
-
如果我们选中的单词离UITextView边缘太近怎么办?因此,该蓝点的理想触摸区域甚至可能位于超级视图 (UITextView) 之外。
如果上蓝点距离下蓝点太近,我们从两个点的中间拖动怎么办(看起来下蓝点获胜的机会更高。)
【问题讨论】:
这不是一个好的解决方案。这就是您发布问题的原因。 同意这不是一个好的解决方案。这就是为什么我正在寻求更好的解决方案。尤其是问题 1。 您得到的答案是在超级视图中触摸的答案句柄,并通过命中测试映射回您的子视图。 如果触摸超出了superview,superview无法接收到触摸怎么办? 处理最顶部视图的触摸并向下映射。 【参考方案1】:您错过了文档的重点。
出于可用性原因,Apple UI 指南建议您不要将可触摸区域(通常由某种视图、按钮、图像等表示)设置为小于 44X44。 (指尖大小)
如果您有一个 5X5 视图,则它不是接收触摸事件的正确视图,您应该使用该视图的超级视图来接收子级的触摸事件。
(已编辑以删除我认为这是不可能的错误陈述)
【讨论】:
您当然可以让视图接收超出其范围的触摸事件。您是否应该这样做因具体情况而异,但在某些时候它肯定是最佳选择。 UIView 将仅接收响应者链基于其框架提供给它的触摸事件。您可以将这些触摸从另一个视图重定向回子视图,但是如果没有来自父视图的事件重定向,视图将无法获得在其边界之外发生的触摸事件 马特如果我错了而海报是对的,那为什么这甚至是一个问题?事实上,如果您想要更精细的视图定位,只需跟踪您的子视图边界并进行简单的命中测试即可。 这不是真的。边界不是响应者链转发机制的基础。正如提问者所说,-pointInside:withEvent
方法是。默认实现将使用边界矩形,但您可以覆盖它以提供您想要的任何逻辑。
如果您只想进行更精细的命中测试,那么您是对的,这是解决问题的错误方法。我只是想指出,“您不能让视图在其边界之外接收触摸事件”这句话从表面上看是不正确的。【参考方案2】:
你采取了错误的方法,首先你不应该弄乱来自 ios 的触摸检测,它已经过预配置和优化,可以在手指触摸时正常工作,这就是为什么如果你触摸你通常会得到比哪里高一点的读数你真的摸过。
您似乎想做某种“用户在某个地方触摸的位置”,如果我是您,我会得到一个 uiview,例如,这是我的完整可触摸区域,只需在其中添加其余元素,你可以把它们放在你想要的任何地方,它们甚至可以重叠或任何东西,只要确保超级视图是接收触摸的那个,然后做一些数学运算,看看哪个最接近元素中心。即使它们是按钮,您也可以禁用交互并以编程方式显示它们的状态更改。好像他们被按下或什么的。
重申我的观点。只使用 1 个大的触控区域,然后计算其余部分,这样您就可以完全控制触控区域等。
(那么我可能完全误解了你的目的)
【讨论】:
以上是关于如何在 iOS 中增加 UIView 的触摸区域的主要内容,如果未能解决你的问题,请参考以下文章
IOS/Objective-C:检测 UIVIew 上的滑动和屏幕相同位置的按钮触摸