0

I am having trouble creating a UIView instance programmatically. I have a function that returns the view so that I can use it in an NSAttachment inside a UITextView.

This is what I am trying to achieve: enter image description here This is what I am getting in the simulator: enter image description here

Code Below:

let fullView = UIView()
    let firstButton = UIButton()
    let secondButton = UIButton()
    let thirdTextView = UITextView()

    fullView.frame = CGRect(x: 0, y: 0, width: textView.frame.width, height: 90)
    fullView.backgroundColor = UIColor(red:0.82, green:0.83, blue:0.85, alpha:1.0)

    firstButton.setTitle(text1, for: .normal)
    firstButton.setTitleColor(.black, for: .normal)
    firstButton.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.medium)
    firstButton.contentHorizontalAlignment = .left

    secondButton.setTitle("Button2", for: .normal)
    secondButton.setTitleColor(.black, for: .normal)
    secondButton.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.medium)
    secondButton.contentHorizontalAlignment = .right

    thirdTextView.text = text2

    let descriptionBarStackView = UIStackView()
    descriptionBarStackView.axis = .horizontal
    descriptionBarStackView.alignment = .fill 
    descriptionBarStackView.distribution = .fillProportionally 

    descriptionBarStackView.addArrangedSubview(firstButton)
    descriptionBarStackView.addArrangedSubview(secondButton)

    let viewWithStackViews = UIStackView()
    viewWithStackViews.axis = .vertical
    viewWithStackViews.alignment = .fill // .leading .firstBaseline .center .trailing .lastBaseline
    viewWithStackViews.distribution = .fillEqually
    viewWithStackViews.addArrangedSubview(descriptionBarStackView)
    viewWithStackViews.addArrangedSubview(thirdTextView)


    fullView.addSubview(viewWithStackViews)

    descriptionBarStackView.translatesAutoresizingMaskIntoConstraints = false
    thirdTextView.translatesAutoresizingMaskIntoConstraints = false
    viewWithStackViews.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate([
    viewWithStackViews.topAnchor.constraint(equalTo: fullView.topAnchor, constant: 5),
    viewWithStackViews.leadingAnchor.constraint(equalTo: fullView.leadingAnchor, constant: 5),
    viewWithStackViews.trailingAnchor.constraint(equalTo: fullView.trailingAnchor, constant: 5),
    viewWithStackViews.bottomAnchor.constraint(equalTo: fullView.bottomAnchor, constant: 5),
    ])

Edit: enter image description here

a.wip
  • 69
  • 12

3 Answers3

1

Check this updated method

func customView(){

let fullView = UIView()
let firstButton = UIButton()
let secondButton = UIButton()
let thirdTextView = UITextView()

fullView.frame = CGRect(x: 0, y: 0, width: mainView.frame.width, height: mainView.frame.height)
fullView.backgroundColor = UIColor(red:0.82, green:0.83, blue:0.85, alpha:1.0)

firstButton.setTitle("Button1", for: .normal)
firstButton.setTitleColor(.black, for: .normal)
firstButton.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.medium)
firstButton.contentHorizontalAlignment = .left
firstButton.backgroundColor = .clear

secondButton.setTitle("Button2", for: .normal)
secondButton.setTitleColor(.black, for: .normal)
secondButton.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.medium)
secondButton.contentHorizontalAlignment = .right
secondButton.backgroundColor = .clear

thirdTextView.text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
thirdTextView.backgroundColor = .clear

let descriptionBarStackView = UIStackView()
descriptionBarStackView.axis = .horizontal
descriptionBarStackView.alignment = .fill
descriptionBarStackView.distribution = .fillProportionally
descriptionBarStackView.isLayoutMarginsRelativeArrangement = true
descriptionBarStackView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 0, leading: 5, bottom: 0, trailing: 5)

descriptionBarStackView.addArrangedSubview(firstButton)
descriptionBarStackView.addArrangedSubview(secondButton)

let viewWithStackViews = UIStackView()
viewWithStackViews.axis = .vertical
viewWithStackViews.alignment = .fill // .leading .firstBaseline .center .trailing .lastBaseline
viewWithStackViews.distribution = .fill
viewWithStackViews.addArrangedSubview(descriptionBarStackView)
viewWithStackViews.addArrangedSubview(thirdTextView)

fullView.addSubview(viewWithStackViews)

descriptionBarStackView.translatesAutoresizingMaskIntoConstraints = false
thirdTextView.translatesAutoresizingMaskIntoConstraints = false
viewWithStackViews.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: descriptionBarStackView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 30).isActive = true
NSLayoutConstraint.activate([
    viewWithStackViews.topAnchor.constraint(equalTo: fullView.topAnchor, constant: 0),
    viewWithStackViews.leadingAnchor.constraint(equalTo: fullView.leadingAnchor, constant: 0),
    viewWithStackViews.trailingAnchor.constraint(equalTo: fullView.trailingAnchor, constant: 0),
    viewWithStackViews.bottomAnchor.constraint(equalTo: fullView.bottomAnchor, constant: 0),
    ])

fullView.layer.cornerRadius = 5
mainView.addSubview(fullView)

}

here i have listed changes

  • mainView.frame.height full height based on main text view
  • firstButton.backgroundColor = .clear
  • secondButton.backgroundColor = .clear
  • thirdTextView.backgroundColor = .clear
  • margin for button descriptionBarStackView.isLayoutMarginsRelativeArrangement = true descriptionBarStackView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 0, leading: 5, bottom: 0, trailing: 5)
  • NSLayoutConstraint constraint zero to all in full view
  • fullView.layer.cornerRadius = 5

thats it here is result.. enter image description here

