swift - Swift 将 GestureRecognizer 添加到 UIStackView 之上的 View
问题描述
我正在尝试将 GestureRecognizer 添加到 UIView,它是 UIStackView 的排列子视图。我已经尝试过this或this。我还尝试为 userInteraction 启用所有底层视图,但它不起作用。
当我将手势识别器添加到作为 stackView 的父视图的 imageView 时,点击工作。奇怪的是,当我点击作为 stackView 的子视图的“bannerView”时,它也会被触发,因此它位于 imageView 的顶部。
在stackViews的arrangedSubview之上获得点击手势识别的正确方法是什么?
这是我的代码:
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
var imageView: UIImageView!
var bannerStackView: UIStackView!
var bannerView: UIView!
override func loadView() {
let view = UIView()
view.backgroundColor = .white
self.view = view
setupImageView()
setupBannerStackView()
setupConstraints()
}
func setupImageView() {
let image = UIImage(named: "Apple.jpeg")
imageView = UIImageView(image: image)
imageView.backgroundColor = .red
view.addSubview(imageView)
}
func setupBannerStackView() {
bannerStackView = UIStackView()
bannerStackView.axis = .vertical
bannerStackView.alignment = .leading
bannerStackView.distribution = .equalCentering
bannerStackView.isUserInteractionEnabled = true
bannerView = UIView()
bannerView.backgroundColor = .blue
bannerStackView.addArrangedSubview(bannerView)
imageView.addSubview(bannerStackView)
/*
Also tried this but didn't work
*/
// let tapGesture = UITapGestureRecognizer(target: self, action:
#selector(onBannerTapped))
// bannerView.isUserInteractionEnabled = true
// bannerView.isUserInteractionEnabled = true
// bannerView.addGestureRecognizer(tapGesture)
for bannerView in bannerStackView.arrangedSubviews {
let tapGesture = UITapGestureRecognizer(target: self, action:
#selector(onBannerTapped))
bannerView.isUserInteractionEnabled = true
bannerView.addGestureRecognizer(tapGesture)
}
}
@objc func onBannerTapped() {
print("Banner view tapped!")
}
func setupConstraints() {
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 200).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 200).isActive = true
bannerStackView.translatesAutoresizingMaskIntoConstraints = false
bannerStackView.topAnchor.constraint(equalTo: imageView.topAnchor, constant: 10).isActive = true
bannerStackView.leadingAnchor.constraint(equalTo: imageView.leadingAnchor).isActive = true
bannerView.translatesAutoresizingMaskIntoConstraints = false
bannerView.heightAnchor.constraint(equalToConstant: 30).isActive = true
bannerView.widthAnchor.constraint(equalToConstant: 80).isActive = true
}
}
解决方案
.isUserInteractionEnabled
级联到子视图。因此,即使我在子视图上将其设置为 true,如果子视图的父视图(或其父视图,以及在层次结构上)已.isUserInteractionEnabled
设置为false
,子视图也不会获得触摸事件。
因此,首先要做的是检查.isUserInteractionEnabled
层次结构中的每个视图。
在您的函数中,删除此行:
bannerStackView.isUserInteractionEnabled = true
然后在创建后添加这些行tapGesture
:
print("imageView isUserInteractionEnabled:", imageView.isUserInteractionEnabled)
print("bannerStackView isUserInteractionEnabled:", bannerStackView.isUserInteractionEnabled)
print("bannerView isUserInteractionEnabled:", bannerView.isUserInteractionEnabled)
所以它看起来像这样:
func setupBannerStackView() {
bannerStackView = UIStackView()
bannerStackView.axis = .vertical
bannerStackView.alignment = .leading
bannerStackView.distribution = .equalCentering
// remove this line (comment-it out)
// bannerStackView.isUserInteractionEnabled = true
bannerView = UIView()
bannerView.backgroundColor = .blue
bannerStackView.addArrangedSubview(bannerView)
imageView.addSubview(bannerStackView)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onBannerTapped))
bannerView.addGestureRecognizer(tapGesture)
print("view isUserInteractionEnabled:", view.isUserInteractionEnabled)
print("imageView isUserInteractionEnabled:", imageView.isUserInteractionEnabled)
print("bannerStackView isUserInteractionEnabled:", bannerStackView.isUserInteractionEnabled)
print("bannerView isUserInteractionEnabled:", bannerView.isUserInteractionEnabled)
}
你应该看到这个输出:
view isUserInteractionEnabled: true
imageView isUserInteractionEnabled: false
bannerStackView isUserInteractionEnabled: true
bannerView isUserInteractionEnabled: true
这告诉你....你只需要添加:
imageView.isUserInteractionEnabled = true
推荐阅读
- python - 使用 BOTO3 ,如何仅按日期过滤和描述快照
- c++ - 如何修复无法打开源文件:'seal/util/config.h'
- c++ - 自终止线程。使用加入或分离
- android - Retrofit 2.6.0:自定义协程 CallAdapterFactory
- json - json.decoder.JSONDecodeError 与 Python3 中的 Google Translate API
- three.js - 无法添加到场景 - 伪造查看器。错误:“THREE.Object3D.add:对象不是 THREE.Object3D 的实例。”
- php - 根据日期时间值更改实体状态
- r - 如何根据闪亮应用程序中复选框的输入设置数据框中某些行的样式?
- python-3.x - Scrapy蜘蛛没有将项目保存到PostgreSQL数据库
- c# - 在 If/else vs ? 中分配委托: