首页 > 解决方案 > Swift 将 GestureRecognizer 添加到 UIStackView 之上的 View

问题描述

我正在尝试将 GestureRecognizer 添加到 UIView,它是 UIStackView 的排列子视图。我已经尝试过thisthis。我还尝试为 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
}
}

标签: swiftuigesturerecognizeruistackview

解决方案


.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

推荐阅读