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")
}
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.
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.
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)
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.
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.
following theGuy's answer, I used the sherlock app and I immediately found the problem:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With