iOS:如何获取长按手势的持续时间?

发布于 2025-01-08 19:01:36 字数 566 浏览 0 评论 0原文

我正在开发一款游戏,其中游戏对象的属性是通过长按对象本身来设置的。该属性的值由长按手势的持续时间决定。我正在使用 UILongPressGestureRecognizer 来实现此目的,所以它是这样的:

[gameObjectView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] 
                                       initWithTarget:self action:@selector(handle:)]];

然后处理函数

- (void)handle:(UILongPressGestureRecognizer)gesture {
  if (gesture.state == UIGestureRecognizerStateEnded) {
    // Get the duration of the gesture and calculate the value for the attribute
  }
}

在这种情况下如何获取长按手势的持续时间?

I'm working on a game in which an attribute of a game object is set by long pressing on the object itself. The value of the attribute is determined by the duration of the long press gesture. I'm using UILongPressGestureRecognizer for this purpose, so it's something like this:

[gameObjectView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] 
                                       initWithTarget:self action:@selector(handle:)]];

Then the handler function

- (void)handle:(UILongPressGestureRecognizer)gesture {
  if (gesture.state == UIGestureRecognizerStateEnded) {
    // Get the duration of the gesture and calculate the value for the attribute
  }
}

How do I get the duration of the long press gesture in this case?

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

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

发布评论

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

评论(7

默嘫て 2025-01-15 19:01:36

我很确定该手势不会存储此信息供您访问。您只能在其上设置一个名为“minimumPressDuration”的属性,该属性是识别手势之前的时间量。

ios 5(未经测试)的解决方法:

创建一个名为timer的NSTimer属性:@property(nonatomic,strong)NSTimer *timer;

和一个计数器:@property(nonatomic,strong)int counter;

然后@synthesize

- (void)incrementCounter {
    self.counter++;
}

- (void)handle:(UILongPressGestureRecognizer)gesture {
    if (gesture.state == UIGestureRecognizerStateBegan) {
         self.counter = 0;
         self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(incrementCounter) userInfo:nil repeats:yes];
    }
    if (gesture.state == UIGestureRecognizerStateEnded) {
        [self.timer invalidate];
    }
}

因此,当手势开始时,启动一个计时器,每秒触发增量方法,直到手势结束。在这种情况下,您需要将 minimumPressDuration 设置为 0,否则手势不会立即开始。然后用计数器做任何你想做的事!

I'm pretty sure the gesture doesn't store this information for you to access. You can only set a property on it called minimumPressDuration that is the amount of time before the gesture is recognised.

Workaround with ios 5 (untested):

Create an NSTimer property called timer: @property (nonatomic, strong) NSTimer *timer;

And a counter: @property (nonatomic, strong) int counter;

Then @synthesize

- (void)incrementCounter {
    self.counter++;
}

- (void)handle:(UILongPressGestureRecognizer)gesture {
    if (gesture.state == UIGestureRecognizerStateBegan) {
         self.counter = 0;
         self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(incrementCounter) userInfo:nil repeats:yes];
    }
    if (gesture.state == UIGestureRecognizerStateEnded) {
        [self.timer invalidate];
    }
}

So when the gesture begins start a timer that fires the incrementation method every second until the gesture ends. In this case you'll want to set the minimumPressDuration to 0 otherwise the gesture won't start straight away. Then do whatever you want with counter!

山人契 2025-01-15 19:01:36

无需计时器。您可以通过以下方式实现:

- (void)handleRecognizer:(UILongPressGestureRecognizer *)gesture
{
    static NSTimeInterval pressStartTime = 0.0; //This can be moved out and kept as a property
    
    switch ([gesture state])
    {
        case UIGestureRecognizerStateBegan:
            //Keeping start time...
            pressStartTime = [NSDate timeIntervalSinceReferenceDate];
            break; /* edit*/
        case UIGestureRecognizerStateEnded:
        {
            //Calculating duration
            NSTimeInterval duration = [NSDate timeIntervalSinceReferenceDate] - pressStartTime;
            //Note that NSTimeInterval is a double value...
            NSLog(@"Duration : %f",duration);
            break;
        }
        default:
            break;
    }
}

另外,如果您想获得长按的实际持续时间,请不要忘记在创建手势识别器时将其 minimumPressDuration 设置为 0按:
myLongPressGestureRecognizer.minimumPressDuration = 0

No timers needed. You can achieve it this way:

