简体   繁体   中英

How to add UIView Gesture - Programmatically UIView

I have searched a lot about adding a gesture on UIView when it is tapped. There are many solutions but none of them worked for me.

I have made UIView class programmatically and using the view in different classes.

Here is my class of UIView:

class PaymentServiceView: UIView {

private let views: UIView = {
    let view = UIView()
    view.backgroundColor = .white
    // view.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]
    view.layer.borderColor = UIColor.gray.cgColor
    view.layer.shadowOpacity = 0.3
    view.layer.shadowColor = UIColor.gray.cgColor
    view.layer.shadowRadius = 10
    view.layer.borderWidth = 0.1
    view.layer.cornerRadius = 20
    view.isUserInteractionEnabled = true
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

private let titleLbl: UILabel = {
    var label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.textAlignment = .center
    label.textColor = UIColor.black
    label.font = UIFont(name: AppFontName.circularStdRegular, size: 18)
    label.clipsToBounds = true
    return label
}()

private let subLbl: UILabel = {
    var label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.textAlignment = .center
    label.textColor = UIColor.gray
    label.numberOfLines = 0
    label.textAlignment = .left
    label.font = UIFont(name: AppFontName.robotoRegular, size: 15)
    label.clipsToBounds = true
    return label
}()

private let image: UIImageView = {
    let imageView = UIImageView()
    imageView.contentMode = .scaleAspectFit
    imageView.clipsToBounds = true
    imageView.translatesAutoresizingMaskIntoConstraints = false
    return imageView
}()

private let btnImage: UIImageView = {
    let imageView = UIImageView()
    imageView.contentMode = .scaleAspectFit
    imageView.clipsToBounds = true
    imageView.image = UIImage(named: IconName.chevron_down)?.transform(withNewColor: UIColor.btnGray)
    imageView.translatesAutoresizingMaskIntoConstraints = false
    return imageView
}()

init(titleLabel: String, subTitleLabel: String, imageName: String) {
    super.init(frame: CGRect.zero)
    self.addSubview(views)
    self.views.addSubview(btnImage)
    self.views.addSubview(titleLbl)
    self.views.addSubview(image)
    self.views.addSubview(subLbl)
    
    titleLbl.text = titleLabel
    image.image = UIImage(named: imageName)
    subLbl.text = subTitleLabel
    
    setupConstraints()
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

private func setupConstraints() {
    
    self.views.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
    self.views.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
    self.views.heightAnchor.constraint(equalToConstant: 150).isActive = true
    self.views.widthAnchor.constraint(equalToConstant: 320).isActive = true
    
    self.image.centerYAnchor.constraint(equalTo: self.views.centerYAnchor).isActive = true
    self.image.leadingAnchor.constraint(equalTo: self.views.leadingAnchor, constant: 15).isActive = true
    self.image.widthAnchor.constraint(equalToConstant: 30).isActive = true
    self.image.heightAnchor.constraint(equalToConstant: 30).isActive = true
    
    self.titleLbl.centerYAnchor.constraint(equalTo: self.views.centerYAnchor, constant: -35).isActive = true
    self.titleLbl.leadingAnchor.constraint(equalTo: image.trailingAnchor, constant: 15).isActive = true
    
    self.subLbl.topAnchor.constraint(equalTo: titleLbl.bottomAnchor, constant: 5).isActive = true
    self.subLbl.leadingAnchor.constraint(equalTo: image.trailingAnchor, constant: 15).isActive = true
    self.subLbl.trailingAnchor.constraint(equalTo: btnImage.leadingAnchor, constant: -15).isActive = true
    
    btnImage.topAnchor.constraint(equalTo: views.topAnchor, constant: 55).isActive = true
    btnImage.rightAnchor.constraint(equalTo: views.rightAnchor, constant: -10).isActive = true
    btnImage.heightAnchor.constraint(equalToConstant: 10).isActive = true
    
}

}

Now Im using this UIView class in PaymentServicesViewController

class PaymentServicesViewController: UIViewController {

private (set) lazy var headerView: HeaderView = { [unowned self] in
    let view = HeaderView.init(titleLbl: Headings.paymentService, closeAction: {
        self.navigationController?.popViewController(animated: true)
    }, nextAction: {
        print("next")
    }, previousAction: {
        self.navigationController?.popViewController(animated: true)
    })
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

private let fundTransferView: PaymentServiceView = {
    
    let view = PaymentServiceView(titleLabel: Headings.fundTransfer, subTitleLabel: Description.fundTransferDecription , imageName: IconName.fundImage )
    view.isUserInteractionEnabled = true
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

private let subscriptionView: PaymentServiceView = {

    let view = PaymentServiceView(titleLabel: Headings.subscribe, subTitleLabel: Description.subscriptionDescription, imageName: IconName.subImage )
    view.isUserInteractionEnabled = true
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

private let billPaymentView: PaymentServiceView = {
    let view = PaymentServiceView(titleLabel: Headings.billPayment, subTitleLabel: Description.billPaymentDescription , imageName: IconName.billImage )
    view.isUserInteractionEnabled = true
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .gray2

    let fundtrasnferGesture = UITapGestureRecognizer(target: self, action: #selector(fundTranferTapped))
    fundTransferView.isUserInteractionEnabled = true
    self.fundTransferView.addGestureRecognizer(fundtrasnferGesture)
    
    let subscribeGesture = UITapGestureRecognizer(target: self, action: #selector(subscribeTapped))
    subscriptionView.isUserInteractionEnabled = true
    self.subscriptionView.addGestureRecognizer(subscribeGesture)

    let billPaymentGesture = UITapGestureRecognizer(target: self, action: #selector(billPaymentTapped))
    fundTransferView.isUserInteractionEnabled = true
    self.billPaymentView.addGestureRecognizer(billPaymentGesture)
    
    view.addSubview(headerView)
    view.addSubview(subscriptionView)
    view.addSubview(fundTransferView)
    view.addSubview(billPaymentView)
    setupConstraint()
}

@objc func fundTranferTapped(sender: UITapGestureRecognizer) {
    print("FundTransfer Tapped.")
}

@objc func subscribeTapped(sender: UITapGestureRecognizer) {
    print("Subscribe Tapped.")
}

@objc func billPaymentTapped(sender: UITapGestureRecognizer) {
    print("BillPayment Tapped.")
}


private func setupConstraint() {
    
    headerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    headerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    headerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    headerView.heightAnchor.constraint(equalToConstant: 100).isActive = true
    
    subscriptionView.trailingAnchor.constraint(equalTo: fundTransferView.trailingAnchor, constant: 0).isActive = true
    subscriptionView.leadingAnchor.constraint(equalTo: fundTransferView.leadingAnchor, constant: 0).isActive = true
    subscriptionView.bottomAnchor.constraint(equalTo: fundTransferView.topAnchor, constant: -130).isActive = true
    
    fundTransferView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
    fundTransferView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
    
    billPaymentView.leadingAnchor.constraint(equalTo: fundTransferView.leadingAnchor, constant: 0).isActive = true
    billPaymentView.trailingAnchor.constraint(equalTo: fundTransferView.trailingAnchor).isActive = true
    billPaymentView.topAnchor.constraint(equalTo: fundTransferView.bottomAnchor, constant: 130).isActive = true
    
}

}

I know there is a small mistake I'm doing but not sure. Help would be appreciated, Thank you.

在此处输入图像描述

You are missing a couple constraints...

If you add this at the end of viewDidLoad() :

    subscriptionView.clipsToBounds = true
    fundTransferView.clipsToBounds = true
    billPaymentView.clipsToBounds = true

You'll see that the views "disappear":

在此处输入图像描述

because they have no Width or Height constraints (so their size is .zero ).

In setupConstraints() in your PaymentServiceView class, add these two lines:

    self.widthAnchor.constraint(equalTo: self.views.widthAnchor).isActive = true
    self.heightAnchor.constraint(equalTo: self.views.heightAnchor).isActive = true

Now, the PaymentServiceView will be the same Width and Height as self.views view.

However, now that the views have Heights:

在此处输入图像描述

your layout needs to be adjusted.

Change the .clipsToBounds back to false (remove those added lines) so the shadows won't be clipped, and change these constraints in your controller (adjust the 15 and -15 to your liking):

    //subscriptionView.bottomAnchor.constraint(equalTo: fundTransferView.topAnchor, constant: -130).isActive = true
    subscriptionView.bottomAnchor.constraint(equalTo: fundTransferView.topAnchor, constant: 15).isActive = true

    //billPaymentView.topAnchor.constraint(equalTo: fundTransferView.bottomAnchor, constant: 130).isActive = true
    billPaymentView.topAnchor.constraint(equalTo: fundTransferView.bottomAnchor, constant: -15).isActive = true

and we get:

在此处输入图像描述

Now, because the views have a size, the Tap Gestures will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM