我想在UIViewController子类中处理触摸(特别是水平幻灯片),但问题是控制器的视图包含覆盖整个屏幕的UIScrollView,因此“touchesBegan:”和“touchesEnded:”事件永远不会在我的控制器中调用。滚动视图仅垂直滚动。
使它能够处理这些事件的最佳方法是什么?让我的UIViewController也继承UIScrollView并根据需要处理触摸(并删除当前的滚动视图),或使用UIScrollView子类代替我当前的滚动视图,它将调用我需要的情况的委托方法?或许还有另一种方式?
这是我目前的代码:
// View creation and adding to parent
NewViewController* newViewController = [[newViewController alloc] initWithNibName:@"NewViewController" bundle:nil];
[self.view addSubview:newViewController.view];
// NewViewController.h
@interface NewViewController : UIViewController {
IBOutlet UIScrollView* scrollView;
// other outlets and properties
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event;
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event;
在IB中,NewViewController的视图包含scrollView,其中包含所有其他插座(标签,按钮)...... 目标是让NewViewController的scrollView调用NewViewController的touchesBegan和touchesEnded方法。
更新: ScrollViewSuite帮助我了解了如何处理触摸回调。 UIScrollView
仅在触摸无法滚动时调用它们。
所以,有三种情况:
touches
方法touchesBegan
,touchesMoved
和touchesEnded
被称为touchesBegan
,touchesMoved
和touchesCancelled
被调用; 通过将UIScrollView
的{{1}}设置为canCancelContentTouches
可以避免触摸取消,但这显然只有在调用FALSE
时才有效,这意味着触摸方法仍然会没有被要求第一个案例。
但是touchesBegan
有一个名为delaysContentTouches的属性,默认情况下设置为UIScrollView
,并且当触摸开始时它会等待一点,以便查看它是否会让他滚动。如果将其设置为TRUE
,则只要触摸开始就会调用触摸方法,并允许子类按照自己的意愿处理它们。
TL; DR:对我来说最简单的方法(如果你不能使用FALSE
)是为了UIGestureRecognizer
的子类,设置它的{{1 }}属性到UIScrollView
并根据您的需要覆盖触摸函数(delayContentTouches
/ FALSE
以及touchesShouldBegin
/ touchesShouldCancel
...)。
答案 0 :(得分:6)
如果您正在为iPhone OS 3.2或更高版本构建,则可以使用Gesture Recognizer对象。根据您的描述,听起来您需要UIPanGestureRecognizer或UISwipeGestureRecognizer。实例化适当的对象,使用[addGestureRecognizer:]
方法将其添加到viewController的视图中,并在viewController中实现委托方法。
供参考:
iPhone Event Handling Guide: Gesture Recognizers
UIGestureRecognizer Reference(抽象超类)
UIGestureRecognizerDelegate Protocol Reference
答案 1 :(得分:1)
您的viewController视图应该是UIScrollView的子视图。 创建一个UIScrollView添加为窗口的子视图,然后创建一个viewController的实例,该实例具有滑块并添加到scrollView的子视图。
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:[window bounds]];
[window addSubView:scrollView];
UIViewController *vc = [[UIViewController alloc] initWithNibNamed:@"MyVC" bundle:nil];
[scrollView addSubView:[vc view]];
我怀疑您是因为缺少IB中的连接而没有收到事件,或者scrollView正在将事件转发到newViewController视图的超级视图。
在UIResponder
nextResponder
属性的Apple文档中。
UIResponder类不会自动存储或设置下一个响应者,而是默认返回nil。子类必须覆盖此方法以设置下一个响应者。 UIView通过返回管理它的UIViewController对象(如果有的话)或超级视图(如果没有)来实现此方法; UIViewController通过返回其视图的superview来实现该方法; UIWindow返回应用程序对象,UIApplication返回nil。
要尝试的事情。
- (BOOL)canBecomeFirstResponder
{
return YES;
}
// View creation and adding to parent
NewViewController* newViewController = [[newViewController alloc] initWithNibName:@"NewViewController" bundle:nil];
[self.view addSubview:newViewController.view];
[self.view resignFirstResponder];
同时查看ScrollViewSuite示例代码。 我注意到包含从scrollView接收事件的视图的控制器实现了视图的委托方法。您可以尝试的方法是在scrollView中子类化视图,并根据示例代码将事件处理委托给您的控制器。
还有其他答案中讨论的新UIGesturizer的样本。请注意,将guest化器添加到视图中,并将guest化器的处理委托给另一个对象(通常是视图的控制器)
您声明按钮和标签是作为IB中滚动视图的子视图添加的。看来你应该有一个UIView作为按钮和标签的容器。只是一个我无法从代码片段中分辨出来的想法。
UIScrollView
-> UIView
->UIButton
->UILabel
..
..