检测 UITableView 中的水平平移
我正在使用 UIPanGestureRecognizer 来识别 UITableView 中的水平滑动(准确地说是在单元格上,尽管它被添加到表格本身)。然而,这个手势识别器显然窃取了桌子上的触摸。我已经让 pangesturerecognizer 识别水平滑动,然后捕捉到它;但如果用户从垂直滑动开始,它应该将所有事件从该触摸传递到桌面视图。
我尝试过的一件事是禁用识别器,但它不会滚动,直到下一个触摸事件。所以我需要它立即通过该事件。
我尝试的另一件事是让它自己滚动,但是停止触摸后你会错过持续的速度。
这是一些代码:
//In the viewdidload method
UIPanGestureRecognizer *slideRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(sliding:)];
[myTable addGestureRecognizer:slideRecognizer];
-(void)sliding:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan)
{
CGPoint translation = [recognizer translationInView:favoritesTable];
if (sqrt(translation.x*translation.x)/sqrt(translation.y*translation.y)>1) {
horizontalScrolling = YES; //BOOL declared in the header file
NSLog(@"horizontal");
//And some code to determine what cell is being scrolled:
CGPoint slideLocation = [recognizer locationInView:myTable];
slidingCell = [myTable indexPathForRowAtPoint:slideLocation];
if (slidingCell.row == 0) {
slidingCell = nil;
}
}
else
{
NSLog(@"cancel");
}
if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled)
{
horizontalScrolling = NO;
}
if (horizontalScrolling)
{
//Perform some code
}
else
{
//Maybe pass the touch from here; It's panning vertically
}
}
那么,关于如何传递触摸有什么建议吗?
另外:我还想也许可以子类化tableview的手势识别器方法,首先检查它是否是水平的;但是,我想我需要原始代码......不知道苹果是否会遇到问题。 另外:我没有子类化 UITableView(controller),只是子类化单元格。此代码位于保存表格的视图控制器中;)
I'm using a UIPanGestureRecognizer to recognize horizontal sliding in a UITableView (on a cell to be precise, though it is added to the table itself). However, this gesture recognizer obviously steals the touches from the table. I already got the pangesturerecognizer to recognize horizontal sliding and then snap to that; but if the user starts by sliding vertical, it should pass all events from that touch to the tableview.
One thing i have tried was disabling the recognizer, but then it wouldn't scroll untill the next touch event. So i'd need it to pass the event right away then.
Another thing i tried was making it scroll myself, but then you will miss the persistent speed after stopping the touch.
Heres some code:
//In the viewdidload method
UIPanGestureRecognizer *slideRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(sliding:)];
[myTable addGestureRecognizer:slideRecognizer];
-(void)sliding:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan)
{
CGPoint translation = [recognizer translationInView:favoritesTable];
if (sqrt(translation.x*translation.x)/sqrt(translation.y*translation.y)>1) {
horizontalScrolling = YES; //BOOL declared in the header file
NSLog(@"horizontal");
//And some code to determine what cell is being scrolled:
CGPoint slideLocation = [recognizer locationInView:myTable];
slidingCell = [myTable indexPathForRowAtPoint:slideLocation];
if (slidingCell.row == 0) {
slidingCell = nil;
}
}
else
{
NSLog(@"cancel");
}
if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled)
{
horizontalScrolling = NO;
}
if (horizontalScrolling)
{
//Perform some code
}
else
{
//Maybe pass the touch from here; It's panning vertically
}
}
So, any advice on how to pass the touches?
Addition: I also thought to maybe subclass the tableview's gesture recognizer method, to first check if it's horizontal; However, then i would need the original code, i suppose... No idea if Apple will have problems with it.
Also: I didn't subclass the UITableView(controller), just the cells. This code is in the viewcontroller which holds the table ;)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我遇到了同样的问题,并提出了一个与 UIPanGestureRecognizer 配合使用的解决方案。
与 Erik 不同的是,我直接将 UIPanGestureRecognizer 添加到单元格中,因为我一次只需要一个特定的单元格来支持平移。但我想这也应该适用于埃里克的案例。
这是代码。
水平手势的计算是从 Erik 的代码中复制的 – 我已经使用 iOS 4.3 对此进行了测试。
编辑:
我发现这个实现可以防止“滑动删除”手势。为了重新获得该行为,我在上面的 if 语句中添加了对手势速度的检查。
在我的设备上玩了一下后,我得出了 500 到 600 的速度,在我看来,这为平移和滑动删除手势之间的转换提供了最佳的用户体验。
I had the same issue and came up with a solution that works with the UIPanGestureRecognizer.
In contrast to Erik I've added the UIPanGestureRecognizer to the cell directly, as I need just one particular cell at once to support the pan. But I guess this should work for Erik's case as well.
Here's the code.
The calculation for the horizontal gesture is copied form Erik's code – I've tested this with iOS 4.3.
Edit:
I've found out that this implementation prevents the "swipe-to-delete" gesture. To regain that behavior I've added check for the velocity of the gesture to the if-statement above.
After playing a bit on my device I came up with a velocity of 500 to 600 which offers in my opinion the best user experience for the transition between the pan and the swipe-to-delete gesture.
我的答案与 Florian Mielke 的相同,但我对其进行了一些简化和更正。
如何使用:
只需为您的
UIPanGestureRecognizer
提供一个委托 (UIGestureRecognizerDelegate
)。例如:然后让该委托实现以下方法:
My answer is the same as Florian Mielke's, but I've simplified and corrected it some.
How to use:
Simply give your
UIPanGestureRecognizer
a delegate (UIGestureRecognizerDelegate
). For example:Then have that delegate implement the following method:
也许您可以使用
UISwipeGestureRecognizer
来代替?您可以通过direction
属性告诉它忽略向上/向下滑动。Maybe you can use the
UISwipeGestureRecognizer
instead? You can tell it to ignore up/down swipes via thedirection
property.您可以尝试手动使用触摸事件而不是手势识别器。始终将事件传递回桌面视图,除非您最终识别出滑动手势。
每个继承自 UIResponder 的类都会有四个触摸函数(开始、结束、取消和移动)。因此,“转发”调用的最简单方法是在您的类中处理它,然后在您想要处理它的下一个对象上显式调用它(但您应该确保首先检查该对象是否响应消息respondsToSelector:因为它是一个可选函数)。这样,您就可以检测您想要的任何事件,并允许与任何其他需要的元素进行正常的触摸交互。
You may try using the touch events manually instead of the gesture recognizers. Always passing the event back to the tableview except when you finally recognize the swipe gesture.
Every class that inherits from UIResponder will have the four touch functions (began, ended, canceled, and moved). So the simplest way to "forward" a call is to handle it in your class and then call it explicitly on the next object that you would want to handle it (but you should make sure to check if the object responds to the message first with respondsToSelector: since it is an optional function ). This way, you can detect whatever events you want and also allow the normal touch interaction with whatever other elements need it.
感谢您的提示!我最终选择了 UITableView 子类,在其中检查移动是否是水平的(在这种情况下我使用我的自定义行为),然后调用 [super TouchsMoved: withEvent:];。
但是,我仍然不明白为什么这有效。我查了一下,super是一个UITableView。看来我仍然不完全理解这个层次结构是如何工作的。有人可以尝试解释一下吗?
Thanks for the tips! I eventually went for a UITableView subclass, where i check if the movement is horizontal (in which case i use my custom behaviour), and else call [super touchesMoved: withEvent:];.
However, i still don't really get why this works. I checked, and super is a UITableView. It appears i still don't fully understand how this hierarchy works. Can someone try and explain?