12

I'm newbie and I've wrote a customView inherited from StackView and I created a button programmatically with few attributes and when I add it to my custom view, I have two problems:

  1. If I use addArrangedSubview(myBtn), my view ignores attributes that I added and fills the whole width. But if I use addSubView(myBtn), It's ok(a blue square in 44x44)
  2. If I use addArrangedSubview(myBtn), addTarget() not works and myBtn is not clickable, but when I use addSubView(myBtn), It works perfectly.

Here is my custom view class:

import UIKit

class RatingControl: UIStackView {

//MARK: Initialization
override init(frame: CGRect) {
    super.init(frame: frame)
    setupButtons()
}

required init(coder: NSCoder) {
    super.init(coder:coder)
    setupButtons()
}

//MARK: Private Methods
private func setupButtons() {

    // Create the button
    let button = UIButton()
    button.backgroundColor = UIColor.blue

    // Add constraints
    button.translatesAutoresizingMaskIntoConstraints = false
    button.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
    button.widthAnchor.constraint(equalToConstant: 44.0).isActive = true

    // Setup the button action
    button.addTarget(self, action: #selector(ratingButtonTapped(_:)), for: .touchUpInside)

    // Add the button to the stack
    addArrangedSubview(button)

}
//MARK: Button Action
@objc func ratingButtonTapped(_ sender: Any) {
    print("Button pressed ")
}

}

Here is the preview:

enter image description here enter image description here

What's difference between addSubView() and addArrangedSubview()? why these problems happens?

Mahdi Moqadasi
  • 2,029
  • 4
  • 26
  • 52

1 Answers1

9

I'm assuming you want to add several buttons horizontally (such as with a typical "stars" rating control).

A UIStackView, as might be guessed from its .addArrangedSubview() method, arranges its subviews, based on its .axis, .alignment, .distribution and .spacing properties, as well as its frame.

So, do some reading about UIStackView and how it can be used. Most likely, you are currently constraining your custom view with:

  • top
  • leading
  • trailing (or width)

So adding your button as an arrangedSubView results in it stretching to the width of the stack view, because that's the default.

Adding it as a subview simply overlays the button on the stack view, instead of allowing the stack view to arrange it, and your stack view likely then has a height of zero -- so the button cannot be tapped.

Try setting only top and leading constraints when you add your custom stack view. That should give you a 44 x 44 button that can be tapped.

As you add more buttons using .addArrangedSubview(), those buttons will be arranged horizontally, which is probably what you want.

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • thanks @DonMag. check my images that I added to my question recently. in situation I use addView(), it is visible (does not has zero height as you said) but no responds to tap. I'm practicing [this tutorial](https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/ImplementingACustomControl.html#//apple_ref/doc/uid/TP40015214-CH19-SW1) and it uses addArrangedSubView but result is different with mine! – Mahdi Moqadasi Mar 18 '19 at 13:23
  • @MahdiMoqadasi - are you laying out your custom RatingControl in Storyboard or via code? – DonMag Mar 18 '19 at 13:43
  • @MahdiMoqadasi - oh, you're following the Food Tracker tutorial. Notice at the start of Part 4 - *"Implement a Custom Control"* - your vertical stack view is set to `Alignment: Leading`... during Part 4 you're instructed to change that to `Center`. At that point, your custom control should only be the width of the number of "star" buttons + the spacing, and should be centered below the image. If you had the vertical stack view set to `Alignment: Fill`, that is why your button stretched horizontally instead of using your defined width of `44`. – DonMag Mar 18 '19 at 14:04
  • You're missing a point. Your custom *horizontal* stackView is embedded in a *vertical* stack view. Check the `Alignment` of the vertical stack view, and make sure ***it*** is set to `Center`. If you've added left and right constraints to your custom stack view, you have gone away from that tutorial. – DonMag Mar 18 '19 at 14:51