JPSVolumeButtonHandler icon indicating copy to clipboard operation
JPSVolumeButtonHandler copied to clipboard

Is there a way to detect long press of volume button?

Open hyd00 opened this issue 9 years ago • 21 comments

hyd00 avatar Aug 05 '16 10:08 hyd00

I haven't used this library myself for a few years now, so I'm not sure how you could go about doing this. I hope someone else who's used it more actively recently can chime in. Maybe @joestelmach?

jpsim avatar Aug 05 '16 17:08 jpsim

I think you'll continue to get notifications when you hold the button down, so you can do something like this:

-(void)onVolumeUp: {
  if(self.timer) {
    [self.timer invalidate];
  }
  self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5
                                               target:self
                                             selector:@selector(onTimerFire)
                                             userInfo:nil
                                              repeats:NO];
}

-(void)onTimerFire {
  NSLog(@"Long Press");
  self.timer = nil;
}

You'll need some way of counting as well, since the timer will fire even if there's only one invocation of onVolumeUp

Keep in mind that the onVolumeUp method will need to run on the same thread every time for the invalidate call to work (https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/)

joestelmach avatar Aug 05 '16 18:08 joestelmach

Thanks man! This works!

hyd00 avatar Aug 06 '16 14:08 hyd00

@joestelmach Please excuse me for asking, Your solution works perfectly, and you are right, it also fires on short press of the button. Any hint as to how I can implement counting to differentiate between long and short press?

Thanks!

hyd00 avatar Aug 06 '16 14:08 hyd00

I did this but it's not working properly:

//Volume button handler
    self.volumeButtonHandler = [JPSVolumeButtonHandler volumeButtonHandlerWithUpBlock:^{
        // Volume Up Button Pressed
        ++secondsElapsed;
        [self onVolumeUp];
    } downBlock:^{
        // Volume Down Button Pressed
    }];

-(void)onVolumeUp {
    if(self.volButtonTimer) {
        [self.volButtonTimer invalidate];
    }
    self.volButtonTimer = [NSTimer scheduledTimerWithTimeInterval:0.5
                                                  target:self
                                                selector:@selector(onTimerFire)
                                                userInfo:nil
                                                 repeats:NO];

}

-(void)onTimerFire {
    NSLog(@"Long Press %d",secondsElapsed);
    if (secondsElapsed > 1)
    {
        //Do Something
    }
    else secondsElapsed = 0;

}

The DO SOMETHING block fires only when I release the button after long press. What happening is, I believe, that OnTimeFire gets called very fast, even before the secondElapsed increments to 2.

Any guides how can I fix this? @joestelmach

Thanks in anticipation :)

hyd00 avatar Aug 08 '16 07:08 hyd00

you just need to incremement a count within the if(self.volButtonTimer), then check that the count is more than one within onTimerFire

joestelmach avatar Aug 08 '16 14:08 joestelmach

Tried. Same issue. When release the button after long press, it fires the desired method. :(

hyd00 avatar Aug 09 '16 05:08 hyd00

Still waiting for any more help :(

hyd00 avatar Aug 31 '16 15:08 hyd00

paste your code and let's look at it

joestelmach avatar Aug 31 '16 16:08 joestelmach

//Volume` button handler

self.volumeButtonHandler = [JPSVolumeButtonHandler volumeButtonHandlerWithUpBlock:^{
        // Volume Up Button Pressed
        [self onVolumeUp];
    } downBlock:^{
        // Volume Down Button Pressed
    }];

-(void)onVolumeUp {
    if(self.volButtonTimer) {
        secondsElapsed = 1; //To detect long press
        [self.volButtonTimer invalidate];
    }
    self.volButtonTimer = [NSTimer scheduledTimerWithTimeInterval:0.5
                                                  target:self
                                                selector:@selector(onTimerFire)
                                                userInfo:nil
                                                 repeats:NO];

}

-(void)onTimerFire {
    NSLog(@"Long Press %d",secondsElapsed);
    if (secondsElapsed > 0)
    {
        //Do Something
    }
    else secondsElapsed = 0;

}

hyd00 avatar Aug 31 '16 16:08 hyd00

How will secondsElapsed ever be greater than 1?

joestelmach avatar Aug 31 '16 16:08 joestelmach

Sorry.Edited.Please,check

hyd00 avatar Aug 31 '16 18:08 hyd00

Hi, maybe this is a bit late, but maybe someone might find useful. If you would like to have methods called when there is long press detected you might verify secondsElapsed in onVolumeUp method like this: // let's say when count is 3 is enough to admit that it was long press `-(void)onVolumeUp {

if(self.volButtonTimer) {
    if(secondsElapsed == 3) {
         secondsElapsed = 0; 
         // call your long press method here
    }
    secondsElapsed ++;
    [self.volButtonTimer invalidate];
}
self.volButtonTimer = [NSTimer scheduledTimerWithTimeInterval:0.5
                                              target:self
                                            selector:@selector(onTimerFire)
                                            userInfo:nil
                                             repeats:NO];

}`

timov7 avatar Oct 11 '16 14:10 timov7

@timov7 let me try and get back. Did you try it urself though?

hyd00 avatar Oct 11 '16 14:10 hyd00

Yes, it is working for me.

timov7 avatar Oct 11 '16 14:10 timov7

It looks good enough to detect long press yes. But does it also help u detect short press?

hyd00 avatar Oct 11 '16 14:10 hyd00

You can detect short press in onTimeFire method `-(void)onTimeFire {

self.volButtonTimer = nil;

if (self.secondsElapsed != 0) {
    self.secondsElapsed = 0;

} else {
    NSLog(@"short");
    // short press method
}

}`

timov7 avatar Oct 11 '16 14:10 timov7

Hey @timov7 .. your solution does work, however it is never going in the following block

else {

NSLog(@"short");

// short press method
}

hyd00 avatar Oct 15 '16 11:10 hyd00

Yes, you need to make timer nil each time onTimeFire gets called. Otherwise secondsElapsed will increase continuously in onVolumeUp method.

timov7 avatar Oct 15 '16 11:10 timov7

Still confused lol ... But thanks a lot for pitching in :)

P.S You're Beautiful - James Blunt

hyd00 avatar Oct 15 '16 12:10 hyd00

I am happy to help. :) See my edited answer for onTimeFire method.

timov7 avatar Oct 15 '16 13:10 timov7