detect when button is pressed down and then up Swift macOS - swift

I'm writing an app that send commands to a set top box.
The box can receive two types of commands: push and release.
I can get the button pressed on macOs in swift.
#IBAction func btnPressed(sender: NSButton) { } in which i send the command and the release. For any command such as change channel, mute or other, all works fine.
Instead, for volume up or done, I need, by doing what I do, to click several time to have the volume up or down.
I got the mouse up and down working, detecting where the click happened (inside the NSImageView (if not a button) corresponding to the up and down images) to simulate a long volume up or down press, but I can't get it inside the button pressed method.
is there a way in the 'buttonpressed' method to combine the mouse event in order to simulate a long press while holding the mouse down?
PS: I have googled and searched here also but did not find a hint.

if it can help:
1 subclass the button class to fire the action on mouseDown and mouseUp (the action will be fired twice)
class myButton: NSButton {
override func awakeFromNib() {
super.awakeFromNib()
let maskUp = NSEvent.EventTypeMask.leftMouseUp.rawValue
let maskDown = NSEvent.EventTypeMask.leftMouseDown.rawValue
let mask = Int( maskUp | maskDown ) // cast from UInt
//shortest way for the above:
//let mask = NSEvent.EventTypeMask(arrayLiteral: [.leftMouseUp, .leftMouseDown]).rawValue
self.sendAction(on: NSEvent.EventTypeMask(rawValue: NSEvent.EventTypeMask.RawValue(mask)))
//objC gives: [self.button sendActionOn: NSLeftMouseDownMask | NSLeftMouseUpMask];
}
}
2: in the storyboard, change the class of the NSButton to your class:
3: set the sender of the action to your subclass and check the currentEvent type:
#IBAction func volUpPressed(sender: myButton) {
let currEvent = NSApp.currentEvent
if(currEvent?.type == .leftMouseDown) {
print("volume Up pressed Down")
//... do your stuff here on mouseDown
}
else
if(currEvent?.type == .leftMouseUp) {
print("volume Up pressed Up")
//... do your stuff here on mouseUp
}
}

Related

Adding long-press to a button while maintaining normal highlight behavior?

I have a button with a long-press gesture recognizer assigned to it.
I would like the button to remain highlighted (just as it would during a normal click) for the duration of a long press, AND for the single click NOT to be triggered after the long press.
What I have tried so far:
To illustrate why it might be important to have this functionality, let's take the example of a UILabel that displays a number, and a button that increments that number.
A single click should increment the number by 1, and a long-press should increment it by 10 (a timer could be added later that "auto-increments" the number as the finger is held down, but for the purposes of this example, I am leaving that out).
So I started with this code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var numberDisplayLabel: UILabel!
#IBOutlet weak var incrementNumberButton: UIButton!
#IBOutlet var buttonLPGR: UILongPressGestureRecognizer!
var numVal = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
numberDisplayLabel.text = String(numVal)
}
#IBAction func buttonClicked(_ sender: UIButton) {
print("button clicked")
numVal += 1
numberDisplayLabel.text = String(numVal)
}
#IBAction func longPressOnButtonRecognized(_ sender: UILongPressGestureRecognizer) {
print("long press recognized, state: \(sender.state.rawValue)")
if (sender.state == .ended) {
numVal += 10
numberDisplayLabel.text = String(numVal)
}
}
}
Let's try to single click and see if that works:
Yes it does, YAY.
Now let's see what happens if we long-press it:
So... you can see that the button highlights when touched down (as normal), but when the long press is recognized (enters the .began state), the highlight is cancelled. When we finally release the touch, the number is incremented by 10 as expected.
But what if we want the button to remain highlighted during the entire process...
we could try adding this code to viewDidLoad():
buttonLPGR.cancelsTouchesInView = false
This should prevent the initial touch from being cancelled by the long-press recognition.
Let's see! :
Hmmm well we got what we wanted as far as the highlighting, but now, since the regular press is no longer cancelled by the long press, the button's touchUpInside action function is still called and so the number is incremented not only by 10, but by 1 also.
This is where I don't know what to do from this point.
So, once again: How can we have the button remain highlighted (just as it would during a normal click) for the duration of a long press, AND for the single click NOT to be triggered after the long press?
If the touch framework provides a way of doing this without a work-around, that would be preferred.

How to create toggle button that only toggles once

I want to create a button that, when pressed, toggles to a different format and stays that way, not allowing the user to toggle it back. For example, I am trying to create a button that says "Special 1" then when it is clicked by the user, it toggles to say "USED". When the word "USED" pops up on the UIButton, it stays that way and the user cannot change it back. Please help me out I can't figure this out. I am also open to other ideas to execute this other then a UIButton, for example maybe a UITableView??
What you can do is create a boolean (true or false) variable in your ViewController, and whenever the button is tapped you set this variable so that the tap function associated with the button can be manipulated.
1.) Make an action connection from your ViewController to your code this can be done by clicking the dual view button (the two circles in the top right corner) then holding control and drag your button into your code. :
For more information on connecting views to your code: https://codewithchris.com/9-hooking-it-all-up-swift-iboutlet-properties/
Skip to 6 min for the actual connection.
2.) Now we can just make our boolean variable, and make a basic if statement:
var didClick:Bool = false
#IBAction func touchButton(_ sender: UIButton) {
if !didClick { // If didClick is false
didClick = true // Set it to true
sender.setTitle("USED", for: .normal)
}
}
Note: The sender should be set to UIButton NOT Any
Should look like this:
_ sender: UIButton
If you are using a storyboard you can write this inside the IBAction function:
#IBAction func buttonName(_ sender: UIButton) {
sender.isUserInteractionEnabled = false
// Do whatever you need to do after...
}
sender's type could be UIButton or Any depending on how you made the connection from the storyboard.