Samir Shaikh
  • 547
  • 3
  • 9
  • Thanks for that! 3 questions. 1. I am wanting the buttons height to not grow, so it would always be fixed and not create space. 2. I need the views height to grow dependant on how much text is provided in thirdTextView.text 3. I need the width to be the width of the textView container it seems mainView.frame.width is making it too wide... – a.wip May 27 '19 at 06:06
  • @a.wip for your first que answer is descriptionBarStackView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint(item: descriptionBarStackView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 30).isActive = true viewWithStackViews.distribution = .fill for second que set height depend on text as u want for third que set width from textview as u set – Samir Shaikh May 27 '19 at 06:29
  • Okay, added those into my code. I am still having trouble with the width, I have added an edit above. It still seems to be cutting off. – a.wip May 27 '19 at 07:19
  • okay, have u set margin and set constraint to zero for viewWithStackViews ? – Samir Shaikh May 27 '19 at 07:30
  • I am using your code from the comment and function. What am I missing? – a.wip May 27 '19 at 07:48
  • descriptionBarStackView.isLayoutMarginsRelativeArrangement = true descriptionBarStackView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 0, leading: 5, bottom: 0, trailing: 5) – Samir Shaikh May 27 '19 at 08:18
  • NSLayoutConstraint.activate([ viewWithStackViews.topAnchor.constraint(equalTo: fullView.topAnchor, constant: 0), viewWithStackViews.leadingAnchor.constraint(equalTo: fullView.leadingAnchor, constant: 0), viewWithStackViews.trailingAnchor.constraint(equalTo: fullView.trailingAnchor, constant: 0), viewWithStackViews.bottomAnchor.constraint(equalTo: fullView.bottomAnchor, constant: 0), ]) should be zero – Samir Shaikh May 27 '19 at 08:19
  • Okay, it seems something is wrong with my width because if I set it manually it's working fine... – a.wip May 27 '19 at 08:27
  • It's still not working properly. It's only working with textView.frame.width - 10 Is there an extra 10 pixels somewhere? – a.wip May 27 '19 at 08:45
1

Tried to preserve your layout structure enter image description here

class VisualTestViewController: UIViewController {

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

        let fullView = UIView()
        fullView.backgroundColor = UIColor(red:0.82, green:0.83, blue:0.85, alpha:1.0)
        fullView.translatesAutoresizingMaskIntoConstraints = false

        let firstButton = UIButton()
        firstButton.translatesAutoresizingMaskIntoConstraints = false
        let secondButton = UIButton()
        secondButton.translatesAutoresizingMaskIntoConstraints = false
        let thirdTextView = UITextView()
        thirdTextView.translatesAutoresizingMaskIntoConstraints = false



        thirdTextView.text = "lorem ipsumlorem ipsumlorem ipsumlorem ipsumlorem ipsumlorem ipsumlorem ipsumlorem ipsumlorem ipsum"

        let text1 = "Button1"
        firstButton.setTitle(text1, for: .normal)
        firstButton.setTitleColor(.black, for: .normal)
        firstButton.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.medium)
        firstButton.contentHorizontalAlignment = .left


        secondButton.setTitle("Button2", for: .normal)
        secondButton.setTitleColor(.black, for: .normal)
        secondButton.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.medium)
        secondButton.contentHorizontalAlignment = .right


        let descriptionBarStackView = UIStackView(arrangedSubviews: [firstButton, UIView() ,secondButton])
        descriptionBarStackView.translatesAutoresizingMaskIntoConstraints = false
        descriptionBarStackView.axis = .horizontal
        descriptionBarStackView.alignment = .center

        let viewWithStackViews = UIStackView(arrangedSubviews: [descriptionBarStackView, thirdTextView])
        viewWithStackViews.translatesAutoresizingMaskIntoConstraints = false
        viewWithStackViews.axis = .vertical
        viewWithStackViews.layoutMargins = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
        viewWithStackViews.isLayoutMarginsRelativeArrangement = true

        fullView.addSubview(viewWithStackViews)


        fullView.leadingAnchor.constraint(equalTo: viewWithStackViews.leadingAnchor).isActive = true
        fullView.trailingAnchor.constraint(equalTo: viewWithStackViews.trailingAnchor).isActive = true
        fullView.topAnchor.constraint(equalTo: viewWithStackViews.topAnchor).isActive = true
        fullView.bottomAnchor.constraint(equalTo: viewWithStackViews.bottomAnchor).isActive = true

        view.addSubview(fullView)
        fullView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -10).isActive = true
        fullView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        fullView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        thirdTextView.isScrollEnabled = false

        thirdTextView.backgroundColor = .clear
    }


}
plymr
  • 45
  • 7
  • How can I make view get larger dependant on how much text is in thirdTextView? – a.wip May 27 '19 at 09:26
  • checkout this https://stackoverflow.com/questions/50467/how-do-i-size-a-uitextview-to-its-content – plymr May 27 '19 at 09:34
  • That's not working for me... Can I somehow allow it to just dynamically get larger dependant on size of thirdTextView? Thanks :) – a.wip May 27 '19 at 09:52
-1

You are setting viewWithStackViews.distribution = .fillEqually Because of .fillEqually the StackView will allocate equal height to the subviews. Thats why you are seeing buttons in half of viewWithStackViews and thirdTextView in remaining half. So change it to: viewWithStackViews.distribution = .fillProportionally

One more thing: your thirdTextView is not getting its height according to its content. Try this to allow you thirdTextView to get height automatically. In case the text might be too long, set scrolledEnabled to true and set height contraint for the textView.

thirdTextView.translatesAutoresizingMaskIntoConstraints = true thirdTextView.sizeToFit() thirdTextView.scrollEnabled = false