无法在嵌套的 ScrollView 中点击 UIView
Can't Tap UIView in Nested ScrollView
我有一个垂直 UIScrollView,allScrollView,和一个水平 UIScrollView,hourlyScrollView,嵌套在垂直 UIScrollView 中。在每个滚动视图中,我还有 10 个将显示数据的其他 UIView。每个视图都分配了一个 UITapGestureRecognizer。我可以点击仅在垂直滚动中的视图,但嵌套水平滚动中的 none 视图在点击时可以执行任何操作。如果有人能帮助我,我将不胜感激,因为我在这里尝试了很多建议,但都没有成功。
我的视图层次结构:
-allScrollView (vertical)
-allContentView
-hourlyScrollView (horizontal)
-hourlyContentView
-10 UIViews
-dailyContentView
-10 UIViews
viewDidLoad()
let dailyContentView = UIView()
let hourlyContentView = UIView()
let hourlyScrollView = UIScrollView()
let allContentView = UIView()
let allScrollView = UIScrollView()
override func viewDidLoad() {
super.viewDidLoad()
hourlyScrollView.translatesAutoresizingMaskIntoConstraints = false
hourlyContentView.translatesAutoresizingMaskIntoConstraints = false
allContentView.translatesAutoresizingMaskIntoConstraints = false
allScrollView.translatesAutoresizingMaskIntoConstraints = false
dailyContentView.translatesAutoresizingMaskIntoConstraints = false
layoutHourlyViews()
layoutDailyViews()
finishLayout()
}
创建水平滚动内容
func layoutHourlyViews() {
for subview in hourlyScrollView.subviews {
subview.removeFromSuperview()
}
for subView in hourlyContentView.subviews {
subView.removeFromSuperview()
}
var previousHour : UIView? = nil
for count in 1...10 {
let hourlyUIView = UIView()
hourlyUIView.backgroundColor = .blue
hourlyUIView.isUserInteractionEnabled = true
hourlyUIView.tag = count
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hourlyTap(_:)))
hourlyUIView.addGestureRecognizer(tapGesture)
let descriptionLabel = UILabel()
let borderView = UIView()
let borderViewTop = UIView()
let borderViewBottom = UIView()
borderViewTop.backgroundColor = .black
borderViewBottom.backgroundColor = .black
borderViewTop.translatesAutoresizingMaskIntoConstraints = false
borderViewBottom.translatesAutoresizingMaskIntoConstraints = false
borderView.translatesAutoresizingMaskIntoConstraints = false
hourlyUIView.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel.text = "test"
borderView.backgroundColor = .black
hourlyUIView.addSubview(borderViewBottom)
hourlyUIView.addSubview(borderViewTop)
hourlyUIView.addSubview(descriptionLabel)
hourlyUIView.addSubview(borderView)
borderViewBottom.leadingAnchor.constraint(equalTo: hourlyUIView.leadingAnchor).isActive = true
borderViewBottom.trailingAnchor.constraint(equalTo: hourlyUIView.trailingAnchor).isActive = true
borderViewBottom.bottomAnchor.constraint(equalTo: hourlyUIView.bottomAnchor).isActive = true
borderViewBottom.heightAnchor.constraint(equalToConstant: 2).isActive = true
borderViewTop.leadingAnchor.constraint(equalTo: hourlyUIView.leadingAnchor).isActive = true
borderViewTop.trailingAnchor.constraint(equalTo: hourlyUIView.trailingAnchor).isActive = true
borderViewTop.topAnchor.constraint(equalTo: hourlyUIView.topAnchor).isActive = true
borderViewTop.heightAnchor.constraint(equalToConstant: 2).isActive = true
hourlyUIView.widthAnchor.constraint(equalToConstant: 160).isActive = true
hourlyUIView.heightAnchor.constraint(equalToConstant: 240).isActive = true
descriptionLabel.topAnchor.constraint(equalTo: hourlyUIView.topAnchor, constant: 16).isActive = true
descriptionLabel.centerXAnchor.constraint(equalTo: hourlyUIView.centerXAnchor, constant: 0).isActive = true
hourlyContentView.addSubview(hourlyUIView)
if previousHour == nil {
hourlyUIView.topAnchor.constraint(equalTo: hourlyContentView.topAnchor, constant: 0).isActive = true
hourlyUIView.leadingAnchor.constraint(equalTo: hourlyContentView.leadingAnchor, constant: 2).isActive = true
}
else {
hourlyUIView.topAnchor.constraint(equalTo: hourlyContentView.topAnchor, constant: 0).isActive = true
hourlyUIView.leadingAnchor.constraint(equalTo: previousHour!.trailingAnchor, constant: 0).isActive = true
borderView.bottomAnchor.constraint(equalTo: hourlyUIView.bottomAnchor).isActive = true
borderView.topAnchor.constraint(equalTo: hourlyUIView.topAnchor).isActive = true
borderView.widthAnchor.constraint(equalToConstant: 2).isActive = true
borderView.leadingAnchor.constraint(equalTo: hourlyUIView.leadingAnchor).isActive = true
}
previousHour = hourlyUIView
}
let borderViewTop = UIView()
let borderViewBottom = UIView()
borderViewTop.backgroundColor = .black
borderViewBottom.backgroundColor = .black
borderViewTop.translatesAutoresizingMaskIntoConstraints = false
borderViewBottom.translatesAutoresizingMaskIntoConstraints = false
hourlyScrollView.addSubview(hourlyContentView)
hourlyContentView.leadingAnchor.constraint(equalTo: hourlyScrollView.leadingAnchor, constant: 0).isActive = true
hourlyContentView.topAnchor.constraint(equalTo: hourlyScrollView.topAnchor, constant: 0).isActive = true
hourlyContentView.trailingAnchor.constraint(equalTo: hourlyScrollView.trailingAnchor, constant: 0).isActive = true
hourlyContentView.bottomAnchor.constraint(equalTo: hourlyScrollView.bottomAnchor, constant: 0).isActive = true
allContentView.addSubview(hourlyScrollView)
hourlyScrollView.isScrollEnabled = true
hourlyScrollView.topAnchor.constraint(equalTo: allContentView.topAnchor, constant: 20).isActive = true
hourlyScrollView.leadingAnchor.constraint(equalTo: allContentView.leadingAnchor, constant: 0).isActive = true
hourlyScrollView.trailingAnchor.constraint(equalTo: allContentView.trailingAnchor, constant: 0).isActive = true
}
创建垂直滚动内容
func layoutDailyViews() {
for subview in dailyContentView.subviews {
subview.removeFromSuperview()
}
var previousDay : UIView? = nil
for count in 1...10 {
let dailyUIView = UIView()
//dailyUIView.isUserInteractionEnabled = true
dailyUIView.tag = count
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dailyTap(_:)))
dailyUIView.addGestureRecognizer(tapGesture)
//hourlyUIView.frame.size = CGSize(width: 500, height: 50)
let descriptionLabel = UILabel()
dailyUIView.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel.text = "daily test"
let borderView = UIView()
borderView.translatesAutoresizingMaskIntoConstraints = false
borderView.backgroundColor = .black
dailyUIView.addSubview(descriptionLabel)
dailyUIView.addSubview(borderView)
borderView.bottomAnchor.constraint(equalTo: dailyUIView.bottomAnchor).isActive = true
borderView.heightAnchor.constraint(equalToConstant: 2).isActive = true
borderView.leadingAnchor.constraint(equalTo: dailyUIView.leadingAnchor).isActive = true
borderView.trailingAnchor.constraint(equalTo: dailyUIView.trailingAnchor).isActive = true
dailyUIView.heightAnchor.constraint(equalToConstant: 100).isActive = true
descriptionLabel.leadingAnchor.constraint(equalTo: dailyUIView.leadingAnchor, constant: 16).isActive = true
descriptionLabel.centerYAnchor.constraint(equalTo: dailyUIView.centerYAnchor, constant: 0).isActive = true
dailyContentView.addSubview(dailyUIView)
if previousDay == nil {
dailyUIView.topAnchor.constraint(equalTo: dailyContentView.topAnchor, constant: 0).isActive = true
}
else {
dailyUIView.topAnchor.constraint(equalTo: previousDay!.bottomAnchor, constant: 0).isActive = true
}
dailyUIView.widthAnchor.constraint(equalToConstant: view.frame.width - 4).isActive = true
dailyUIView.centerXAnchor.constraint(equalTo: dailyContentView.centerXAnchor).isActive = true
previousDay = dailyUIView
}
allContentView.addSubview(dailyContentView)
}
func finishLayout() {
hourlyScrollView.bottomAnchor.constraint(equalTo: dailyContentView.bottomAnchor, constant: 0).isActive = true
dailyContentView.topAnchor.constraint(equalTo: allContentView.topAnchor, constant: 260).isActive = true
dailyContentView.centerXAnchor.constraint(equalTo: allContentView.centerXAnchor, constant: 0).isActive = true
dailyContentView.leadingAnchor.constraint(equalTo: allContentView.leadingAnchor).isActive = true
dailyContentView.trailingAnchor.constraint(equalTo: allContentView.trailingAnchor, constant: 0).isActive = true
dailyContentView.bottomAnchor.constraint(equalTo: allContentView.bottomAnchor).isActive = true
allScrollView.addSubview(allContentView)
allContentView.topAnchor.constraint(equalTo: allScrollView.topAnchor).isActive = true
allContentView.leadingAnchor.constraint(equalTo: allScrollView.leadingAnchor).isActive = true
allContentView.trailingAnchor.constraint(equalTo: allScrollView.trailingAnchor).isActive = true
allContentView.bottomAnchor.constraint(equalTo: allScrollView.bottomAnchor).isActive = true
allContentView.centerXAnchor.constraint(equalTo: allScrollView.centerXAnchor).isActive = true
allContentView.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
allContentView.heightAnchor.constraint(equalToConstant: 1500).isActive = true
view.addSubview(allScrollView)
allScrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
allScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
allScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
allScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
点击函数
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
hourlyScrollView.contentSize = CGSize(width:160 * 10 + 2, height:240)
allScrollView.contentSize = CGSize(width: view.frame.width, height:1500)
}
@objc func hourlyTap(_ sender: UITapGestureRecognizer) {
let tappedView = sender.view
print("hourly: \(tappedView!.tag)")
}
@objc func dailyTap(_ sender: UITapGestureRecognizer) {
let tappedView = sender.view
print("daily: \(tappedView!.tag)")
}
您尚未在 hourlyContentView
上设置所有必需的约束,因此水平滚动视图的大小为 (0,0)
,因此无法滚动或点击。您可以在 Xcode 中使用 Debug View Hierarchy
来查看此内容。
您需要添加的约束是:
- 在你最后一个
hourlyUIView
的 trailingAnchor 和 hourlyContentView
的尾随锚点之间:
...
previousHour = hourlyUIView
}
previousHour?.trailingAnchor.constraint(equalTo: hourlyContentView.trailingAnchor).isActive = true
let borderViewTop = UIView()
let borderViewBottom = UIView()
...
- 将您的
hourlyContentView
heightAnchor 设置为等于 hourlyScrollView
高度锚点:
hourlyContentView.heightAnchor.constraint(equalTo: hourlyScrollView.heightAnchor).isActive = true
我有一个垂直 UIScrollView,allScrollView,和一个水平 UIScrollView,hourlyScrollView,嵌套在垂直 UIScrollView 中。在每个滚动视图中,我还有 10 个将显示数据的其他 UIView。每个视图都分配了一个 UITapGestureRecognizer。我可以点击仅在垂直滚动中的视图,但嵌套水平滚动中的 none 视图在点击时可以执行任何操作。如果有人能帮助我,我将不胜感激,因为我在这里尝试了很多建议,但都没有成功。
我的视图层次结构:
-allScrollView (vertical)
-allContentView
-hourlyScrollView (horizontal)
-hourlyContentView
-10 UIViews
-dailyContentView
-10 UIViews
viewDidLoad()
let dailyContentView = UIView()
let hourlyContentView = UIView()
let hourlyScrollView = UIScrollView()
let allContentView = UIView()
let allScrollView = UIScrollView()
override func viewDidLoad() {
super.viewDidLoad()
hourlyScrollView.translatesAutoresizingMaskIntoConstraints = false
hourlyContentView.translatesAutoresizingMaskIntoConstraints = false
allContentView.translatesAutoresizingMaskIntoConstraints = false
allScrollView.translatesAutoresizingMaskIntoConstraints = false
dailyContentView.translatesAutoresizingMaskIntoConstraints = false
layoutHourlyViews()
layoutDailyViews()
finishLayout()
}
创建水平滚动内容
func layoutHourlyViews() {
for subview in hourlyScrollView.subviews {
subview.removeFromSuperview()
}
for subView in hourlyContentView.subviews {
subView.removeFromSuperview()
}
var previousHour : UIView? = nil
for count in 1...10 {
let hourlyUIView = UIView()
hourlyUIView.backgroundColor = .blue
hourlyUIView.isUserInteractionEnabled = true
hourlyUIView.tag = count
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hourlyTap(_:)))
hourlyUIView.addGestureRecognizer(tapGesture)
let descriptionLabel = UILabel()
let borderView = UIView()
let borderViewTop = UIView()
let borderViewBottom = UIView()
borderViewTop.backgroundColor = .black
borderViewBottom.backgroundColor = .black
borderViewTop.translatesAutoresizingMaskIntoConstraints = false
borderViewBottom.translatesAutoresizingMaskIntoConstraints = false
borderView.translatesAutoresizingMaskIntoConstraints = false
hourlyUIView.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel.text = "test"
borderView.backgroundColor = .black
hourlyUIView.addSubview(borderViewBottom)
hourlyUIView.addSubview(borderViewTop)
hourlyUIView.addSubview(descriptionLabel)
hourlyUIView.addSubview(borderView)
borderViewBottom.leadingAnchor.constraint(equalTo: hourlyUIView.leadingAnchor).isActive = true
borderViewBottom.trailingAnchor.constraint(equalTo: hourlyUIView.trailingAnchor).isActive = true
borderViewBottom.bottomAnchor.constraint(equalTo: hourlyUIView.bottomAnchor).isActive = true
borderViewBottom.heightAnchor.constraint(equalToConstant: 2).isActive = true
borderViewTop.leadingAnchor.constraint(equalTo: hourlyUIView.leadingAnchor).isActive = true
borderViewTop.trailingAnchor.constraint(equalTo: hourlyUIView.trailingAnchor).isActive = true
borderViewTop.topAnchor.constraint(equalTo: hourlyUIView.topAnchor).isActive = true
borderViewTop.heightAnchor.constraint(equalToConstant: 2).isActive = true
hourlyUIView.widthAnchor.constraint(equalToConstant: 160).isActive = true
hourlyUIView.heightAnchor.constraint(equalToConstant: 240).isActive = true
descriptionLabel.topAnchor.constraint(equalTo: hourlyUIView.topAnchor, constant: 16).isActive = true
descriptionLabel.centerXAnchor.constraint(equalTo: hourlyUIView.centerXAnchor, constant: 0).isActive = true
hourlyContentView.addSubview(hourlyUIView)
if previousHour == nil {
hourlyUIView.topAnchor.constraint(equalTo: hourlyContentView.topAnchor, constant: 0).isActive = true
hourlyUIView.leadingAnchor.constraint(equalTo: hourlyContentView.leadingAnchor, constant: 2).isActive = true
}
else {
hourlyUIView.topAnchor.constraint(equalTo: hourlyContentView.topAnchor, constant: 0).isActive = true
hourlyUIView.leadingAnchor.constraint(equalTo: previousHour!.trailingAnchor, constant: 0).isActive = true
borderView.bottomAnchor.constraint(equalTo: hourlyUIView.bottomAnchor).isActive = true
borderView.topAnchor.constraint(equalTo: hourlyUIView.topAnchor).isActive = true
borderView.widthAnchor.constraint(equalToConstant: 2).isActive = true
borderView.leadingAnchor.constraint(equalTo: hourlyUIView.leadingAnchor).isActive = true
}
previousHour = hourlyUIView
}
let borderViewTop = UIView()
let borderViewBottom = UIView()
borderViewTop.backgroundColor = .black
borderViewBottom.backgroundColor = .black
borderViewTop.translatesAutoresizingMaskIntoConstraints = false
borderViewBottom.translatesAutoresizingMaskIntoConstraints = false
hourlyScrollView.addSubview(hourlyContentView)
hourlyContentView.leadingAnchor.constraint(equalTo: hourlyScrollView.leadingAnchor, constant: 0).isActive = true
hourlyContentView.topAnchor.constraint(equalTo: hourlyScrollView.topAnchor, constant: 0).isActive = true
hourlyContentView.trailingAnchor.constraint(equalTo: hourlyScrollView.trailingAnchor, constant: 0).isActive = true
hourlyContentView.bottomAnchor.constraint(equalTo: hourlyScrollView.bottomAnchor, constant: 0).isActive = true
allContentView.addSubview(hourlyScrollView)
hourlyScrollView.isScrollEnabled = true
hourlyScrollView.topAnchor.constraint(equalTo: allContentView.topAnchor, constant: 20).isActive = true
hourlyScrollView.leadingAnchor.constraint(equalTo: allContentView.leadingAnchor, constant: 0).isActive = true
hourlyScrollView.trailingAnchor.constraint(equalTo: allContentView.trailingAnchor, constant: 0).isActive = true
}
创建垂直滚动内容
func layoutDailyViews() {
for subview in dailyContentView.subviews {
subview.removeFromSuperview()
}
var previousDay : UIView? = nil
for count in 1...10 {
let dailyUIView = UIView()
//dailyUIView.isUserInteractionEnabled = true
dailyUIView.tag = count
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dailyTap(_:)))
dailyUIView.addGestureRecognizer(tapGesture)
//hourlyUIView.frame.size = CGSize(width: 500, height: 50)
let descriptionLabel = UILabel()
dailyUIView.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel.text = "daily test"
let borderView = UIView()
borderView.translatesAutoresizingMaskIntoConstraints = false
borderView.backgroundColor = .black
dailyUIView.addSubview(descriptionLabel)
dailyUIView.addSubview(borderView)
borderView.bottomAnchor.constraint(equalTo: dailyUIView.bottomAnchor).isActive = true
borderView.heightAnchor.constraint(equalToConstant: 2).isActive = true
borderView.leadingAnchor.constraint(equalTo: dailyUIView.leadingAnchor).isActive = true
borderView.trailingAnchor.constraint(equalTo: dailyUIView.trailingAnchor).isActive = true
dailyUIView.heightAnchor.constraint(equalToConstant: 100).isActive = true
descriptionLabel.leadingAnchor.constraint(equalTo: dailyUIView.leadingAnchor, constant: 16).isActive = true
descriptionLabel.centerYAnchor.constraint(equalTo: dailyUIView.centerYAnchor, constant: 0).isActive = true
dailyContentView.addSubview(dailyUIView)
if previousDay == nil {
dailyUIView.topAnchor.constraint(equalTo: dailyContentView.topAnchor, constant: 0).isActive = true
}
else {
dailyUIView.topAnchor.constraint(equalTo: previousDay!.bottomAnchor, constant: 0).isActive = true
}
dailyUIView.widthAnchor.constraint(equalToConstant: view.frame.width - 4).isActive = true
dailyUIView.centerXAnchor.constraint(equalTo: dailyContentView.centerXAnchor).isActive = true
previousDay = dailyUIView
}
allContentView.addSubview(dailyContentView)
}
func finishLayout() {
hourlyScrollView.bottomAnchor.constraint(equalTo: dailyContentView.bottomAnchor, constant: 0).isActive = true
dailyContentView.topAnchor.constraint(equalTo: allContentView.topAnchor, constant: 260).isActive = true
dailyContentView.centerXAnchor.constraint(equalTo: allContentView.centerXAnchor, constant: 0).isActive = true
dailyContentView.leadingAnchor.constraint(equalTo: allContentView.leadingAnchor).isActive = true
dailyContentView.trailingAnchor.constraint(equalTo: allContentView.trailingAnchor, constant: 0).isActive = true
dailyContentView.bottomAnchor.constraint(equalTo: allContentView.bottomAnchor).isActive = true
allScrollView.addSubview(allContentView)
allContentView.topAnchor.constraint(equalTo: allScrollView.topAnchor).isActive = true
allContentView.leadingAnchor.constraint(equalTo: allScrollView.leadingAnchor).isActive = true
allContentView.trailingAnchor.constraint(equalTo: allScrollView.trailingAnchor).isActive = true
allContentView.bottomAnchor.constraint(equalTo: allScrollView.bottomAnchor).isActive = true
allContentView.centerXAnchor.constraint(equalTo: allScrollView.centerXAnchor).isActive = true
allContentView.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
allContentView.heightAnchor.constraint(equalToConstant: 1500).isActive = true
view.addSubview(allScrollView)
allScrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
allScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
allScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
allScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
点击函数
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
hourlyScrollView.contentSize = CGSize(width:160 * 10 + 2, height:240)
allScrollView.contentSize = CGSize(width: view.frame.width, height:1500)
}
@objc func hourlyTap(_ sender: UITapGestureRecognizer) {
let tappedView = sender.view
print("hourly: \(tappedView!.tag)")
}
@objc func dailyTap(_ sender: UITapGestureRecognizer) {
let tappedView = sender.view
print("daily: \(tappedView!.tag)")
}
您尚未在 hourlyContentView
上设置所有必需的约束,因此水平滚动视图的大小为 (0,0)
,因此无法滚动或点击。您可以在 Xcode 中使用 Debug View Hierarchy
来查看此内容。
您需要添加的约束是:
- 在你最后一个
hourlyUIView
的 trailingAnchor 和hourlyContentView
的尾随锚点之间:
...
previousHour = hourlyUIView
}
previousHour?.trailingAnchor.constraint(equalTo: hourlyContentView.trailingAnchor).isActive = true
let borderViewTop = UIView()
let borderViewBottom = UIView()
...
- 将您的
hourlyContentView
heightAnchor 设置为等于hourlyScrollView
高度锚点:
hourlyContentView.heightAnchor.constraint(equalTo: hourlyScrollView.heightAnchor).isActive = true