Hide button function if statement issue - Swift

I have a function to hide a slider if another button is pressed. I currently have:
#IBOutlet weak var sliderHide: UISlider!
#IBAction func sliderHide(sender: UISlider) {
if (buttonPlay.selected) {
sliderHide.hidden = false
}
else if (!buttonPlay.selected) {
sliderHide.hidden = true
}
}
The build is running but the slider only hides if itself is selected. It does nothing if the button is selected.
Use == not = when comparing,= is an assignment operator.
Moreover, if buttonImage is not a variable representing the control state of a button, but the button itself you want to do:
if buttonImage.selected == false {
}
However, you should use an #IBAction for the button if you want to run a function when it is pressed.
Please consider using an #IBAction for this kind of thing unless your button is programmatically created. You can read more about it here:
http://rshankar.com/different-ways-to-connect-ibaction-to-uibutton/
I
I think you want
add an Outlet to the slider like the picture and then wherever you play the sound, make the sliderYouMightHide.hidden = false and wherever the sound stops make the sliderYouMightHide.hidden = true. You might also want to make it hidden in viewDidLoad

Swift enable point - make a point be clickable again

I am a beginner and I am building a RPN calculator. I have disabled the point key (not clickable anymore) if the digit situated in the display has already a point. How can I enable it again after having pressed the enter key? Because now, it stays disabled even if I enter another digit in the display. So if I clicked on the point key once for the first digit, I cannot add a point for the second digit of my operation.
I have that code for to add a point to a digit:
#IBAction func floatingPoint(sender: UIButton) {
labelDisplay.text = labelDisplay.text! + "."
sender.enabled = false //not clickable if the digit as already a point
}
I have that code for enter:
var enterPressed = false
#IBAction func Enter() {
userHasStartedTyping = false
self.calcEngine!.operandStack.append(displayValue)
print("Operand Stack on engine = \(self.calcEngine!.operandStack)")
}
I have that code for the operation:
#IBAction func operation(sender: UIButton) {
let operation = sender.currentTitle!
if userHasStartedTyping {
Enter()
}
self.displayValue = (self.calcEngine?.operate(operation))!
Enter() //
}
You will have to add an #IBOutlet in your class, so you can access this button from various parts of your code, not just it's action method. For example, add this to the top of your view controller:
#IBOutlet var pointButton:UIButton!
Remember to connect the button to this outlet on your storyboard.
With that, you can re-enable the point button in your Enter() method for example. Like this:
pointButton:UIButton.enabled = true

How to stop my UIButton animation SWIFT

I made an animation with UIButton via somes images.
Here's the code:
#IBAction func Touchdown(sender: AnyObject) {
Izer.setImage(image1, forState: UIControlState.Normal)
Izer.imageView!.animationImages = [image1, image2, image3, image4, image5,
image6, image7,image8]
Izer.imageView!.animationDuration = 0.9
Izer.imageView!.startAnimating()
playButton.enabled = false
}
#IBAction func TouchUp(sender: AnyObject) {
soundRecorder.stop()
playButton.enabled = true
}
When I touch the button , the animation start. But I want to stop it via my Touchup function.
How can I do it ?
Thank you , and sorry for my bad english :(
Add this to your TouchUp func:
Izer.imageView!.stopAnimating()
p.s. A good place to find information about functions is in the Apple documentation - it really is quite good. So this is the page for an imageView and if you look on the left under tasks, or if you scroll down, you can see the functions and properties you can call and set for animating an imageView.
Ok, looks like you want the button to act as a toggle switch. On the first touch the button starts animating an imageview and records something. When touched again the animation stops and the button is enabled again.
You can achieve this by declaring a bool variable that tracks the state of the button. If the boolean value is set to true, you run the animation & recording. If the boolean value is false, you stop the and recording.
Here is the sample code :
class ViewController: UIViewController {
#IBOutlet weak var mainView: UIView!
var isButtonPressed = false{
// Adding a Property Observer, that reacts to changes in button state
didSet{
if isButtonPressed{
// Run the Recording function & Animation Function.
startAnimationAndRecording()
}else{
// Stop the Recoding function & Animation Function.
stopAnimationAndRecording()
}
}
}
#IBAction func changeButtonValue(sender: UIButton) {
// Toggle the button value.
isButtonPressed = !isButtonPressed
}
func startAnimationAndRecording(){
// Add your animation and recording code here.
}
func stopAnimationAndRecording(){
//Add your stop Animation & Stop Recording code here.
}
}