Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unresponsive UIButton in subview added to UIStackView

In the detailViewController of a UISplitView I have subviews added to a UIStackView inside a UIScrollView.

Just using system buttons without subviews or images, results in responsive buttons, but subviews seem to interfere.

Enabling touch is specifically coded. I have attempted to keep each view inside the containing view so there will be no overlap to invalidate receiving touch events, but not sure if this is done properly. Each subview contains a label and a custom button with an image. The subview is then added to the stackview, and the stackview to the scrollview.

Thanks for any help.

override func viewDidLoad() {
    super.viewDidLoad()

    scrollView = UIScrollView()
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(scrollView)

    // Constrain the scroll view within the detailView
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: .AlignAllCenterX, metrics: nil, views: ["scrollView": scrollView]))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options: .AlignAllCenterX, metrics: nil, views: ["scrollView": scrollView]))


    stackView = UIStackView()

    stackView.frame = CGRectMake(0,0,view.frame.width, 1000)
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.axis = .Vertical
    scrollView.contentSize = CGSizeMake(400, 1000)
    scrollView.addSubview(stackView)

    // Constrain the stackView within the scrollView
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[stackView]|", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: ["stackView": stackView]))
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[stackView]", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: ["stackView": stackView]))


    let selectedGroup: Group = GroupArray[5]

    let descriptorsArray = selectedGroup.descriptorsArray

    for descriptor in descriptorsArray {
        // Create a subview for each descriptor

        let subView = UIView()
        subView.frame = CGRectMake(0 , 0, self.stackView.frame.width-10, 54)
        subView.backgroundColor = UIColor.yellowColor()

        subView.heightAnchor.constraintEqualToConstant(54.0).active = true
        // Create a label for Descriptor subview

        let label = UILabel(frame: CGRectMake(20, 0, 200, 50))
        label.text = descriptor.name
        label.font = UIFont.boldSystemFontOfSize(22.0)
        label.textAlignment = .Left
        label.textColor = UIColor.brownColor()
        label.backgroundColor = UIColor.greenColor()
        label.heightAnchor.constraintEqualToConstant(50.0).active = true
        subView.addSubview(label)

        // Create a button for Checkbox
        let btn = UIButton()
        btn.frame = CGRectMake(220, 0, 50, 50)
        btn.backgroundColor = UIColor.blueColor()
        btn.setImage(UIImage(named:"checked.png"), forState: UIControlState.Normal)

        btn.heightAnchor.constraintLessThanOrEqualToConstant(50.0)
        btn.widthAnchor.constraintLessThanOrEqualToConstant(50.0)

        btn.addTarget(self, action: "btnPressed:", forControlEvents: UIControlEvents.TouchUpInside)

        subView.addSubview(btn)
        btn.userInteractionEnabled = true
        subView.userInteractionEnabled = true
        stackView.userInteractionEnabled = true
        scrollView.userInteractionEnabled = true
        stackView.addArrangedSubview(subView)


    }
}

func btnPressed(sender: UIButton!) {

    print("btn Pressed")

}
like image 493
Jolly Avatar asked Aug 26 '16 13:08

Jolly


6 Answers

I have had the exact same issue: a StackView which contains views. Each view contains a button and a label. The views are only containers for layout reasons.

In my case: I did not give the view a height constraint and it seems that it had a zero height (after changing the background color for debugging I did not see the view), but the button and label was visible (but unresponsive).

After I have added a height constraint to the layout view the (debug) background color was visible and the buttons responded as expected.

like image 103
theguy Avatar answered Oct 07 '22 21:10

theguy


I just ran into this issue myself. In my case, I had a UIStackView as a subview of my UIButton. I needed to set isUserInteractionEnabled = false on the stack view in order to get my button to work. This is probably a wise thing to set on any UIButton subview.

like image 41
Kyle Cronin Avatar answered Oct 07 '22 20:10

Kyle Cronin


It seems to be that something is lying over your button and catching all the touch events.

1. Never turn on userInterectionEnabled if you don't need it

There is no reason why a normal view like subView should have set userInteractionEnabled set to true so put it to false.

2. Find the bug:

To find out witch view catches the event start your app on a device and navigate to the stackView. Now in Xcode, press the button "Debug View Hierarchy" (placed right over the console output)

enter image description here

After that you will see every view currently displayed on your device. What you do now is finding out wich views are above your button, and then in code turn their userInteractionEnabled value to false.

like image 30
M. Kremer Avatar answered Oct 07 '22 20:10

M. Kremer


In my case, it was the aligment property of the StackView that was causing the problem.

When I set that property to Fill instead of Center the problem dissappeared.

like image 21
jmartinalonso Avatar answered Oct 07 '22 21:10

jmartinalonso


following theGuy's answer, I used the sherlock app and I immediately found the problem:

enter image description here

like image 40
abbood Avatar answered Oct 07 '22 20:10

abbood


In my case, I had set a custom view subclass in loadView. That subclass had isUserInteractionEnabled = false which translated down to all the sub views including my stackView and all its views and buttons.

like image 45
Justin Vallely Avatar answered Oct 07 '22 20:10

Justin Vallely