Denys  Triasunov
Denys Triasunov

Reputation: 569

Layout for different iPhone screens

I'm building my first real-world app after going through some tutorials and I've come across a layout issue. It is quite simple to adjust UI layout to different screen size classes, but I haven't found any information on how to adjust layout within same size class.

For example, I have a label whose Top Space constraint is set to 40 pt form top of view. It looks neat on a large iPhone 8 Plus screen:

enter image description here

But on a smaller iPhone SE screen (which is confusingly of same size class) this constraint of 40 pt pushes the label halfway through to the center, leaving reasonably less useful space below it:

enter image description here

So I was wondering if there's a way to set different constraints for different iPhones: say, 40 pt for iPhone 8 Plus, 30 pt for iPhone 8 and 20 pt for iPhone SE. Same goes about positioning other views below the label: I want them more compact vertical-wise on a small iPhone screen, and having more space between them on large screen. I know this last part can be solved with a stack view, but it's not always convenient to use.

UPD. Here is a full layout of the view on 8 Plus screen: enter image description here

It has 3 fixed constraints: 1. From 'Title' label to top of the view - 50 pt 2. From 'Percent' label to bottom of 'Title' label - 60 pt 3. From 'Details' label to bottom of the view - 80 pt.

I've used text autoshrink in all labels + height of each label is proportional to view's height. This made layout a bit more flexible, but still there's a noticible issue on small SE screen: enter image description here

As you can see, 'Details' is squeezed to 'Percent' label. At this point it would be great to move 'Percent' label higher up and closer to 'Title', but unlike heights constraints cannot be set in proportion (not in IB at least) to Superview height.

One of the options I see is to put a blank view between top and mid labels, making its height proportional and setting 'Percent' label top constraint at 0 to this blank view. Not sure though using such a "crutch" is a good practice.

Upvotes: 2

Views: 129

Answers (1)

DonMag
DonMag

Reputation: 77462

You may get your most satisfactory results by using a single UILabel and setting the Attributed Text, instead of trying to get multiple labels and font sizes to cooperate.

Try this:

  • Create a new View Controller
  • add a normal UILabel
  • set constraints to 85% of width and 80% of height, and centered both ways
  • connect the label to an IBOutlet

then:

class ScalingViewController: UIViewController {

    @IBOutlet weak var theLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        let titleFont = UIFont.systemFont(ofSize: 80.0, weight: UIFontWeightThin)
        let pctFont = UIFont.systemFont(ofSize: 100.0, weight: UIFontWeightThin)
        let paraFont = UIFont.systemFont(ofSize: 30.0, weight: UIFontWeightLight)

        // for blank lines between Title and Percent and between Percent and Body
        let blankLineFont = UIFont.systemFont(ofSize: 36.0, weight: UIFontWeightLight)

        let sTitle = "Title"
        let sPct = "78%"
        let sBody = "A detailed text explaining the meaning of percentage above and what a person should do to make it lower or higher."

        // create the Attributed String by combining Title, Percent and Body, plus blank lines
        let attText = NSMutableAttributedString()

        attText.append(NSMutableAttributedString(string: sTitle, attributes: [NSFontAttributeName: titleFont]))
        attText.append(NSMutableAttributedString(string: "\n\n", attributes: [NSFontAttributeName: blankLineFont]))
        attText.append(NSMutableAttributedString(string: sPct, attributes: [NSFontAttributeName: pctFont]))
        attText.append(NSMutableAttributedString(string: "\n\n", attributes: [NSFontAttributeName: blankLineFont]))
        attText.append(NSMutableAttributedString(string: sBody, attributes: [NSFontAttributeName: paraFont]))

        // these properties can be set in Interface Builder... or set them here to make sure.
        theLabel.textAlignment = .center
        theLabel.numberOfLines = 0
        theLabel.adjustsFontSizeToFitWidth = true
        theLabel.minimumScaleFactor = 0.05

        // set the label content
        theLabel.attributedText = attText

    }

}

This gives me these results for 7+, 6s and SE:

And, just for demonstration's sake, how it looks with additional text in the "body" paragraph:

Upvotes: 1

Related Questions