自定义 iOS 手势

发布于 2025-01-07 03:09:08 字数 547 浏览 0 评论 0原文

我是 iOS/objective-C 的新手,我想知道如何构建自定义手势。特别是,如果用户点击屏幕的右上角并将他/她的手指沿着设备边缘滑动到底部(左侧的手势相同)。我读过这个:

https://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/GestureRecognizers/GestureRecognizers.html#//apple_ref/doc/uid/TP40009541-CH6-SW2

但我想我很难弄清楚如何将其应用到我的具体案例中。

I am new to iOS/objective-C and I wanted to know how to build custom gestures. In particular, if a user taps the top right of the screen and slides his/her finger down the edge of the device to the bottom (same gesture for the left hand side). I read through this:

https://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/GestureRecognizers/GestureRecognizers.html#//apple_ref/doc/uid/TP40009541-CH6-SW2

But I guess I am having trouble figuring out how to apply it to my specific case.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

a√萤火虫的光℡ 2025-01-14 03:09:08

创建一个 UIGestureRecognizer 子类需要以可靠的方式完成。我非常推荐观看有关该主题的 WWDC2010 视频Session 120 - Simplifying Touch Event Handling with Gesture Recognizers & 课程 121 - 高级手势识别。他们很彻底并且做得很好。

但对于一个非常简单的示例,根据您的问题,我创建了一个非常简单的手势识别器,当用户触摸附加视图的左上象限并将手指向下滑动到附加视图的右下象限并拾取时,该手势识别器会触发他们的手指,而不滑动到所附视图的左侧。

RightSlidedown.h:

#import <UIKit/UIGestureRecognizerSubclass.h> // This import is essential
@interface RightSlidedown : UIGestureRecognizer
@end

RightSlidedown.m

