【问题标题】:How do I create a button in swift, which senses where on the button you touch it, and gives you two values (x-axis, y-axis)如何快速创建一个按钮,它会感知您触摸按钮的位置,并为您提供两个值(x 轴,y 轴)
【发布时间】:2021-11-08 03:32:32
【问题描述】:

我想在 swift 中创建一个具有两个轴 (x, y) 的按钮,并且可以感知用户触摸它的位置,并基于此为 x 和 y 设置一个介于 0 和 1 之间的值。

我该怎么做?

【问题讨论】:

    标签: swift uibutton touch grid-layout


    【解决方案1】:

    编辑:更新答案以回应@Duncan C 指出我的错误。

    您需要创建一个自定义“按钮”,而不是使用 UIButton 来实现此目的。有两种可能的方法来做到这一点:

    1. 创建一个 UIView 来充当按钮,添加手势识别器来检测触摸,以及所有必要的方法以使其按您的意愿运行。然后您可以使用手势识别器location(ofTouch touchIndex: Int, in view: UIView?) -> CGPoint 来确定触摸的位置。根据您要求的复杂性,这可能需要大量工作。

    2. 子类 UIControl 来创建你的按钮。 UIControl 具有内置的所有触摸和事件处理支持,因此您无需重新发明轮子。您需要做的就是覆盖方法beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool

    我总是选择第二个选项,因为您可以免费获得这么多。

    这是一个快速而肮脏的示例,可以帮助您入门:

    class BigButton: UIControl {
       override init(frame: CGRect){
          super.init(frame: frame)
          let label = UILabel()
          label.text = "Big Button"
          addSubview(label)
          label.translatesAutoresizingMaskIntoConstraints = false
          NSLayoutConstraint.activate([
             label.centerXAnchor.constraint(equalTo: self.centerXAnchor),
             label.centerYAnchor.constraint(equalTo: self.centerYAnchor)
          ])
          backgroundColor = .systemMint
          addTarget(self, action: #selector(tapped), for: .touchUpInside)
       }
       
       @objc func tapped() {
          print("button tapped")
       }
       
       required init?(coder: NSCoder) {
          fatalError("init(coder:) has not been implemented")
       }
       
       //here's the key method you need to get the touch location:
        
       override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
          super.beginTracking(touch, with: event)
          //iirc overridden method can be omitted, as I think all the default implementation does is return true.  
          // It seems to work either way.  Check the docs if you are bothered.
          let touches = event?.touches(for: self)
          if let location = touches?.first?.location(in: self) {
                print(location)
          }
          return true
       }
    }
    

    对于这个简单的示例,每次单击按钮的数量时,您都会触发绑定操作和位置识别。 在不同的区域点击它几次会得到一个控制台输出

    (92.5, 112.5)
    button tapped
    (14.0, 12.0)
    button tapped
    (557.0, 14.5)
    button tapped
    (513.0, 647.0)
    button tapped
    (436.0, 563.0)
    button tapped
    (436.0, 563.0)
    button tapped
    (40.5, 25.0)
    button tapped
    

    如果您希望它们在 0 ... 1 范围内,则需要将它们计算为视图大小的一小部分。

    【讨论】:

    • 我同意继承 UIControl。但是,如果您这样做,您可能不会使用手势识别器,因为点击会转到控件,而不是手势识别器。我会说要么创建一个自定义 UIControl 子类,要么将手势识别器附加到自定义视图。
    • @DuncanC 好地方。我急忙把这两种方法混为一谈。 UIControl 应该覆盖 beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool 以获取触摸信息。或者,正如您所说,您可以使用 UIView 和手势识别器,但这将涉及您自己创建所有触摸处理......所以为什么要打扰!我会更新我的答案(即使它已被接受:-))
    猜你喜欢
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多