jpsim / JPSVolumeButtonHandler

JPSVolumeButtonHandler provides an easy block interface to hardware volume buttons on iOS devices. Perfect for camera apps!
MIT License
336 stars 91 forks source link

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

Open hyd00 opened 8 years ago

jpsim commented 8 years ago

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?

joestelmach commented 8 years ago

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/)

hyd00 commented 8 years ago

Thanks man! This works!

hyd00 commented 8 years ago

@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 commented 8 years ago

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 :)

joestelmach commented 8 years ago

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

hyd00 commented 8 years ago

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

hyd00 commented 8 years ago

Still waiting for any more help :(

joestelmach commented 8 years ago

paste your code and let's look at it

hyd00 commented 8 years ago
//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;

}
joestelmach commented 8 years ago

How will secondsElapsed ever be greater than 1?

hyd00 commented 8 years ago

Sorry.Edited.Please,check

timov7 commented 8 years ago

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];

}`

hyd00 commented 8 years ago

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

timov7 commented 8 years ago

Yes, it is working for me.

hyd00 commented 8 years ago

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

timov7 commented 8 years ago

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
}

}`

hyd00 commented 8 years ago

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

else {

NSLog(@"short");

// short press method
}
timov7 commented 8 years ago

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

hyd00 commented 8 years ago

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

P.S You're Beautiful - James Blunt

timov7 commented 8 years ago

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