1

I am building an app for iPhone and iPad using swift 5 and I have having some issues with constraints.

First I created all the views, stack views and labels I will need.

let st  = UIStackView()
let st1 = UIStackView()
let st2 = UIStackView()

let underConstructionStackView = UIStackView()
let scheduleJobsStackView = UIStackView()
let withoutScheduleStackView = UIStackView()
let withoutPMStackView = UIStackView()

var underConstruction = PieChartView()
var scheduleJobs = PieChartView()
var withoutSchedule = PieChartView()
var withoutPM = PieChartView()

var underConstructionLabel = UILabel()
var scheduleJobsLabel = UILabel()
var withoutScheduleLabel = UILabel()
var withoutPMLabel = UILabel()

Then I set translatesAutoresizingMaskIntoConstraints to false for all of these items:

st.translatesAutoresizingMaskIntoConstraints = false

underConstruction.translatesAutoresizingMaskIntoConstraints = false
scheduleJobs.translatesAutoresizingMaskIntoConstraints = false
withoutSchedule.translatesAutoresizingMaskIntoConstraints = false
withoutPM.translatesAutoresizingMaskIntoConstraints = false

underConstructionLabel.translatesAutoresizingMaskIntoConstraints = false
scheduleJobsLabel.translatesAutoresizingMaskIntoConstraints = false
withoutScheduleLabel.translatesAutoresizingMaskIntoConstraints = false
withoutPMLabel.translatesAutoresizingMaskIntoConstraints = false

Then I set the stack views directions and add it to the view

let size = UIScreen.main.bounds.size

if size.width < size.height {
    st.axis = .horizontal
    st1.axis = .vertical
    st2.axis = .vertical
} else {
    st.axis = .horizontal
    st1.axis = .horizontal
    st2.axis = .horizontal
}

underConstructionStackView.axis = .vertical
scheduleJobsStackView.axis = .vertical
withoutScheduleStackView.axis = .vertical
withoutPMStackView.axis = .vertical

st.distribution = .fill
st.alignment = .center

view.addSubview(st)

st.addArrangedSubview(st1)
st.addArrangedSubview(st2)

underConstructionStackView.addArrangedSubview(underConstructionLabel)
underConstructionStackView.addArrangedSubview(underConstruction)
st1.addArrangedSubview(underConstructionStackView)

scheduleJobsStackView.addArrangedSubview(scheduleJobsLabel)
scheduleJobsStackView.addArrangedSubview(scheduleJobs)
st1.addArrangedSubview(scheduleJobsStackView)

withoutScheduleStackView.addArrangedSubview(withoutScheduleLabel)
withoutScheduleStackView.addArrangedSubview(withoutSchedule)
st2.addArrangedSubview(withoutScheduleStackView)

withoutPMStackView.addArrangedSubview(withoutPMLabel)
withoutPMStackView.addArrangedSubview(withoutPM)
st2.addArrangedSubview(withoutPMStackView)

st1.distribution = .fillEqually
st2.distribution = .fillEqually

Then I programmatically created the constraints:

NSLayoutConstraint.activate([
    st.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
    st.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
    st.topAnchor.constraint(equalTo: self.communityButton.topAnchor,constant:60),

    underConstruction.widthAnchor.constraint(equalTo: underConstruction.heightAnchor),

    scheduleJobs.widthAnchor.constraint(equalTo: scheduleJobs.heightAnchor),

    withoutSchedule.widthAnchor.constraint(equalTo: withoutSchedule.heightAnchor),

    withoutPM.widthAnchor.constraint(equalTo: withoutPM.heightAnchor),
])

My issues is the PieChartView(),

  • iPhone - Landscape - PieChartView need to be smaller
  • iPhone - Portrait - PieChartView could be smaller
  • iPad - Portrait - PieChartView are way too big

This looks fine on iPad - Landscape

(Screen shots attached)

What do I need to do to my constraint to get the PieChartView to fit in between self.communityButton and the grid I have below the PieChartView?

I have tried setting a bottom constraint on the UIStackView to the top of the grid topAnchor, but the grid is a Shinobigrid and does not have a topAnchor.....what should I do?

enter image description here enter image description here enter image description here enter image description here

UPDATE:

I have tried the following

if size.width < size.height
        {

            if UIDevice.current.userInterfaceIdiom == .pad  {

                widthCon = st.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 1)

            }
            else
            {
                widthCon = st.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.95)
            }
        }
        else
        {

            if UIDevice.current.userInterfaceIdiom == .pad  {

                widthCon = st.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.75)

            }
            else
            {
                widthCon = st.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.75)
            }

        }

        widthCon.isActive = true

on initial load everything looks great.....however when I rotate the device everything is messed up.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)

        if UIDevice.current.userInterfaceIdiom == .pad  {

            if UIDevice.current.orientation.isPortrait  {

                widthCon = st.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.75)
            }
            else {

                widthCon = st.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 1)

            }
        }
        else {

            if UIDevice.current.orientation.isPortrait {

                widthCon = st.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.50)

            }
            else{

                widthCon = st.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.75)

            }
        }

        self.view.layoutIfNeeded()

}

1 Answer 1

2

The problem is here

st.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), 
st.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),

as it fills the screen in all devices , You need to substitute with

var widthCon:NSLayoutConstraint!

 //put inside activate
 st.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)

// outside activate
widthCon =  st.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.8)
widthCon.isActive = true

Then according to the combination you need to check do

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    if UIDevice.current.userInterfaceIdiom == .pad  {

        if UIDevice.current.orientation.isPortrait  {
            //
           widthCon.constant = size.width * 0.5 // lower it
        }
        else {
            //
        }
    }
    else {

        if UIDevice.current.orientation.isPortrait {
            // 
        }
        else{
            //
        }
    }

    self.view.layoutIfNeeded()

}
Sign up to request clarification or add additional context in comments.

4 Comments

This works on initial load, but when I rotate the device it to landscape everything looks too small, when I rotate it to Portrait everything looks too big.....What I did on the inital load is had the conditions for .pad or not and inside those conditions had a condition of landscape or Portrait...ill update my question.
you create a new constraint , follow what in answer for example for 0.7 ratio do widthCon.constant = UIScreen.main.bounds.width * 0.7
I've tried that too, did not work....instead of UIScreen.main.bounds I am going to try with the size parameter.
using the size parameter instead of UIScreen.main.bounds works!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.