- (void)handleRecognizer:(UILongPressGestureRecognizer *)gesture
{
    static NSTimeInterval pressStartTime = 0.0; //This can be moved out and kept as a property
    
    switch ([gesture state])
    {
        case UIGestureRecognizerStateBegan:
            //Keeping start time...
            pressStartTime = [NSDate timeIntervalSinceReferenceDate];
            break; /* edit*/
        case UIGestureRecognizerStateEnded:
        {
            //Calculating duration
            NSTimeInterval duration = [NSDate timeIntervalSinceReferenceDate] - pressStartTime;
            //Note that NSTimeInterval is a double value...
            NSLog(@"Duration : %f",duration);
            break;
        }
        default:
            break;
    }
}

Also, don't forget to set the gesture recognizer's minimumPressDuration to 0 while creating it, if you want to get the real duration of the long press:
myLongPressGestureRecognizer.minimumPressDuration = 0

自在安然 2025-01-15 19:01:36

到目前为止,面向对象的 Cocoa Touch 中最干净、最简单的解决方案似乎是子类化 UILongPressGesture。这是一个用 Swift 编写的示例。

    class MyLongPressGesture : UILongPressGestureRecognizer {
        var startTime : NSDate?
    }

    func installGestureHandler() {
            let longPress = MyLongPressGesture(target: self, action: "longPress:")
            button.addGestureRecognizer(longPress)
    }

    @IBAction func longPress(gesture: MyLongPressGesture) {
            if gesture.state == .Began {
                    gesture.startTime = NSDate()
            }
            else if gesture.state == .Ended {
                    let duration = NSDate().timeIntervalSinceDate(gesture.startTime!)
                    println("duration was \(duration) seconds")
            }
    }

如果您想包含从第一次点击开始的时间,您可以在计算持续时间时通过添加 backgesture.minimumPressDuration 来包含它。缺点是,它可能不是微秒级的精确度,因为在触发手势和调用 .Start 处理程序之间可能需要很短的时间。但对于绝大多数应用程序来说这并不重要。

It seems by far the cleanest and simplest solution in object oriented Cocoa Touch is to subclass UILongPressGesture. Here is an example written in Swift.

    class MyLongPressGesture : UILongPressGestureRecognizer {
        var startTime : NSDate?
    }

    func installGestureHandler() {
            let longPress = MyLongPressGesture(target: self, action: "longPress:")
            button.addGestureRecognizer(longPress)
    }

    @IBAction func longPress(gesture: MyLongPressGesture) {
            if gesture.state == .Began {
                    gesture.startTime = NSDate()
            }
            else if gesture.state == .Ended {
                    let duration = NSDate().timeIntervalSinceDate(gesture.startTime!)
                    println("duration was \(duration) seconds")
            }
    }

If you want to include the time from first tap, you can include it when you calculate duration, by adding back gesture.minimumPressDuration. The drawback is that it is probably not be micro-second precise, given there is likely a small (tiny) amount of time elapsing between the gesture being triggered and your .Start handler being called. But for the vast majority of applications that shouldn't matter.

机场等船 2025-01-15 19:01:36

请参阅“minimumPressDuration”属性。根据文档:

手指必须按在视图上的最短时间才能使手势生效
被认可。

[...]

时间间隔以秒为单位。默认持续时间为 0.5
秒。

See the "minimumPressDuration" property. According to the documentation:

The minimum period fingers must press on the view for the gesture to
be recognized.

[...]

The time interval is in seconds. The default duration is is 0.5
seconds.

遇到 2025-01-15 19:01:36

我知道这是一个迟到的答案,但这对我来说在 IOS 7 和 iOS 7 中非常适合。 8 无需创建计时器。

UILongPressGestureRecognizer *longGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(yourAction)]; // create the recognizer
longGR.minimumPressDuration = 10.0f; //Ten Seconds
longGR.allowableMovement = 50.0f; //Allowable Movement while being pressed
[gameObjectView setUserInteractionEnabled:YES]; //If setting interaction to a non-interactable object such as a UIImageView
[gameObjectView addGestureRecognizer:longGR]; //Add the gesture recognizer to your object

I know this is a late answer but this works perfectly for me in IOS 7 & 8 without having to create a timer.

UILongPressGestureRecognizer *longGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(yourAction)]; // create the recognizer
longGR.minimumPressDuration = 10.0f; //Ten Seconds
longGR.allowableMovement = 50.0f; //Allowable Movement while being pressed
[gameObjectView setUserInteractionEnabled:YES]; //If setting interaction to a non-interactable object such as a UIImageView
[gameObjectView addGestureRecognizer:longGR]; //Add the gesture recognizer to your object
相守太难 2025-01-15 19:01:36

