iPhone - 在 UIViewController 中处理触摸幻灯片
Posted
技术标签:
【中文标题】iPhone - 在 UIViewController 中处理触摸幻灯片【英文标题】:iPhone - Handle touch slide in a UIViewController 【发布时间】:2010-06-22 13:24:14 【问题描述】:我想在 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 的视图包含滚动视图,其中包含所有其他出口(标签、按钮)... 目标是让 NewViewController 的 scrollView 调用 NewViewController 的 touchesBegan 和 touchesEnded 方法。
更新: ScrollViewSuite 帮助我了解了如何处理触摸回调。 UIScrollView
仅在触摸不滚动时才调用它们。
所以,三种情况:
倾斜滑动(即使是轻微的,只要滚动条出现):没有调用touches
方法
完全水平滑动(不出现滚动条):touchesBegan
、touchesMoved
和 touchesEnded
被调用
任何不引起滚动的触摸(触摸而不移动,或水平移动)然后稍微垂直滑动:touchesBegan
、touchesMoved
和 touchesCancelled
都会被调用;
可以通过将UIScrollView
的canCancelContentTouches
设置为FALSE
来避免取消触摸,但这显然只有在调用touchesBegan
时才有效,这意味着在第一种情况下仍然不会调用触摸方法。
但是UIScrollView
有一个名为delaysContentTouches 的属性,默认设置为TRUE
,它会在触摸开始时稍等片刻,以查看是否会让他滚动。如果设置为FALSE
,则在触摸开始时立即调用触摸方法,并允许子类根据需要处理它们。
TL;DR: 对我来说似乎最简单的方法(如果你不能使用UIGestureRecognizer
)是继承UIScrollView
,将其delayContentTouches
属性设置为@987654340 @ 并根据您的需要覆盖触摸功能(touchesShouldBegin
/ touchesShouldCancel
以及 touchesBegan
/ touchesMoved
...)。
【问题讨论】:
scrollView 的 contentSize 属性在哪里设置? 在 NewViewController 的 viewDidLoad 中。我根据插座的大小放置插座,最后设置 scrollView 的内容高度。但是使用此代码滚动工作,唯一的问题是不调用触摸方法。 【参考方案1】:如果您正在为 iPhone OS 3.2 或更高版本构建,您可以使用 Gesture Recognizer 对象。根据您的描述,您可能想要UIPanGestureRecognizer 或UISwipeGestureRecognizer。实例化适当的对象,使用 [addGestureRecognizer:]
方法将其添加到 viewController 的视图中,并在 viewController 中实现委托方法。
供参考:iPhone Event Handling Guide: Gesture RecognizersUIGestureRecognizer Reference(抽象超类)UIGestureRecognizerDelegate Protocol Reference
【讨论】:
好吧,我曾经为 3.1.3 ios 构建,而我使用的 iPhone 目前也是 3.1.3。如果我找不到任何简单的东西,我会尝试升级并查看这些手势识别器,谢谢。【参考方案2】:您的 viewController 的视图应该是 UIScrollView 的子视图。 创建一个 UIScrollView 添加为窗口的子视图,然后创建一个具有滑块的 viewController 实例并添加到滚动视图的子视图中。
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 通过返回其视图的父视图来实现该方法; UIWindow 返回应用程序对象,UIApplication 返回 nil。
尝试几件事。
-
在 NewViewController.m 中,覆盖 canBecomeFirstResponder
- (BOOL)canBecomeFirstResponder
return YES;
因为您只是将新视图添加为子视图,而不是使用导航或模式视图,请确保 newViewController 的父视图不再是第一响应者。添加:
// View creation and adding to parent
NewViewController* newViewController = [[newViewController alloc] initWithNibName:@"NewViewController" bundle:nil];
[self.view addSubview:newViewController.view];
[self.view resignFirstResponder];
确保 `NextViewController' 的视图已连接到 IB 中的 File's Owner。
确保视图的 userInteractionEnabled 属性为 YES
还请查看ScrollViewSuite 示例代码。 我注意到包含从 scrollView 接收事件的视图的控制器实现了视图的委托方法。您可以尝试的一种方法是将 scrollView 中的视图子类化,并根据示例代码将事件处理委托给您的控制器。
还有其他答案中讨论的新 UIGesturizer 的示例。请注意,guesturizers 被添加到视图中,并且 guesturizers 的处理被委托给另一个对象(通常是视图的控制器)
您说按钮和标签是作为 IB 中滚动视图的子视图添加的。看来您应该有一个 UIView 作为按钮和标签的容器。只是一个想法,我无法从代码 sn-p 中看出。
UIScrollView
-> UIView
->UIButton
->UILabel
..
..
【讨论】:
哼,我不确定我明白你的意思。事情是我的 viewControllers 的视图已经是应用程序中前一个屏幕中另一个 VC 视图的子视图,所以我尝试从 nib 中删除 scrollView,像在我当前的 VC 的 viewDidLoad 中那样手动创建它,将它添加到 VC 的超级视图,最后将VC的视图添加到scrollView的子视图中。但这无济于事,我既没有滚动也没有 touchesBegan/Ended 回调。 我用原始代码更新了我的问题。不过没什么可看的。 我覆盖了 canBecomeFirstResponder,辞去了 superview 的第一响应者并检查了 IB 中的所有内容,但仍然没有调用 touches 方法。我首先尝试了我的想法,我创建了一个 UIScrollView 的子类,它覆盖了触摸方法(在调用 [super touches...] 之前存储了一些数据)并用它替换了我的 scrollView。这可行,但并不是每次都调用这些方法......它甚至是非常随机的。如果我想确保调用这两种方法,就必须慢慢滑动并避免滚动,就好像有某种过滤器一样......这似乎不是一个好方法。 添加了更多尝试 抱歉耽搁了,我正在处理其他事情。我想我已经找到了解决方案,我更新了原始问题。现在我将看看手动处理所有内容是否可行。非常感谢您的帮助,ScrollViewSuite 是个好主意。以上是关于iPhone - 在 UIViewController 中处理触摸幻灯片的主要内容,如果未能解决你的问题,请参考以下文章
未调用 DidEndSendingToApplication