我目前想让自己熟悉Swift下的UIKit,并找出以编程方式添加UI元素的最佳方法。但是,我发现触摸可以结束于其开始的按钮之外,但仍然注册为TouchUpInside事件。下面的ViewController来自单个 View 应用程序,可以很容易地开始触摸,例如,在按钮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
    }
}

最佳答案

好吧,这需要花很多时间才能深入研究,但是有一些有用的Obj-C链接...

UIControlEventTouchDragExit triggers when 100 pixels away from UIButton

How to correctly subclass UIControl?

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

...而且由于触摸界面,这种行为似乎是标准的(个人而言,我本能地发现默认区域过多,但我确定苹果确实做了功课),并且可以通过对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
    }
}

关于ios - UIButton外部的TouchUpInside边界,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24746293/

10-09 02:31