UITableView的水平移动?

我试图区分UITableView水平滑动/平移和垂直滚动。 我正在模仿的行为(在某种意义上)是Twitter的iPad应用程序,它有多个UITableView ,可以在屏幕上水平移动。 如果我在这些UITableView一个上左右滑动手指,视图本身会水平移动。 如果我垂直滑动,视图按预期滚动。

我很难找出实现这种行为的正确方法。 我已经看到了一些关于这个的教程,包括在UITableViewCells添加触摸事件处理程序,并在UITableView重写hitTest以根据手势正在移动的方向来适当地路由事件。 我已经实现了其中的一些技巧,但是没有一个能够很好地工作。

有谁知道实施这种行为的正确方法? 根据用户手指移动的方向 ,对UITableView有条件地执行操作?

谢谢。

我一直在类似的问题上挣扎了好几天,而且我经历了几个潜在的解决scheme。 我已经find了最好的方法,也是最简单的解决scheme,是inheritanceUIGestureRecognizer来处理水平移动并将其附加到您的UITableViews。

它的工作方式是在它进入UITableView(也是UIScrollView)之前拦截任何触摸事件。 作为UIScrollView的子类的UITableView具有内置的自定义UIPanGestureRecognizer,它可以检测拖动并相应地滚动它的视图。 通过添加您自己的UIGestureRecognizer的子类,您可以在UIScrollView的手势识别器之前获得触摸。 如果您的识别器发现用户正在水平拖动,则应将其重写的touchesMoved:方法中的状态更改为UIGestureRecognizerStateBegan。 否则,它将状态设置为UIGestureRecognizerCancelled,它让底层的UIScrollView处理触摸。

以下是我的UIGestureRecognizer子类的样子:

 #import <UIKit/UIGestureRecognizerSubclass.h> @interface TableViewCellPanGestureRecognizer : UIGestureRecognizer { CGPoint startTouchPoint; CGPoint currentTouchPoint; BOOL isPanningHorizontally; } - (void)reset; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; @end @implementation TableViewCellPanGestureRecognizer -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; startTouchPoint = [[touches anyObject] locationInView:nil]; } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesMoved:touches withEvent:event]; currentTouchPoint = [[touches anyObject] locationInView:nil]; if ( !isPanningHorizontally ) { float touchSlope = fabsf((currentTouchPoint.y - startTouchPoint.y) / (currentTouchPoint.x - startTouchPoint.x)); if ( touchSlope < 1 ) { self.state = UIGestureRecognizerStateBegan; isPanningHorizontally = YES; [self.view touchesCancelled:touches withEvent:event]; } else { self.state = UIGestureRecognizerStateCancelled; [self.view touchesCancelled:touches withEvent:event]; } } else { self.state = UIGestureRecognizerStateChanged; } } -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesCancelled:touches withEvent:event]; self.state = UIGestureRecognizerStateCancelled; [self.view touchesCancelled:touches withEvent:event]; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesEnded:touches withEvent:event]; self.state = UIGestureRecognizerStateCancelled; } -(void)reset { [super reset]; startTouchPoint = CGPointZero; currentTouchPoint = CGPointZero; isPanningHorizontally = NO; } @end 

然后我有一个子类UITableView,将识别器附加到自身,并实现一个触发水平移动单个行的动作方法:

在我的UITableView初始化中:

 horizontalPanGesture = [[TableViewCellPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleHorizontalDrag:)]; [self addGestureRecognizer:horizontalPanGesture]; [horizontalPanGesture release]; 

和行动方法:

 -(void)handleHorizontalDrag:(UIGestureRecognizer *)gesture { UIGestureRecognizerState state = gesture.state; // Set the touched cell if (!touchedCell){ NSIndexPath *indexPathAtHitPoint = [self indexPathForRowAtPoint:[gesture locationInView:self]]; id cell = [self cellForRowAtIndexPath:indexPathAtHitPoint]; touchedCell = cell; startTouchPoint = [gesture locationInView:touchedCell]; } if ( state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged ) { // move your views horizontally } else if ( state == UIGestureRecognizerStateEnded || state == UIGestureRecognizerStateCancelled ) { touchedCell = nil; } } 

上面获取当前单元格在表格视图中被触摸,然后在用户向左或向右拖动时向其应用水平移动。 但是,如果我的手势识别器确定触摸是垂直滚动,它只是取消自己,接下来的触摸被发送到UITableView自动启动垂直滚动。

这个设置似乎比覆盖hitTest更简单,并且在UITableView本身内部进行各种触摸事件欺骗。 它只是立即确定触摸移动的方向。 您将需要阅读UIGestureRecognizers – 特别是如何将其分类。 因为UITableView内build的panGestureRecognizer不会像往常一样处理这些事件,所以需要确保将特定的触摸事件转发到UITableView,如touchesCledlled。 显然,你会想要移动整个表格视图而不是单个单元格,但它应该是非常简单的。

这个解决scheme就像我一样简单,花了我一段时间才准确地满足我的确切需求。 我对IOS开发很新,所以我不得不花费大量的时间阅读和修改手势识别器和滚动视图来解决这个问题。

我从来没有这样做过,但作为一个UITableView是UIScrollView的子类,UITableView的代表也是UIScrollViewDelegates。 所以在你的UITableViewController子类中,你应该能够使用UIScrollView委托,并截取滚动 – 确保也调用超级方法。

如果你想把UITableView放在“并排”的位置,当你水平滑动的时候,你希望它们都能同时水平移动(就像带有UITableViews而不是图像的照片库),你可以这样做:

使用UIScrollView并添加UITableViews作为UIScrollView的子视图。 你应该像这样设置scrollview的contentSize:

 CGRect bounds = scrollView.bounds; scrollView.contentSize=CGSizeMake(bounds.size.width * kNumOfTableViews, bounds.size.height); 

以便UIScrollview可以水平滚动而不是垂直滚动。

你也可以使用

 scrollView.pagingEnabled=YES; 

取决于理想的行为。

如果垂直滑动手指,UITableviews将以正常的方式响应,通过水平滑动手指,可以在UITableView之间切换。

有关如何高效完成此操作的更多详细信息,请参阅WWDC 2010video会话104 – 使用滚动视图devise应用程序,并从以下位置查看源代码: http : //developer.apple.com/library/ios/# samplecode / PhotoScroller / 。 本节介绍如何在图像之间滑动。 您将使用UITableViews而不是图像

但是,如果您希望每个UITableView能够独立水平移动,并且可能与另一个iPad应用程序的twitter应用程序重叠,则此解决scheme对您不起作用,至less不是开箱即用。