Events iOS-通过视图转发所有接触
我有一个覆盖在许多其他视图之上的视图。我只使用overaly来检测屏幕上的一些触摸次数,但除此之外,我不希望视图停止下面其他视图的行为,这些视图是滚动视图等。如何通过此覆盖视图转发所有触摸?这是UIView的子脚本。试试这样的东西Events iOS-通过视图转发所有接触,events,uiview,touch,Events,Uiview,Touch,我有一个覆盖在许多其他视图之上的视图。我只使用overaly来检测屏幕上的一些触摸次数,但除此之外,我不希望视图停止下面其他视图的行为,这些视图是滚动视图等。如何通过此覆盖视图转发所有触摸?这是UIView的子脚本。试试这样的东西 for (UIView *view in subviews) [view touchesBegan:touches withEvent:event]; 例如,上面的代码在touchesBegind方法中会将触摸传递给视图的所有子视图。如果要将触摸转发到的视图恰好
for (UIView *view in subviews)
[view touchesBegan:touches withEvent:event];
例如,上面的代码在touchesBegind方法中会将触摸传递给视图的所有子视图。如果要将触摸转发到的视图恰好不是子视图/超级视图,可以在UIView子类中设置自定义属性,如下所示:
@interface SomeViewSubclass : UIView {
id forwardableTouchee;
}
@property (retain) id forwardableTouchee;
确保在您的.m:
@synthesize forwardableTouchee;
然后在任何UIResponder方法中包括以下内容,例如:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.forwardableTouchee touchesBegan:touches withEvent:event];
}
无论在何处实例化UIView,请将forwardableTouchee属性设置为希望将事件转发到的任何视图:
SomeViewSubclass *view = [[[SomeViewSubclass alloc] initWithFrame:someRect] autorelease];
view.forwardableTouchee = someOtherView;
要将接触从覆盖视图传递到下面的视图,请在UIView中实现以下方法: 目标C:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(@"Passing all touches to the next view (if any), in the view stack.");
return NO;
}
myWebView.userInteractionEnabled = NO;
Swift 5:
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
print("Passing all touches to the next view (if any), in the view stack.")
return false
}
禁用用户交互是我所需要的 目标C:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(@"Passing all touches to the next view (if any), in the view stack.");
return NO;
}
myWebView.userInteractionEnabled = NO;
斯威夫特:
myWebView.isUserInteractionEnabled = false
这是一个旧线程,但它是在搜索时出现的,所以我想我应该添加我的2c。我有一个包含子视图的覆盖UIView,并且只想截取触及其中一个子视图的触摸,因此我修改了PixelCloudSt的答案
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
for (UIView* subview in self.subviews ) {
if ( [subview hitTest:[self convertPoint:point toView:subview] withEvent:event] != nil ) {
return YES;
}
}
return NO;
}
正如@PixelCloudStv所建议的,如果您想将touch从一个视图切换到另一个视图,但需要对该过程进行一些额外的控制-子类UIView //标题
@interface TouchView : UIView
@property (assign, nonatomic) CGRect activeRect;
@end
//实施
#import "TouchView.h"
@implementation TouchView
#pragma mark - Ovverride
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
BOOL moveTouch = YES;
if (CGRectContainsPoint(self.activeRect, point)) {
moveTouch = NO;
}
return moveTouch;
}
@end
进入interfaceBuilder后,只需将视图类设置为TouchView,并使用您的rect设置活动rect。您还可以更改和实现其他逻辑。我在UIStackView中遇到了类似的问题(但可能是任何其他视图)。 我的配置如下: 这是一个典型的例子,我有一个容器,需要放在背景中,旁边有按钮。出于布局目的,我在UIStackView中包含了按钮,但现在stackView的中间(空)部分截取了以下内容:-( 我所做的是创建UIStackView的一个子类,该子类具有一个属性,该属性定义了应该可触摸的子视图。 现在,侧面按钮(包含在*viewsWithActiveTouch*数组中)上的任何触摸都将被赋予按钮,而堆栈视图上除这些视图以外的任何地方的任何触摸都不会被拦截,因此将传递给堆栈视图下方的任何对象
/** Subclass of UIStackView that does not accept touches, except for specific subviews given in the viewsWithActiveTouch array */
class NoTouchStackView: UIStackView {
var viewsWithActiveTouch: [UIView]?
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
if let activeViews = viewsWithActiveTouch {
for view in activeViews {
if CGRectContainsPoint(view.frame, point) {
return view
}
}
}
return nil
}
}
@fresidue answer的改进版本。您可以使用此
UIView
子类作为透明视图,在其子视图外传递触摸。在Objective-C中实现:
@interface PassthroughView : UIView
@end
@implementation PassthroughView
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
for (UIView *view in self.subviews) {
if (!view.hidden && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
return YES;
}
}
return NO;
}
@end
在Swift中:
class PassthroughView: UIView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return subviews.contains(where: {
!$0.isHidden
&& $0.isUserInteractionEnabled
&& $0.point(inside: self.convert(point, to: $0), with: event)
})
}
}
提示: 假设你有一个大的“holder”面板,可能后面有一个表视图。你可以使“holder”面板
通过视图。现在它可以工作了,你可以在“holder”中滚动表格
但是
在“支架”面板的顶部有一些标签或图标。别忘了,当然,这些标签或图标必须简单地标记为“用户交互启用关闭”
在“支架”面板的顶部有一些按钮。别忘了,当然这些按钮必须简单地标记为启用用户交互
注意有点令人困惑的是,“持有者”本身-您在上使用的视图PassthroughView
on-必须在上标记为启用了用户交互功能!这是on!!(否则,将永远不会调用PassthroughView中的代码。)
斯威夫特5
class ThroughView: UIView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
guard let slideView = subviews.first else {
return false
}
return slideView.hitTest(convert(point, to: slideView), with: event) != nil
}
}
看起来,即使是你,这里也有很多答案,没有一个干净的斯威夫特,我需要的。
所以我在这里从@fresidue获取答案,并将其转换为swift,因为现在大多数开发人员都想在这里使用它
它解决了我的问题,我有一些透明的工具栏按钮,但我想工具栏是不可见的用户和触摸事件应该通过
isUserInteractionEnabled=false,正如某些人所说,这不是基于我的测试的选项
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
for subview in subviews {
if subview.hitTest(convert(point, to: subview), with: event) != nil {
return true
}
}
return false
}
我在StackView中有两个标签,我在上面的解决方案中没有太大成功,相反,我使用以下代码解决了我的问题:
let item = ResponsiveLabel()
// Configure label
stackView.addArrangedSubview(item)
子类化视图:
class PassThrouStackView:UIStackView{
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
for subview in self.arrangedSubviews {
let convertedPoint = convert(point, to: subview)
let labelPoint = subview.point(inside: convertedPoint, with: event)
if (labelPoint){
return subview
}
}
return nil
}
}
然后你可以做一些类似的事情:
class ResponsiveLabel:UILabel{
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// Respond to touch
}
}
类响应标签:UILabel{
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
//对触摸作出反应
}
}
我试图使用嵌套的UIStackView中的控件构建一个控制面板。一些控件有UITextField的控件,其他控件有UIButton的控件。此外,还有标识控件的标签。我想做的是放一个大的“不可见”图标控制面板后面的按钮,这样,如果用户点击按钮或文本字段外的区域,我就可以捕捉到并采取行动-如果文本字段处于活动状态,主要是关闭任何键盘(辞职FirstResponder)。但是,轻敲控制面板上的标签或其他空白区域不会传递任何信息。上述讨论有助于我在下面给出答案
基本上,我对UIStackView进行了子分类,并重写了“point(inside:with)”例程,以查找需要触摸的控件类型,以及“忽略”我想要忽略的标签之类的内容。它还检查UIStackView内部的内容,以便这些内容可以递归到控制面板结构中
代码可能比它应该的要详细一点。但它在调试中很有帮助,并且希望能够更清楚地说明例程正在执行的操作。只需确保在Interface Builder中将UIStackView的类更改为PassTrustPack即可
class PassThruStack: UIStackView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
for view in self.subviews {
if !view.isHidden {
let isStack = view is UIStackView
let isButton = view is UIButton
let isText = view is UITextField
if isStack || isButton || isText {
let pointInside = view.point(inside: self.convert(point, to: view), with: event)
if pointInside {
return true
}
}
}
}
return false
}
}我需要通过UIStackView传递触摸。内部的UIView是透明的,但UIStackView消耗了所有触摸。这对我来说很有效:
class PassThrouStackView: UIStackView {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let view = super.hitTest(point, with: event)
if view == self {
return nil
}
return view
}
}
所有ArrangedSubview仍会接收到触摸,但UIStackView本身上的触摸会消失