Ios 长按后轻扫

Ios 长按后轻扫,ios,objective-c,swipe,long-press,Ios,Objective C,Swipe,Long Press,好的,我正在帮助将android游戏转换为iOS。该游戏基于2048,但以字母代替数字。我有一个很好的工作点,但仍在学习目标C/iOS的怪癖。到目前为止,我有瓷砖/网格工作,移动工作,等等,但我需要一些帮助。其目标是允许用户长按一个磁贴来选择它,然后将手指滑动到相邻的磁贴上开始拼写单词。我已经实现了长按部分,但我有点不知道如何让它长按然后轻扫。除此之外,我已经有了一个滑动功能,允许用户移动瓷砖。在这里搜索时,我看到了关于子类化的建议,因此我想我需要对uisweegesturecognizer方法

好的,我正在帮助将android游戏转换为iOS。该游戏基于2048,但以字母代替数字。我有一个很好的工作点,但仍在学习目标C/iOS的怪癖。到目前为止,我有瓷砖/网格工作,移动工作,等等,但我需要一些帮助。其目标是允许用户长按一个磁贴来选择它,然后将手指滑动到相邻的磁贴上开始拼写单词。我已经实现了长按部分,但我有点不知道如何让它长按然后轻扫。除此之外,我已经有了一个滑动功能,允许用户移动瓷砖。在这里搜索时,我看到了关于子类化的建议,因此我想我需要对
uisweegesturecognizer
方法进行子类化。我已经安装了手势识别器,但我不确定接下来该怎么做

