DND 23: Scaling UI Sizes with Dynamic Type

Design Notes Diary

As I’ve started to roll out the wider TestFlight testing of the upcoming Pedometer++ a consistent bit of feedback I’ve received is “EVERYTHING IS TOO BIG”.

I thought that the UI looked good but I got this message back enough times that clearly the issue was me…and maybe I need to start using the 110% dynamic type size on my own iPhone…rather than just scaling up my own app’s UI to fit my aging eyes.

So today I went through the app and scaled down the general sizing of every element in the app. That would ordinarily be a pretty daunting task, if I hadn’t been planning for just this eventuality all along.

Rather than hard coding any size values in the app, I instead base every size related metric off of a common baseline value. This value is passed around my app via a common Environment Value type.

I use a default value of 0.0 here because I never want to use the default value, so I want it to be obvious when it has fallen back to it.

In all my root views I then pass in a value that is scaled using the @ScaledMetric type which will automagically scale the value up and down with Dynamic Type sizes.

Now I can just read this common metric everywhere in the app where I need to know how large to draw things, and multiply it by whatever relative scaling factor makes sense for the context. This scaling factor is typically around 0.5-0.7 for text, and for lines and padding values it ends up with more like 0.1-0.2. I base the scaling factors generally off the values Apple provides in the HIG for dynamic type sizes…but adjusted a bit to taste.

All this means that today when I wanted to scale things down a bit all I did was adjust the root views @ScaledMetric value and this propagated down to all the views in the app. I did have to a bit of minor tweaking here and there after I shrunk things, but overall the process was very straight forward and made for easy, rapid trying out of different values.

You can get a pretty good sense of how adjusting this value “flows” through the app in these images. All I did between them is change the root views scale and the rest are just propagated changes.

I have no idea yet if this is truly a good idea yet. I’ll have to maintain this code for a few months to really know that, but so far this approach has really helped me better support Dynamic Type in a practical, sustainable way. Supporting Dynamic Type now is the default behaviour of my workflow, rather than something I have to consider specially.

David Smith