我有一个自定义UIControl
,其中包含一些其他控件。在这些控件之间有空白空间,我UIControl
的背景需要透明。
我需要捕获在我的自定义UIControl
上发生的所有触摸事件,即使它们恰好位于其他控件之间(透明区域)。我不能使用手势识别器,我需要更多的控制然后他们提供。相反,我想注册这样的触摸处理函数:
myControl.addTarget(self, action: "handleTouchDown:event:", forControlEvents: UIControlEvents.TouchDown)
通过这种方法,我会收到myControl
非透明区域发生的触摸,但不会发生透明背景的那些区域。
我尝试在自定义控件中覆盖hitTest::point:withEvent
,不检查alpha值。但是当透明控制区域发生触摸时,甚至不会调用hitTest::point:withEvent
。我用自定义layer
替换了我的控件的CALayer
,并且在那里也覆盖了hitTest
而没有结果(层上似乎没有调用hitTest
)。
要提供完美答案(并赢得赏金),您需要做的就是:
UIControl
(例如UIButton
)。UIControl
中移除所有内容(来自UIButton
的文字)并使其背景透明(设置为清除颜色或将Alpha通道设置为0)。addTarget::action:forControlEvents:
方法在控件上注册UIControlEvents.TouchDown
个事件。在处理程序方法中打印一些东西到控制台。addTarget::action:forControlEvents:
提供的粒度。没有黑客解决方案。我知道将控件上的背景alpha通道设置为0.01
会让它突然工作,但这是我不想要的黑客攻击。在这里描述一下你做了什么。答案 0 :(得分:2)
关注编辑部分:
https://github.com/soxjke/TransparentControl
1)如果我将背景颜色设置为+[UIColor clearColor]
,那么触摸效果会非常好。所以你不需要做更多的事情,继续使用清晰的颜色。 (顶部按钮)
2)如果我设置alpha = 0,则不处理触摸。 OK(中键)
3)为了处理这个问题,有一个简单的解决方案(底部按钮),子类UIButton
(实际上你可以使用层次结构中的任何内容到UIView
)。覆盖hitTest:withEvent:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
return CGRectContainsPoint(self.bounds, point) ? self : nil;
}
PROFIT
4)如果你需要更深入,请使用
touchesBegan:withEvent:
touchesMoved:withEvent:
touchesEnded:withEvent:
touchesCancelled:withEvent:
中提出的UIResponder
子类{p} {p}}
P.S。我将结束主题。不知道你的任务究竟是什么,但是告诉你不能使用识别器,因为你需要对所有触摸事件“更多控制”,发现你不知道手势识别器的可能性。所以,根据我的经验,我会说你宁愿发明自行车然后做好解决方案。
P.P.S。如果我和其他人在这里建议方法对你不起作用 - 请检查你的控件userInteractionEnabled
附录(查看要测试的控制器代码:):
#import "ViewController.h"
#import "TransparentControl.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *buttonClearColor;
@property (weak, nonatomic) IBOutlet UIButton *buttonAlpha0;
@property (weak, nonatomic) IBOutlet TransparentControl *customButtonAlpha0;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.buttonClearColor addTarget:self action:@selector(touchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[self.buttonClearColor addTarget:self action:@selector(touchUpOutside:) forControlEvents:UIControlEventTouchUpOutside];
[self.buttonClearColor addTarget:self action:@selector(touchDown:) forControlEvents:UIControlEventTouchDown];
[self.buttonAlpha0 addTarget:self action:@selector(touchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[self.buttonAlpha0 addTarget:self action:@selector(touchUpOutside:) forControlEvents:UIControlEventTouchUpOutside];
[self.buttonAlpha0 addTarget:self action:@selector(touchDown:) forControlEvents:UIControlEventTouchDown];
[self.customButtonAlpha0 addTarget:self action:@selector(touchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[self.customButtonAlpha0 addTarget:self action:@selector(touchUpOutside:) forControlEvents:UIControlEventTouchUpOutside];
[self.customButtonAlpha0 addTarget:self action:@selector(touchDown:) forControlEvents:UIControlEventTouchDown];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)touchUpInside:(id)sender
{
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void)touchDown:(id)sender
{
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void)touchUpOutside:(id)sender
{
NSLog(@"%s", __PRETTY_FUNCTION__);
}
@end
答案 1 :(得分:1)
hitTest
的文档提到完全透明的内容被忽略,因此覆盖hitTest
本身可能不足以解决这个问题,因为任何调用hitTest
都没有调用当物体是透明的时候。
相反,如果您需要访问原始触摸事件(无论是什么)(UIResponder
和{{继承),我建议您尝试使用较低级UIView
触摸方法。 1}}所以你可以使用。)
他们是:
UIControl
第一个参数是touchesBegan:withEvent:
touchesMoved:withEvent:
touchesEnded:withEvent:
touchesCancelled:withEvent:
个触摸,第二个参数NSSet
就像你在其他方法中所指的那样......
使用此功能,您无需添加目标操作,但会在自定义控件上覆盖这些方法。这些是较低级别(和极端的老式学校),但应该让您完全控制触摸事件。
答案 2 :(得分:1)
我使用空UIControl
方法对drawRect
进行了子类化,但它确实有效。
根据文档,opaque
和其他一些控件会忽略UIButton
,因此无法将其用作此技术的控制点。但奇怪的是,视图的默认背景颜色是透明的(无)。
通过继承UIControl
并设置opaque = NO
,您可以创建一个drawRect
方法,该方法不会完全填充框架并允许"透明"没有设置alpha = 0
的区域允许hitTest:withEvent:
仍然接收事件。由于该元素是UIView
,因此您应该能够添加视图,然后实现自己的drawRect
调用所有子视图'等效函数,而不是绘制应该是透明的区域。
我的基本ViewController元素,ImageView
是为了确保它有效。
@implementation MyViewController
- (void)viewDidLoad {
[ super viewDidLoad ];
transparentControl = [ [ TransparentControl alloc ] initWithFrame:CGRectMake( 0, 0, 400, 400 ) ];
[ transparentControl addTarget:self action:@selector(printText) forControlEvents:UIControlEventTouchUpInside];
// Create an image view below the button for proof the control is transparent
UIImageView * imageView = [ [ UIImageView alloc ] initWithImage:[ UIImage imageNamed:@"BGImage.jpg" ] ];
imageView.frame = self.view.frame;
[ self.view addSubview:imageView ];
[ self.view addSubview:transparentControl ];
}
-( void )printText {
NSLog( @"Hello, this is a transparent button." );
}
@end
我的透明控制。
@implementation TransparentControl
- ( instancetype )initWithFrame:( CGRect )frame {
if( self = [ super initWithFrame:frame ] ) {
self.opaque = NO;
self.userInteractionEnabled = YES;
}
return self;
}
- ( void )drawRect:(CGRect)rect {
}
@end