James M
James M

Reputation: 41

iOS: UIButton Appearing, But Not Functioning On UIView

There are some similar questions out there on this, but they're in Obj-C and don't specifically answer my question.

I'm building a Tinder-like dating application with a button on the card that allows the current user to view more info about the user on the displayed card. I've written this button (moreInfoButton) programmatically and have it displayed on the card (UIView) without a problem. But when I click on the button, it does not function. I've tried isEnabled and isUserInteractionEnabled, but neither work. Here's my code:

import UIKit
import SDWebImage

class CardView: UIView {

var imageView = UIImageView(image: #imageLiteral(resourceName: "lady5c"))

var informationLabel = UILabel()

var images: [String]?

var userId: String?

var stackView: UIStackView?

let moreInfoButton: UIButton = {
    let button = UIButton(type: .system)
    button.setImage(#imageLiteral(resourceName: "info_icon").withRenderingMode(.alwaysOriginal), for: .normal)
    return button
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    layer.cornerRadius = 15
    clipsToBounds = true

    imageView.contentMode = .scaleAspectFill
    addSubview(imageView)
    imageView.fillSuperview()

    addSubview(informationLabel)
    informationLabel.numberOfLines = 0
    informationLabel.anchor(top: nil, leading: leadingAnchor, bottom: bottomAnchor, trailing: trailingAnchor, padding: .init(top: 0, left: 16, bottom: 16, right: 16))
    informationLabel.text = ""
    informationLabel.textColor = .white
    informationLabel.layer.zPosition = 1

    addSubview(moreInfoButton)
    moreInfoButton.anchor(top: nil, leading: nil, bottom: bottomAnchor, trailing: trailingAnchor, padding: .init(top: 0, left: 0, bottom: 20, right: 20), size: .init(width: 50, height: 50))
    moreInfoButton.layer.zPosition = 1
    moreInfoButton.isUserInteractionEnabled = true

    // let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
    // addGestureRecognizer(panGesture)
    addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))

}

Upvotes: 0

Views: 1196

Answers (4)

rs7
rs7

Reputation: 1630

UPDATE: Since the button is sitting on top of the tappable view, make sure the button is displayed in front of the tappable view. If you are using storyboard, the button should be listed below the tappable view.

Also, in your touchesBegan method, make sure you don't respond to touches inside your button:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
    if touch?.view != button && touch?.view == tappableView {
        // Next picture
    }
}

If that still doesn't work, try this implementation of touchesBegan instead:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
    if touch?.view == button {
        // performSegue or call button's target function
    } else if touch?.view == tappableView {
        // Next picture
    }
}

You are missing a target for your button:

moreInfoButton.addTarget(self, action: #selector(buttonTapped(_:)), forControlEvents: .TouchUpInside)

and a function to handle the tap:

@objc func buttonTapped(sender: UIButton!) {
    // action
}

Upvotes: 0

erkutbas
erkutbas

Reputation: 303

if you add a button programmatically, I think you should use addTarget instead of using whole uiview gesture. This makes button has a functionality without having any relation about view gestures.

lazy var button: UIButton = {
    let temp = UIButton(type: .system)
    temp.isUserInteractionEnabled = true
    temp.addTarget(self, action: someFunction, for: UIControl.Event.touchUpInside)
    return temp
}()

Upvotes: 1

Malik
Malik

Reputation: 3802

Disable cancelsTouchesInView property of the gesture. By default, I think it is set to true. This means that the gesture consumes the touch event and it is not passed on to the button

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapGesture.cancelsTouchesInView = false
addGestureRecognizer(tapGesture)

Upvotes: 0

Thanh Vu
Thanh Vu

Reputation: 1739

I think UITapGestureRecognizer conflict with button tap event. You can try use override touchesBegan event instead of tap gesture.

Upvotes: 0

Related Questions