您可以通过Swift 3.0中的以下内容来获取它

逻辑:只需分配按下时间并找到触摸结束时的时间差

代码:

//variable to calculate the press time
static var pressStartTime: TimeInterval = 0.0

func handleRecognizer(gesture: UILongPressGestureRecognizer) -> Double {
    var duration: TimeInterval = 0

    switch (gesture.state) {
    case .began:
        //Keeping start time...
        Browser.pressStartTime = NSDate.timeIntervalSinceReferenceDate

    case .ended:
        //Calculating duration
        duration = NSDate.timeIntervalSinceReferenceDate - Browser.pressStartTime
        //Note that NSTimeInterval is a double value...
        print("Duration : \(duration)")

    default:
        break;
    }

    return duration
}

You can get it by Following in Swift 3.0

Logic : Just assigning the time of press and find the difference of time when touch ends

Code :

//variable to calculate the press time
static var pressStartTime: TimeInterval = 0.0

func handleRecognizer(gesture: UILongPressGestureRecognizer) -> Double {
    var duration: TimeInterval = 0

    switch (gesture.state) {
    case .began:
        //Keeping start time...
        Browser.pressStartTime = NSDate.timeIntervalSinceReferenceDate

    case .ended:
        //Calculating duration
        duration = NSDate.timeIntervalSinceReferenceDate - Browser.pressStartTime
        //Note that NSTimeInterval is a double value...
        print("Duration : \(duration)")

    default:
        break;
    }

    return duration
}
清旖 2025-01-15 19:01:36

似乎在新的 iOS 版本中(目前是 10), .begin.ending 状态的长按识别器回调会相继发生,仅在事件结束后,即仅当您从屏幕上抬起手指时。

这使得两个事件之间的差异只有几分之一毫秒,而不是您实际搜索的差异。

在这个问题得到解决之前,我决定用 swift 从头开始​​创建另一个手势识别器,这将是它的工作框架。

import UIKit.UIGestureRecognizerSubclass
class LongPressDurationGestureRecognizer : UIGestureRecognizer {
        private var startTime : Date?
        private var _duration = 0.0
        public var duration : Double {
            get {
                return _duration
            }
        }
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
            startTime = Date() // now
            state = .begin
            //state = .possible, if you would like the recongnizer not to fire any callback until it has ended
        }
        override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
            _duration = Date().timeIntervalSince(self.startTime!)
            print("duration was \(duration) seconds")
            state = .ended
            //state = .recognized, if you would like the recongnizer not to fire any callback until it has ended
        }
 }

然后您可以轻松访问 LongPressDurationGestureRecognizer 手势识别器的 .duration 属性。

例如:

func handleLongPressDuration(_ sender: LongPressDurationGestureRecognizer) {
        print(sender.duration)
}

这个具体示例没有考虑实际发生的触摸次数或其位置。但您可以轻松地使用它,扩展 LongPressDurationGestureRecognizer。

It seems that with new iOS versions (10 for me at the moment), the long press recognizer callbacks for both the .begin and .ended states happen one after the other, only after the event has ended, that is only when you raise your finger from the screen.

That makes the difference between the two events be fractions of milliseconds, and not what you were actually searching for.

Until this will be fixed, I decided to create another gesture recognizer from scratch in swift, and that would be its working skeleton.

import UIKit.UIGestureRecognizerSubclass
class LongPressDurationGestureRecognizer : UIGestureRecognizer {
        private var startTime : Date?
        private var _duration = 0.0
        public var duration : Double {
            get {
                return _duration
            }
        }
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
            startTime = Date() // now
            state = .begin
            //state = .possible, if you would like the recongnizer not to fire any callback until it has ended
        }
        override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
            _duration = Date().timeIntervalSince(self.startTime!)
            print("duration was \(duration) seconds")
            state = .ended
            //state = .recognized, if you would like the recongnizer not to fire any callback until it has ended
        }
 }

Then you can access the .duration property of the LongPressDurationGestureRecognizer gesture recognizer easily.

For instance:

func handleLongPressDuration(_ sender: LongPressDurationGestureRecognizer) {
        print(sender.duration)
}

This specific example, doesn't take into consideration how many touches actually took place, or their location. But you can easily play with it, extending the LongPressDurationGestureRecognizer.

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