#import "RightSlidedown.h"
@implementation RightSlidedown
-(id)initWithTarget:(id)target action:(SEL)action{
    if ((self = [super initWithTarget:target action:action])){
        // so simple there's no setup
    }
    return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    if ([touch locationInView:self.view].x < CGRectGetMidX(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
    else if ([touch locationInView:self.view].y > CGRectGetMidY(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    if([touch locationInView:self.view].x < CGRectGetMidX(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    if ([touch locationInView:self.view].x < CGRectGetMidX(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
    else if ([touch locationInView:self.view].y < CGRectGetMidY(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
    else {
            // setting the state to recognized fires the target/action pair of the recognizer
        self.state = UIGestureRecognizerStateRecognized; 
    }
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
    self.state = UIGestureRecognizerStateCancelled;
}
-(void)reset{
    // so simple there's no reset
}
@end

因此,基本上手势识别器获取看起来像标准触摸事件的内容。 (他们不是,但他们就是这样做的)。当您响应动作时,您会更改手势识别器的 state 属性。

识别器有两种基本类型:“离散”(例如点击手势)和“连续”(例如平移手势)。这两种类型都会自动从 UIGestureRecognizerStatePossible 开始。

对于像这样的“离散”类型,您的目标是尽快进入 UIGestureRecognizerStateRecognizedUIGestureRecognizerStateFailed 状态。

此示例的理想用法是将 RightSlidedown 手势识别器添加到视图控制器的 viewDidLoad 中新“单视图应用程序”的主视图。

[self.view addGestureRecognizer:[[RightSlidedown alloc] initWithTarget:self action:@selector(rightSlide:)]];

然后一个简单的操作方法就足够了,如下所示:

-(void)rightSlide:(RightSlidedown *)rsd{
    NSLog(@"right slide");
}

Creating a UIGestureRecognizer subclass is a bit involved to do in a solid way. I very much recommend watching the WWDC2010 videos on the subject Session 120 - Simplifying Touch Event Handling with Gesture Recognizers & Session 121 - Advanced Gesture Recognition. They are thorough and well done.

But for a very simple example, based on your question, I created a very simple gesture recognizer that fires when a user touches the upper left quadrant of the attached view and slides their finger down to the lower right quadrant of the attached view and picks up their finger, without sliding to the left side of the attached view.

RightSlidedown.h:

#import <UIKit/UIGestureRecognizerSubclass.h> // This import is essential
@interface RightSlidedown : UIGestureRecognizer
@end

RightSlidedown.m

#import "RightSlidedown.h"
@implementation RightSlidedown
-(id)initWithTarget:(id)target action:(SEL)action{
    if ((self = [super initWithTarget:target action:action])){
        // so simple there's no setup
    }
    return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    if ([touch locationInView:self.view].x < CGRectGetMidX(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
    else if ([touch locationInView:self.view].y > CGRectGetMidY(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    if([touch locationInView:self.view].x < CGRectGetMidX(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    if ([touch locationInView:self.view].x < CGRectGetMidX(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
    else if ([touch locationInView:self.view].y < CGRectGetMidY(self.view.bounds)) self.state = UIGestureRecognizerStateFailed;
    else {
            // setting the state to recognized fires the target/action pair of the recognizer
        self.state = UIGestureRecognizerStateRecognized; 
    }
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
    self.state = UIGestureRecognizerStateCancelled;
}
-(void)reset{
    // so simple there's no reset
}
@end

So basically the gesture recognizer gets what seems like the standard touch events. (They're not, but they act that way). As you respond to the movements you change the state property of your gesture recognizer.

There are two basic types of recognizers, "Discrete" (think tap gesture) and "Continuous" (think pan gesture). Both types automatically start in UIGestureRecognizerStatePossible in the beginning.

For a "Discrete" type, like this one, your goal is to get to state UIGestureRecognizerStateRecognized or UIGestureRecognizerStateFailed as soon as possible.

The ideal usage of this example would be to add the RightSlidedown gesture recognizer to the main view of a new "Single View Application" in the view controller's viewDidLoad.

[self.view addGestureRecognizer:[[RightSlidedown alloc] initWithTarget:self action:@selector(rightSlide:)]];

Then a simple action method is all that's required, like so:

-(void)rightSlide:(RightSlidedown *)rsd{
    NSLog(@"right slide");
}
紫瑟鸿黎 2025-01-14 03:09:08

您可以通过查看触摸的 x 轴和 y 轴的正增量或负增量来做到这一点。例如,复选标记手势 (√) 将是一个负增量,然后是 y 方向的正增量,而 x 方向始终存在负增量,并且触摸结束时的高度比开始时的高度低。添加更多的手指,就会添加更多的检查。

伪代码:

bool firstStroke, secondStroke, motion, override;
while (touchdown){
if (yDelta < 0){firstStroke = TRUE;}
if (firstStroke && yDelta > 0){secondStroke = TRUE;}
if (xDelta < 0){motion = TRUE;}
if (xDelta > 0 || (firstStroke && secondStroke && yDelta < 0)){override = TRUE;}
}
if (firstStroke && secondStroke && motion && start.y > end.y && !override){
    return TRUE;
}else{
    return FALSE;
}

while 命令意味着当触摸按下时,检查 3 件事:

- 如果触摸已向下移动

- 如果触摸向下移动后又向上移动

向左移动

- 如果触摸从右 第四个检查是查看触摸是否从左向右移动过,或者在手势完成后是否向下移动过。

触摸完成后,还会进行一项检查,以查看手势移动是否正确、点是否在正确的位置开始和结束以及手势是否以不正确的动作移动(覆盖)。

希望有帮助。

You can do it by seeing either positive or negative delta in the x and y axis of the touch. for instance, a check mark gesture (√) will be a negative delta followed by a positive delta in the y while there is always a negative delta with the x and the touch ends at a lower height than where it started. Add more fingers you add more checks.

Pseudocode:

bool firstStroke, secondStroke, motion, override;
while (touchdown){
if (yDelta < 0){firstStroke = TRUE;}
if (firstStroke && yDelta > 0){secondStroke = TRUE;}
if (xDelta < 0){motion = TRUE;}
if (xDelta > 0 || (firstStroke && secondStroke && yDelta < 0)){override = TRUE;}
}
if (firstStroke && secondStroke && motion && start.y > end.y && !override){
    return TRUE;
}else{
    return FALSE;
}

The while command means that while the touch is down, check for 3 things:

-If the touch has moved down

-If after the touch has moved down that it has moved up again

-If the touch is moving a right to left

The forth check is to see if the touch ever moved left to right or if after the gesture moved down after the gesture has been finished.

After the touch is finished, there is one more check to see if the gesture moved correctly, if the points started and ended in the correct places and if the gesture moved in an incorrect motion (override).

Hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文