TouchUpInside UIButton之外的边界

时间:2014-07-14 21:29:09

标签: ios uibutton swift

我目前正忙着在Swift下熟悉UIKit,并找出以编程方式添加UI元素的最佳方法。但是,我发现触摸可以在按钮之外结束,但仍然会在其中注册为TouchUpInside事件。下面的ViewController来自单个视图应用程序,可以直接开始触摸,例如,按钮17,结束按钮18,仍然有buttonAction()声明"按钮点击:17"。

知道我在这里失踪的是什么吗? (编辑:这是在Xcode 6 beta 3 BTW下。)

// ViewController.swift

import UIKit

class ViewController: UIViewController {
    let scrollView:UIScrollView = UIScrollView()

    var GWIDTH:Float = 0.0
    var GHEIGHT:Float = 0.0


    override func viewDidLoad() {
        super.viewDidLoad()

        GWIDTH = self.view.bounds.size.width
        GHEIGHT = self.view.bounds.size.height

        scrollView.frame = CGRectMake(10, 10, GWIDTH-10, GHEIGHT-20)
        scrollView.contentSize = CGSize(width:GWIDTH-20, height: 0)
        self.view.addSubview(scrollView)

        for currentTag in 1...30{
            var currentButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
            currentButton.frame = CGRectMake(100, scrollView.contentSize.height, 100, 50)
            currentButton.backgroundColor = UIColor.greenColor()
            currentButton.setTitle("Test Button \(currentTag)", forState: UIControlState.Normal)
            currentButton.tag = currentTag
            currentButton.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)

            scrollView.addSubview(currentButton)
            scrollView.contentSize = CGSize(width:GWIDTH-20,height:2.0+currentButton.frame.size.height+currentButton.frame.origin.y)
        }//next
    }// end viewDidLoad()


    func buttonAction(sender:UIButton!){
        println("Button tapped: \(sender.tag)")
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


    override func prefersStatusBarHidden() -> Bool {
        return true
    }
}

1 个答案:

答案 0 :(得分:6)

好的,我们花了很多时间来深入研究这个问题,但是有一些有用的Obj-C链接......

UIControlEventTouchDragExit triggers when 100 pixels away from UIButton

How to correctly subclass UIControl?

http://www.bytearray.org/?p=5336(特别是第89行)

......似乎行为是标准的,因为触摸界面(个人我本能地发现默认区域过多,但我确信Apple做了功课)并且可以通过子类化UIControl来覆盖或询问控制事件的位置。

我选择了后者,这是Swift特别实现的:

// ViewController.swift

import UIKit

class ViewController: UIViewController {
    let buttonCount = 3

    override func viewDidLoad() {
        super.viewDidLoad()

        for currentTag:Int in 1...buttonCount{
            var currentButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
            currentButton.frame = CGRectMake(50, Float(currentTag*50), 120, 50)
            currentButton.backgroundColor = UIColor.greenColor()
            currentButton.setTitle("Test Button \(currentTag)", forState: UIControlState.Normal)
            currentButton.contentEdgeInsets = UIEdgeInsets(top:3,left:6,bottom:3,right:6)
            currentButton.tag = currentTag
            currentButton.addTarget(self,
                action: "btn_TouchDown:",
                forControlEvents: UIControlEvents.TouchDown)
            currentButton.addTarget(self,
                action: "btn_TouchDragExit:",
                forControlEvents: UIControlEvents.TouchDragExit)
            currentButton.addTarget(self,
                action: "btn_TouchUpInside:event:",
                forControlEvents: UIControlEvents.TouchUpInside)
            currentButton.sizeToFit()

            self.view.addSubview(currentButton)
        }//next
    }// end viewDidLoad()


    func btn_TouchDown(sender:UIButton!){
        println("TouchDown event: \(sender.tag)\n")
    }

    func btn_TouchDragExit(sender:UIButton!){
        println("TouchDragExit event: \(sender.tag)\n")
    }

    func btn_TouchUpInside(sender:UIButton!,event:UIEvent!){
        println("TouchUpInside event: \(sender.tag)")

        var currentTouch:CGPoint = event.allTouches().anyObject().locationInView(sender)
        println( "Point: \(currentTouch.x), \(currentTouch.y)\n" )
        if currentTouch.x > sender.frame.width{return}
        if currentTouch.x < 0 {return}
        if currentTouch.y > sender.frame.height{return}
        if currentTouch.y < 0 {return}

        println("Event ended within frame!")
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


    override func prefersStatusBarHidden() -> Bool {
        return true
    }
}