Slide finger across 3 buttons - Xcode & Swift

2019-07-29 10:17发布

问题:

I have 3 buttons in my UI that ultimately will perform similar to keys on a piano. Either of the 3 buttons may get tapped to perform that particular buttons actions, but the user can 'slide' their finger off onto the next button to perform button 2's action.

I did some searching and it looks like a touchesBegan method detecting the location of the tap is best. My attempt is below:

@IBOutlet weak var button1: UIButton!
@IBOutlet weak var button2: UIButton!
@IBOutlet weak var button3: UIButton!

(I don't have any action events tied to the 3 buttons, because I thought touchesBegan will cover that.)

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    var touch: UITouch = event!.allTouches()!.first!
    var location: CGPoint = touch.locationInView(touch.view!)
    if CGRectContainsPoint(button1.frame, location){
        print("button 1")
    }
    else if CGRectContainsPoint(button2.frame, location) {
        print("button 2")
    }
    else if CGRectContainsPoint(button3.frame, location) {
        print("button 3")
    }

}

Nothing prints to the console when I test this. I tested both tapping and swiping across buttons. Should I be using UIViews instead of UIButtons? Should I be using actions on the buttons? This is for Swift 2.0. Thank you.

EDIT

I have a working prototype much closer to how I envisioned this functioning. This thread here: Using iOS pan gesture to highlight buttons in grid pointed me in the direction of using a pangesture on the buttons superview.

var touchPoint = CGPoint()
var myGesture = UIPanGestureRecognizer()

viewDidLoad:

    myGesture = UIPanGestureRecognizer(target: self, action: Selector("panDetected:"))
    myGesture.maximumNumberOfTouches = 1
    view.addGestureRecognizer(myGesture)

.

func panDetected(sender : UIPanGestureRecognizer) {
    touchPoint = sender.locationInView(self.view)


        if CGRectContainsPoint(button1.frame, touchPoint) {
            button1Func()
        }

        else if CGRectContainsPoint(button2.frame, touchPoint) {
            button2Func()
        }

        else if CGRectContainsPoint(button3.frame, touchPoint) {
            button3Func()
        }

The above DOES work, however, button1Func / button2Func / button3Func all contain an animation block. When the finger is dragged within the buttons, it fires the method every time a movement is detected. I just need for this to happen once. I tried adding this to a state == .Began statement, but that prevents any functionality once the finger leaves the first tapped button.

Is there any way I can fire those methods (button1Func / button2Func / button3Func) just ONCE inside the pan gesture once the finger is inside the bounds of each of the 3 buttons? I will be happy to clarify this if it's confusing. THANKS.

回答1:

There are a whole bunch of control events you can tie to IBActions. Take a look at the UIControlEvents enum. You probably want to add actions for UIControlEventTouchDragInside, UIControlEventTouchDragEnter and a few others.