Iphone 如何制作superview截取按钮触摸事件?

Iphone 如何制作superview截取按钮触摸事件?,iphone,objective-c,cocoa-touch,Iphone,Objective C,Cocoa Touch,假设我有这个代码: #import <UIKit/UIKit.h> @interface MyView : UIView @end @implementation MyView - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { // How can I get this to show up even when the button is touched? NSLog(@"%@",

假设我有这个代码:

#import <UIKit/UIKit.h>

@interface MyView : UIView
@end
@implementation MyView

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // How can I get this to show up even when the button is touched?
    NSLog(@"%@", [touches anyObject]);
}

@end

@interface TestViewAppDelegate : NSObject <UIApplicationDelegate>
{
    UIWindow *window;
}

@end

@implementation TestViewAppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
    window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    MyView *view = [[MyView alloc] initWithFrame:[window frame]];
    [view setBackgroundColor:[UIColor whiteColor]];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [button setTitle:@"Hiya!" forState:UIControlStateNormal];
    [button setFrame:CGRectMake(100.0, 100.0, 200.0, 200.0)];
    [view addSubview:button];

    [window addSubview:view];
    [window makeKeyAndVisible];
}


- (void)dealloc
{
    [window release];
    [super dealloc];
}

@end
#导入
@接口MyView:UIView
@结束
@实现MyView
-(无效)触摸移动:(NSSet*)触摸事件:(UIEvent*)事件
{
//我怎样才能让它在按下按钮时显示出来?
NSLog(@“%@,[接触任何对象]);
}
@结束
@接口TestViewAppDelegate:NSObject
{
UIWindow*窗口;
}
@结束
@实现TestViewAppDelegate
-(无效)应用程序IDFinishLaunching:(UIApplication*)应用程序
{
窗口=[[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]边界]];
MyView*view=[[MyView alloc]initWithFrame:[窗口框架]];
[查看setBackgroundColor:[UIColor whiteColor]];
UIButton*button=[UIButton button类型:UIButtonyPeroundRect];
[按钮设置标题:@“Hiya!”用于状态:UIControlStateNormal];
[按钮设置框:CGRectMake(100.0、100.0、200.0、200.0)];
[查看添加子视图:按钮];
[窗口添加子视图:视图];
[WindowMakeKeyandVisible];
}
-(无效)解除锁定
{
[窗口释放];
[super dealoc];
}
@结束

有没有办法截获发送到按钮的触摸事件?我最终想做的是创建一个UIView子类,当它检测到刷卡时,它会告诉它的视图控制器(或委托,无论哪个),这样它就可以将下一个视图控制器“推”到堆栈上(类似于iPhone主屏幕)。我认为这是第一步,但如果我处理得不正确,我愿意接受建议。

我希望看到其他解决方案,但我知道的最简单的方法是覆盖以下两种UIView方法之一:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
这些方法被调用以确定触摸是否在视图或其任何子视图的边界内,因此这是拦截触摸并将其传递的一个好点。你想干什么就干什么,然后

return [super hitTest:point withEvent:event];


我相信在这种情况下,您必须将UIButton子类化,并覆盖对UIResponder的触摸和运动事件的响应。然后,假设UIButton子类可以访问它,您可以将它们转发到您想要的任何对象

在这种情况下,您可以将它们传递给UIButton的superview

@interface MyButton : UIButton
@end

@implementation MyButton

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
     [[self superview] touchesMoved:touches withEvent:event];
}

@end
参见

本能会说“子类UIButton”,但UIButton实际上是一个类簇(即,对象的实际类型根据您想要制作的按钮类型而透明地改变),这使得子类化非常困难。除了重写UIButton之外,在这种方法上你做不了什么

当我需要解决一个几乎相同的问题时,我提出了一个视图,它使用合成来显示代理UIView,但仍然允许触摸截取。下面是它的工作原理:

@interface MyView : UIView {
  UIView * visibleView;
}

- (id) initWithFrame:(CGRect)frame controlClass:(Class)class;

@end


@implementation MyView

- (id) initWithFrame:(CGRect)frame controlClass:(Class)class {
  if (self = [super initWithFrame:frame]) {
    CGRect visibleViewFrame = frame;
    visibleViewFrame.origin = CGPointZero;
    visibleView = [[class alloc] initWithFrame:visibleViewFrame];
    [visibleView setUserInteractionEnabled:NO];
    [self addSubview:visibleView];

    [self setUserInteractionEnabled:YES];
    [self setBackgroundColor:[UIColor clearColor]];
  }
  return self;
}

- (void) dealloc {
  [visibleView removeFromSuperview];
  [visibleView release], visibleView = nil;
  [super dealloc];
}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  if (someCondition == YES) {
    [visibleView touchesBegan:touches withEvent:event];
  }
}

//and similar methods for touchesMoved:, touchesEnded:, etc

@end
其基本思想是将按钮(或任何东西)嵌入到容器类中(类似于您在问题中描述的内容)。但是,您正在禁用按钮上的交互,这意味着当用户点击按钮时,点击事件将“穿过”按钮并进入包含superview的按钮(在这里是MyView实例)。从那里,您可以适当地处理触摸。如果您想让按钮对触摸做出“响应”,只需发送相应的UIResponder消息即可。(不过,您可能需要首先在visibleView上重新启用userInteractionEnabled。我对此不确定。)


如前所述,当我需要在界面上有一个按钮时,我已经非常成功地使用了这种方法(不是这种精确的实现,而是这种模式),而且还捕获了UITouch对象本身。

感谢您的建议和信息性回复。最后,我只使用了第页所示的解释:(在“技巧1:使用单个UIScrollView模拟照片应用程序滑动/缩放/滚动”)。

我可以建议使用这种方法吗:

    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
                                                 initWithTarget:self 
                                                 action:@selector(tapDetected:)];
    tapRecognizer.numberOfTapsRequired = 1;
    tapRecognizer.numberOfTouchesRequired = 1;

    [self.view addGestureRecognizer:tapRecognizer];

您可以从superview执行此操作,无需创建自定义UI元素。

UIButton是一个类群集,很遗憾。这意味着它几乎不可能子类化。我不知道它有那么糟糕。他确实提到了一些UIView子类,所以我只是使用UIButton,因为他在示例代码中使用了它
super
是正确的,因为您希望调用classes父类方法,
superview
将跳过此步骤。很好,UIApgestureRecognitor与包含多个UILabel的UIView配合得很好。
    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
                                                 initWithTarget:self 
                                                 action:@selector(tapDetected:)];
    tapRecognizer.numberOfTapsRequired = 1;
    tapRecognizer.numberOfTouchesRequired = 1;

    [self.view addGestureRecognizer:tapRecognizer];