如何快速创建一个按钮,它会感知您触摸按钮的位置,并为您提供两个值(x 轴,y 轴)

Posted

技术标签:

【中文标题】如何快速创建一个按钮,它会感知您触摸按钮的位置,并为您提供两个值(x 轴,y 轴)【英文标题】: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) 【发布时间】:2021-11-08 03:32:32 【问题描述】:

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

我该怎么做?

【问题讨论】:

【参考方案1】:

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

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

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

    子类 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 和手势识别器,但这将涉及您自己创建所有触摸处理......所以为什么要打扰!我会更新我的答案(即使它已被接受:-))

以上是关于如何快速创建一个按钮,它会感知您触摸按钮的位置,并为您提供两个值(x 轴,y 轴)的主要内容,如果未能解决你的问题,请参考以下文章

通过触摸移动按钮

触摸屏幕上的任何位置,除了 GUI 按钮 Android Unity

使用带有约束的持续时间动画快速移动按钮并在其中检测触摸

如何通过快速触摸单元格内的按钮来编辑文本字段

单击并拖动到另一个按钮

触摸按钮时如何更改 UIButton 图像