简体   繁体   中英

Swift, touch down on UIButton and touch up on another

I'm making a calculator app that has several UIButtons for input of digits etc. I want the user to be able to touch down on one button and, if this was not the intended button, move the finger to another button and touch up inside that one. The button that the user has his/her finger on should change background color to indicate to the user what is happening, much like Apples built in calculator app.

I've tried to do this by using touch drag inside/outside and touch drag enter/exit on the buttons, but it only works for the button where the touch originated. Meaning I can touch down on one button, drag outside, back inside and touch up inside, but I can't touch down, drag outside and touch up inside another button.

Also the area that is recognized as being inside or outside the button is larger than the bounds of the button.

Here's an example of the code I've tried for one of the buttons:

@IBAction func didTouchDownThreeButton(sender: AnyObject) {
    threeButton.backgroundColor = blueColor
}

@IBAction func didTouchUpInsideThreeButton(sender: AnyObject) {
    inputTextView.text = inputTextView.text + "3"
    threeButton.backgroundColor = lightGrayColor
}

@IBAction func didTouchDragExitThreeButton(sender: AnyObject) {
    threeButton.backgroundColor = lightGrayColor
}

@IBAction func didTouchDragEnterThreeButton(sender: AnyObject) {
    threeButton.backgroundColor = blueColor
}

Any help would be much appreciated!

I managed to create a suitable solution by overriding the functions below and keeping track of which button was touched last and second to last. The last button touched gets highlighted and the second to last gets unhighlighted. Here's my code for a two button test in case anyone should find it useful:

@IBOutlet weak var bottomButton: UIButton!
@IBOutlet weak var topButton: UIButton!

var lastTouchedButton: UIButton? = nil
var secondToLastTouchedButton: UIButton? = nil

override func touchesBegan(touches: Set<UITouch>?, withEvent event: UIEvent?) {

    let touch = touches?.first
    let location : CGPoint = (touch?.locationInView(self.view))!

    if topButton.pointInside(self.view.convertPoint(location, toView: topButton.viewForLastBaselineLayout), withEvent: nil) {

        topButton?.backgroundColor = UIColor.redColor()

    }

    else if bottomButton.pointInside(self.view.convertPoint(location, toView: bottomButton.viewForLastBaselineLayout), withEvent: nil) {

        bottomButton?.backgroundColor = UIColor.redColor()

    }

    super.touchesBegan(touches!, withEvent:event)
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

    let touch = touches.first
    let location : CGPoint = (touch?.locationInView(self.view))!

    if topButton.pointInside(self.view.convertPoint(location, toView: topButton.viewForLastBaselineLayout), withEvent: nil) {

        secondToLastTouchedButton = lastTouchedButton
        lastTouchedButton = topButton
        lastTouchedButton?.backgroundColor = UIColor.redColor()

    }

    else if bottomButton.pointInside(self.view.convertPoint(location, toView: bottomButton.viewForLastBaselineLayout), withEvent: nil) {

        secondToLastTouchedButton = lastTouchedButton
        lastTouchedButton = bottomButton
        lastTouchedButton?.backgroundColor = UIColor.redColor()

    }

    else {

        lastTouchedButton?.backgroundColor = UIColor.whiteColor()

    }


    if secondToLastTouchedButton != lastTouchedButton {
        secondToLastTouchedButton?.backgroundColor = UIColor.whiteColor()
    }

    super.touchesMoved(touches, withEvent: event)
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {

    let touch = touches.first
    let location : CGPoint = (touch?.locationInView(self.view))!

    if topButton.pointInside(self.view.convertPoint(location, toView: topButton.viewForLastBaselineLayout), withEvent: nil) {
        topButton?.backgroundColor = UIColor.whiteColor()

    }

    else if bottomButton.pointInside(self.view.convertPoint(location, toView: bottomButton.viewForLastBaselineLayout), withEvent: nil) {
        bottomButton?.backgroundColor = UIColor.whiteColor()
    }

    super.touchesEnded(touches, withEvent: event)
}

override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {

    lastTouchedButton?.backgroundColor = UIColor.whiteColor()

    super.touchesCancelled(touches, withEvent: event)
}

I've tried to do this by using touch drag inside/outside and touch drag enter/exit on the buttons, but it only works for the button where the touch originated

Absolutely right. The touch "belongs" to a view, and for as long as you keep dragging, it will still only belong to that view. Thus, the only way something like what you describe can be possible is for the touch detection to take place in the common superview of these button views.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM