UITableView的水平移动? [英] Horizontal movement of a UITableView?

查看:73
本文介绍了UITableView的水平移动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to distinguish between horizontal swiping / panning and vertical scrolling in a UITableView. The behavior I'm looking to imitate (in a sense) is that of the Twitter iPad app, that has multiple UITableView that can be moved horizontally on the screen. If I slide my finger left or right on one of these UITableView, the view itself moves horizontally. If I swipe vertically, the view scrolls as expected.

我无法找出实现此
行为的正确方法。我已经看过一些关于这个的教程,包括在 UITableViewCells 中添加touch
事件处理程序,并覆盖 hitTest
UITableView 中根据手势移动的方向
来适当地路由事件。我已经实现了一些这些技术,但是
它们都没有特别好用。

I'm having trouble figuring out the correct way to implement this behavior. I've seen some tutorials on this which involve adding touch event handlers in the UITableViewCells, and overriding hitTest in the UITableViewto appropriately route events depending on which direction the gesture is moving. I've implemented some of these techniques, but none of them work particularly well.

有没有人知道正确的方法实现这种行为?
有条件地在 UITableView 上执行操作,具体取决于用户手指移动的
方向

Does anyone know the correct way to implement this sort of behavior? Conditionally performing actions on a UITableViewdependent on the direction of the user's finger movement?

谢谢。

推荐答案

我几天来一直在努力解决类似的问题,而我已经经历了几个潜在的解决方案。我找到了最好的方法,也是最简单的解决方案,可以将UIGestureRecognizer子类化,以处理水平移动并将其附加到你的UITableViews。

I've been struggling with a similar problem for days, and I've went through several potential solutions. I've found the best way and also the simplest solution to be subclassing UIGestureRecognizer to handle horizontal movement and attach it to your UITableViews.

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

The way it works is that it intercepts any touch events before they go to the UITableView (also UIScrollView). The UITableView, being a subclass of UIScrollView, has a custom UIPanGestureRecognizer built in which detects dragging and scrolls it's view accordingly. By adding your own subclass of UIGestureRecognizer, you can get the touches before the UIScrollView's gesture recognizer does. If your recognizer sees that the user is dragging horizontally, it should change it's state in an overridden touchesMoved: method to UIGestureRecognizerStateBegan. Otherwise, it sets it's state to UIGestureRecognizerCancelled, which lets the underlying UIScrollView handle the touches instead.

这是我的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将识别器附加到自身并实现一个动作方法来触发各行的水平移动:

Then I have a subclassed UITableView that attaches the recognizer to itself and implements an action method to trigger horizontal movement of individual rows:

在我的UITableView init中:

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以自动启动垂直滚动。

The above gets the current cell being touched within the table view, and then applies horizontal movements to it as the user drags left or right. However, if my gesture recognizer determines that the touches are meant to scroll vertically, it just cancels itself and the following touches are sent on to the UITableView to initiate vertical scrolling automatically.

这个设置似乎比重写hitTest和在UITableView本身内做各种触摸事件欺骗要简单得多。它只是立即确定触摸运动的方向。您需要阅读 UIGestureRecognizers - 特别是关于它应该如何被子类化。您需要确保将某些触摸事件(如touchesCancelled)转发到UITableView,因为UITableView内置的panGestureRecognizer不会像往常那样处理这些事件。显然,你想要移动整个表视图而不是单个单元格,但它应该非常简单。

This setup seems to be much simpler than overriding hitTest and doing all sorts of touch event trickery within the UITableView itself. It simply makes an immediate determination about the direction of the touch movement. You'll want to read up on UIGestureRecognizers - specifically about how it should be subclassed. You need to make sure to forward on certain touch events like touchesCancelled to the UITableView, as the UITableView's built in panGestureRecognizer won't be handling these events as it normally does. Obviously, you'll want to move entire table views and not individual cells, but it should be pretty straightforward.

这个解决方案虽然简单,但却花了我一段时间完全正确满足我的确切需求。我对IOS开发很新,所以我不得不花很多时间阅读和修改手势识别器和滚动视图来解决这个问题。

This solution, as simple as it is, took me awhile to get exactly right for my exact needs. I am pretty new to IOS development, so I had to spend a lot of time reading about and tinkering with gesture recognizers and scroll views to figure this out.

这篇关于UITableView的水平移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