【发布时间】:2021-11-08 03:32:32
【问题描述】:
我想在 swift 中创建一个具有两个轴 (x, y) 的按钮,并且可以感知用户触摸它的位置,并基于此为 x 和 y 设置一个介于 0 和 1 之间的值。
我该怎么做?
【问题讨论】:
标签: swift uibutton touch grid-layout
我想在 swift 中创建一个具有两个轴 (x, y) 的按钮,并且可以感知用户触摸它的位置,并基于此为 x 和 y 设置一个介于 0 和 1 之间的值。
我该怎么做?
【问题讨论】:
标签: swift uibutton touch grid-layout
编辑:更新答案以回应@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 范围内,则需要将它们计算为视图大小的一小部分。
【讨论】:
beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool 以获取触摸信息。或者,正如您所说,您可以使用 UIView 和手势识别器,但这将涉及您自己创建所有触摸处理......所以为什么要打扰!我会更新我的答案(即使它已被接受:-))