因此,有几个问题

  • 最好的方法是什么?实现每个
    UISweepGestureRecognitor
    的子类

  • 我当前的刷卡检测会干扰吗?(现在,滑动本身会沿滑动方向移动瓷砖)

  • 我想我需要做一个(如果长按)然后激活子类滑动方法

  • 任何回答上述问题的例子都会大有帮助。我不是要你帮我做这件事,而是至少给我指出一个大致的方向。谢谢

  • 代码如下

    //  Grid.m
    #import "Grid.h"
    #import "Tile.h"
    
    - (void)didLoadFromCCB {
        // listen for swipes to the left
        UISwipeGestureRecognizer * swipeLeft= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeLeft)];
        swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
        [[[CCDirector sharedDirector] view] addGestureRecognizer:swipeLeft];
    
        // listen for swipes to the right
        UISwipeGestureRecognizer * swipeRight= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeRight)];
        swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
        [[[CCDirector sharedDirector] view] addGestureRecognizer:swipeRight];
    
        // listen for swipes up
        UISwipeGestureRecognizer * swipeUp= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeUp)];
        swipeUp.direction = UISwipeGestureRecognizerDirectionUp;
        [[[CCDirector sharedDirector] view] addGestureRecognizer:swipeUp];
    
        // listen for swipes down
        UISwipeGestureRecognizer * swipeDown= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeDown)];
        swipeDown.direction = UISwipeGestureRecognizerDirectionDown;
        [[[CCDirector sharedDirector] view] addGestureRecognizer:swipeDown];
    
        // listen for long press
        UILongPressGestureRecognizer *longpress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(onLongPress:)];
        [longpress setMinimumPressDuration:0.5];
        [[[CCDirector sharedDirector] view] addGestureRecognizer:longpress];
    }
    
    - (void)swipeLeft {
        [self move:ccp(-1, 0)];
    }
    - (void)swipeRight {
        [self move:ccp(1, 0)];
    }
    - (void)swipeDown {
        [self move:ccp(0, -1)];
    }
    - (void)swipeUp {
        [self move:ccp(0, 1)];
    }
    
    // detect longpress, convert to NodeSpace and check if touch location is within tile boundingbox. If yes, set background white, text black.
    - (void)onLongPress:(UILongPressGestureRecognizer *) recognizer {
        CGPoint touchPoint = [[CCDirector sharedDirector] convertToGL:[recognizer locationInView:[recognizer view]]];
        touchPoint = [self convertToNodeSpace:touchPoint];
    
        if (recognizer.state == UIGestureRecognizerStateBegan) {
            for (Tile *tile in self.children) {
                if([tile isKindOfClass:[Tile class]]) {
    
                    CGRect tileBoundingBox = tile.boundingBox;
                    if (CGRectContainsPoint(tileBoundingBox, touchPoint)) {
    
                        tile.backgroundNode.color = [CCColor whiteColor];
                        tile.valueLabel.color = [CCColor blackColor];
                        [self spellWord:tile.value];
                        [_word setString:[_word lowercaseString]];
                        CCLOG(@"%@", _word);
                    }
                }
            }
        }
    
        if (recognizer.state == UIGestureRecognizerStateChanged) {
    
        }
    
        if (recognizer.state == UIGestureRecognizerStateEnded) {
            for (Tile *tile in self.children) {
                if([tile isKindOfClass:[Tile class]]) {
    
                    CGRect tileBoundingBox = tile.boundingBox;
                    if (CGRectContainsPoint(tileBoundingBox, touchPoint)) {
                        tile.backgroundNode.color = [tile getColor:tile.value];
                        tile.valueLabel.color = [self getContrastColor:r green:g blue:b];
    
                    }
                }
            }
        }
    }
    
    // allow for simultaneous gestures
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *) recognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        return YES;
    }
    

    回答你的问题:

  • 我并不认为这是一种需要对
    uilongpressurerecognizer
    进行子类化的编码情况。话虽如此,子类化通常是清理视图控制器代码的好方法,这样视图控制器类中就不会有血淋淋的手势识别器代码。但这里没有任何东西(据我所知)需要这样做。您通常会深入到手势识别器的子类中,在这些子类中,您需要一些特殊的自定义行为(例如,如果某个复杂的标准失败,则手势会失败)。不过,在我走这条路之前,我会先看看你是否能通过标准手势实现所需的用户体验

  • 我能看到刷卡手势相互干扰的唯一原因是您指定了
    应该同时使用GestureRecognizer进行识别
    应该返回
    YES
    。这在需要同时运行多个识别器的情况下使用,这在这里似乎没有必要(而且只是问题的根源)

    我不清楚你是真的想要一个单独的刷卡手势,还是仅仅想要一个手势(“长时间按住并拖动”)。但是,如果您需要单独的滑动手势,您通常会通过指定
    requiregestrerecognizertofail
    来指定手势识别器的相对优先级(例如,滑动需要长按才能失败才能识别滑动)。但如果你真的只有一个手势(“长时间按住并拖动”),那么只需要一个手势识别器

  • 这似乎没有必要。如果要在长按被识别后检测移动,可以将“长按后移动”代码放入
    UIgestureRecognitedStateChanged
    If
    语句中,该语句用于
    UIgestureRecognitedStateChanged
    ,该语句发生在长按被识别后,但在用户抬起手指之前。
    ui长按手势识别器
    是一个连续的手势识别器,在最初识别手势后,随着用户手指的移动,该识别器将继续获得更新


  • 我知道你没有要求输入代码,但是如果你想要一个滑动手势,以及一个长按手势,基本上就是把它捡起来并拖动,你可以做如下的事情。注意,我使滑动手势要求长按失败,因此如果用户长按,则优先,否则它会滑动。但您可能根本不需要滑动手势,因此如果不需要,只需将其完全移除:

    #import <UIKit/UIGestureRecognizerSubclass.h>
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
        [self.view addGestureRecognizer:longPress];
    
        // if you needed a second gesture, a swipe, completely distinct from the long press and drag
        // gesture, you could add it like so:
        //
        // UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)];
        // [swipe requireGestureRecognizerToFail:longPress];
        // // do additional swipe configuration
        // [self.view addGestureRecognizer:swipe];
    }
    
    - (void)handleSwipe:(UISwipeGestureRecognizer *)gesture
    {
        // do your separate swipe stuff here
    }
    
    - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
    {
        static UIView *tileToMove;
        static CGPoint startCenter;
        static CGPoint startLocation;
    
        CGPoint location = [gesture locationInView:self.view];
    
        switch (gesture.state) {
            case UIGestureRecognizerStateBegan:
            {
                // find the tile
    
                tileToMove = [self findTileToMove:location];
                if (tileToMove) {
                    // if found, capture state ...
    
                    startCenter = tileToMove.center;
                    startLocation = location;
    
                    // ... and animate "pick up tile", so the user gets positive feedback
                    // that the drag/swipe portion of the gesture is starting.
    
                    [UIView animateWithDuration:0.25 animations:^{
                        tileToMove.transform = CGAffineTransformMakeScale(1.2, 1.2);
                    }];
                } else {
                    gesture.state = UIGestureRecognizerStateFailed;
                }
                break;
            }
            case UIGestureRecognizerStateChanged:
            {
                // move the tile as the user's finger moves
    
                CGPoint translate = CGPointMake(location.x - startLocation.x, location.y - startLocation.y);
    
                // note, if you want to constrain the translation to be, for example, on the
                // x-axis alone, you could do something like:
                //
                // CGPoint translate = CGPointMake(location.x - startLocation.x, 0);
    
                tileToMove.center = CGPointMake(startCenter.x + translate.x, startCenter.y + translate.y);
                break;
            }
            case UIGestureRecognizerStateEnded:
            {
                // animate "drop the tile"
    
                [UIView animateWithDuration:0.25 animations:^{
                    tileToMove.transform = CGAffineTransformIdentity;
    
                    // if you want the tile to "snap" to some location having let it go,
                    // set the `center` or `frame` here.
                }];
    
                // clear our variables, just in case
    
                tileToMove = nil;
                startCenter = CGPointZero;
                startLocation = CGPointZero;
                break;
            }
            default:
                break;
        }
    }
    
    - (UIView *)findTileToMove:(CGPoint)location
    {
        for (UIView *tile in self.tiles) {
            if (CGRectContainsPoint(tile.frame, location)) {
                return tile;
            }
        }
    
        return nil;
    }
    
    #导入
    -(无效)viewDidLoad{
    [超级视图下载];
    UILongPressGestureRecognitzer*longPress=[[UILongPressGestureRecognitzer alloc]initWithTarget:self action:@selector(handleLongPress:)];
    [self.view addgesturecognizer:longPress];
    //如果你需要第二个手势,一次轻扫,完全不同于长时间的按住和拖动
    //手势,您可以这样添加:
    //
    //UISweepGestureRecognizer*滑动=[[UISweepGestureRecognizer alloc]initWithTarget:self action:@selector(HandleSweep:)];
    //[刷卡要求检测识别邮件:longPress];
    ////进行额外的刷卡配置
    //[self.view addgestureignizer:滑动];
    }
    -(无效)无手擦拭:(UISweepGestureRecognitor*)手势
    {
    //在这里单独刷卡
    }
    -(无效)手动长按:(UILongPress手势识别器*)手势
    {
    静态UIView*平铺移动;
    静态CGPoint startCenter;
    静态点定位;
    CGPoint location=[手势位置视图:self.view];
    开关(手势状态){
    案例UIgestureRecognitzerStateStart:
    {
    //找到瓷砖
    tileToMove=[self-findTileToMove:location];
    如果(平铺移动){
    //如果找到,捕获状态。。。
    startCenter=tileToMove.center;
    位置=位置;
    //…并设置“拾取瓷砖”的动画,以便用户获得积极反馈
    //手势的拖动/滑动部分正在开始。
    [UIView animateWithDuration:0.25动画:^{
    tileToMove.transform=CGAffineTransformMakeScale(1.2,1.2);
    }];
    }否则{
    手势.state=UIgestureRecognitizerStateFailed;
    }
    打破
    }
    案例UIgestureRecognitzerStateChanged:
    {
    //随着用户手指的移动移动互动程序
    CGPoint translate=CGP