如何解决如何在循环中创建的视图上处理 UITapGestureRecognizer?
我有一个垂直的 UIStackView,我在这个视图中附加了一个水平的 UIStackView 和一些 UILabels。我附加了 UITapGestureRecognizer 来处理点击动作。例如,当我点击一行时如何更改标签(这是一个子视图)?
这是我目前的代码:
for article in articleType {
//Create a row
let row = UIStackView()
row.axis = NSLayoutConstraint.Axis.horizontal
//Create a label and indicator
let label = UILabel()
label.text = article.label
let indicator = UILabel()
indicator.text = "off"
//Add label to row and row to parent stack view
row.addSubView(label)
row.addSubView(indicator)
mainUiStackView.addArrangedSubview(row)
//Create tap handled
let tap = UITapGestureRecognizer(target: self,action: #selector(self.handleTap(sender:)))
row.addGestureRecognizer(tap)
}
@objc func handleTap(sender: UITapGestureRecognizer? = nil) {
print(sender.view)
//This is where i'm stuck,how can i change the second label's text to "on" for example?
sender.view.indicator.text = "on"
}
解决方法
首先,确保您要点击的标签的 isUserInteractionEnabled
属性设置为 true
,因为它默认设置为 false
。
@objc func handleTap(_ sender: UITapGestureRecognizer) {
guard let tappedView = sender.view else { return }
let location = sender.location(in: tappedView.superview)
if case let hitView as UILabel = tappedView.hitTest(location,with: nil) {
hitView.text = hitView.text == "off" ? "on" : "off"
}
}
,
您的代码经过一个循环并在局部变量 row
中创建一系列堆栈视图。然后,您不会将这些堆栈视图添加到您的视图层次结构中,因此它们会“掉到地上”。
对于这一行:
let row = UIStackView()
每次通过 for 循环后,您创建的堆栈视图将超出范围并被释放。
编辑:
在您指出之后,我现在看到您将 row
堆栈视图添加到 mainUiStackView
的位置。
我根据您发表的评论收集到,您希望点击其中一个“行”堆栈视图,将该堆栈视图中的 indicator
标签设置为“开启”。
我建议构建一个行堆栈视图及其标签视图(作为结构)的数组。然后找到被点击的行并将其标签设置为开启状态:
struct RowStackViewStruct {
let stackView: UIStackView
let label: UILabel
}
var rowStackViews = [RowStackViewStruct]()
for article in articleType {
//Create a row
let row = UIStackView()
row.axis = NSLayoutConstraint.Axis.horizontal
//Create a label and indicator
let label = UILabel()
label.text = article.label
let indicator = UILabel()
indicator.text = "off"
//Add label to row and row to parent stack view
row.addSubView(label)
row.addSubView(indicator)
mainUiStackView.addArrangedSubview(row)
//Create tap handled
let tap = UITapGestureRecognizer(target: self,action: #selector(self.handleTap(sender:)))
row.addGestureRecognizer(tap)
//Build a RowStackViewStruct for this row
let newRowStackViewStruct = RowStackViewStruct(stackView: row,label: indicator)
rowStackViews.append(newRowStackViewStruct)
}
And then in your tap handler code:
@objc func handleTap(sender: UITapGestureRecognizer? = nil) {
print(sender.view)
if let aStruct = rowStackViews.first(where: { sender?.view == $0.stackView }) {
aStruct.label.text = "on"
}
我在 SO 编辑器中敲出了上面的代码。它可能包含轻微的语法错误,旨在作为指南,而不是您可以插入的复制粘贴代码。
看来您真的应该跟踪行的开关状态。似乎您应该拥有一组代表行状态的模型对象,并使用它来构建和维护主垂直堆栈视图。事实上,切换到表格视图或集合视图可能会更好,因为它们是由模型驱动的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。