Question

I want to create a UIButton that can be held down, when held down it calls the "hold down" action once. when it is released, calls the "hold was release" action.

This code isn't working correctly because the touch can move inside the button and the events aren't triggered in correct order

[button handleControlEvent:UIControlEventTouchDown withBlock:^{
        [self performMomentaryAction:PXActionTypeTouchDown];
    }];
[button handleControlEvent:UIControlEventTouchUpInside withBlock:^{
        [self performMomentaryAction:PXActionTypeTouchUp];
    }];

handle control events is based on UIBUtton+block implementation

Was it helpful?

Solution

try this

  UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  aButton.frame = CGRectMake(xValue, yValue, 45, 45);
  [aButton addTarget:self action:@selector(holdDown) forControlEvents:UIControlEventTouchDown];
  [aButton addTarget:self action:@selector(holdRelease) forControlEvents:UIControlEventTouchUpInside];


 - (void)holdDown
  {
     NSLog(@"hold Down");
  }

  - (void)holdRelease
  {
      NSLog(@"hold release");

  }

for NSPratik's case: u can use the event UIControlEventTouchUpOutside If user long press button and after some time, instead of releasing the finger, user will move his/her finger out of the bounds of button. just add one more event.

  UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  aButton.frame = CGRectMake(xValue, yValue, 45, 45);
  [aButton addTarget:self action:@selector(holdDown) forControlEvents:UIControlEventTouchDown];
  [aButton addTarget:self action:@selector(holdRelease) forControlEvents:UIControlEventTouchUpInside];
  [aButton addTarget:self action:@selector(holdReleaseOutSide) forControlEvents:UIControlEventTouchUpOutside]; //add this for your case releasing the finger out side of the button's frame

 //add this method along with other methods 
  - (void)holdReleaseOutSide
  {
     NSLog(@"hold release out side");
  }

Swift Version

 var  aButton:UIButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
 aButton.frame = CGRectMake(xValue,yValue, 45, 45)
 aButton.setTitle("aButton", forState: UIControlState.Normal)
 aButton.backgroundColor = UIColor.greenColor()
 aButton.addTarget(self, action: Selector("holdRelease:"), forControlEvents: UIControlEvents.TouchUpInside);
 aButton.addTarget(self, action: Selector("HoldDown:"), forControlEvents: UIControlEvents.TouchDown)
 self.addSubview(aButton)

 //target functions   
 func HoldDown(sender:UIButton)
 {
    print("hold down")
 }

 func holdRelease(sender:UIButton)
 {
    print("hold release")
 }

OTHER TIPS

Try this

Add TouchDown ,Touch Up Inside, Touch Up Outside event to ur button

enter image description here

 -(IBAction)theTouchDown:(id)sender
 {

    timer = [NSTimer scheduledTimerWithTimeInterval:0.2
                                             target:self
                                           selector:@selector(performFunctionality)
                                           userInfo:nil
  }
-(IBAction)theTouchUpInside:(id)sender
{
[timer invalidate];
timer = nil;
[self performFunctionality];

 }


 -(IBAction)theTouchUpOutside:(id)sender
 {
[timer invalidate];
timer = nil;
 }

-(void)performFunctionality
 {
 //write your logic
 }

I have faced this problem myself, and mostly we use these events:-

// This event works fine and fires

[aButton addTarget:self action:@selector(holdDown) forControlEvents:UIControlEventTouchDown];

// This does not fire at all

[aButton addTarget:self action:@selector(holdRelease) forControlEvents:UIControlEventTouchUpInside];

Solution:-

Use Long Press Gesture Recognizer:-

 UILongPressGestureRecognizer *btn_LongPress_gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleBtnLongPressgesture:)];
[aButton addGestureRecognizer:btn_LongPress_gesture];

Implementation of gesture:-

- (void)handleBtnLongPressgesture:(UILongPressGestureRecognizer *)recognizer{


//as you hold the button this would fire

if (recognizer.state == UIGestureRecognizerStateBegan) {

    [self holdDown];
}

//as you release the button this would fire

if (recognizer.state == UIGestureRecognizerStateEnded) {

    [self holdRelease];
}
}
    **in Swift 3.0,**

btnPasswordShow.addTarget(self, action:#selector(btnShowPasswordClickHoldDown), for: .touchDown)

btnPasswordShow.addTarget(self, action:#selector(btnShowPasswordClickRelease), for: .touchUpInside)

 func btnShowPasswordClickHoldDown(){
    txtpassword.isSecureTextEntry = false
 }

 func btnShowPasswordClickRelease(){
     txtpassword.isSecureTextEntry = true
 }

drag a button from tools(pane) and right click on it.a list will occur find "touch up inside" and click and drag on circle point that on front of text and move it to viewcontroller.h and define a name and in viewcontroller.m do this.

nslog("clicked in"); repeat all action for touch out and find an appropriate event from list

You need to connect following two events 1.Touch Down ,2.Touch Up Inside to it's IBAction Methods .It will be fun in Interface Builder. But you can do it programmatically also using addTarget: action: forControlEvents:

You can use Timer and and button touchup to handle this action


 var timer: Timer?

    @IBAction func dowm(_ sender: UIButton) {
        timer = Timer.scheduledTimer(withTimeInterval: 0.3, repeats: true, block: { (time) in
            print("im hold in ")
        })
    }

    @IBAction func up(_ sender: UIButton) {
        timer!.invalidate()

    }

this two @IBAction are for handle touch up and touch down button when button touch down timer is started and print something and when button is going u invalidate timer.

access to completed project from Github :

https://github.com/sadeghgoo/RunCodeWhenUIbuttonIsHeld

The best solution I have for this is to copy the following into your viewDidLoad:

// This will start your action.
hornTouchUp.addTarget(self, action: #selector(start), for: .touchDown)

// This will end your action.
hornTouchUp.addTarget(self, action: #selector(end), for: .touchUpInside)

And place these functions under your viewDidLoad in the same file:

@objc func start() { print("start() triggered."); }
@objc func end() { print("end() triggered"); }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top