Pixel Perfection
16 March 2023 | 11:40 am

In the early days of iPhone development people would often talk about “Pixel Perfect” design, where we would sweat the details right down to the pixel. I hear a lot less of that these days. The shift towards such a wide variety of device screens and accessibility modes made it incredibly cumbersome to be designing things to that level because you’d be tweaking layouts for many dozen screens individually.

Well, I ran into a situation today where I had to pull out my old Pixel Perfect design skills, fire up xScope and get down to the pixel level.

The fast switching button in the top of Pedometer++’s workout view (discussed here) has turned out be a really great solution for providing persistent UI without getting the way. However, placing a UI element on the inside of the top corner of the Apple Watch has lead to a number of really tricky layout challenges.

Here is an array of all the different Apple Watch versions that this screen supports. If you look closely at them you’ll notice that the exact layout of the top areas are actually relatively different between the models. Pay special attention to the position of the time label for reference.

In some watches the date label is pressed closely to the top margin of the screen, in others it floats down considerably. This is largely just an artifact of the same size text being used here so the relative shape and position of the label will naturally need to be adjusted to look at home on the screen. The 40mm watch is a really different screen size to the 49mm, so naturally things will need to shift.

In my original version of this button I did some basic adjustments to account for this but after living with it for a few weeks I didn’t like the result. It wasn’t quite right.

So today I’ve gone into depth to explore what I can do better here.

The first place I looked for reference was the HIG, but it doesn’t seem to provide indications about handling layout into these corners, I think generally it is regarded as best practice to respect the safe areas and so I’m definitely (and literally) painting outside the lines with this design.

The second place I checked was in the Accessory Design Guidelines which is a document Apple publishes for case and accessory manufacturers. I was hoping it would document the corner radius for the screen in a way I could then use to guide my layout.

Sadly this was little help. If I’m reading the blueprint correctly the corner radius isn’t actually even uniform with respect to vertical and horizontal curve. 😞

Undaunted, I then just wrote a little app I could use to determine a close approximation of the corner radius of the screens. This was the result:

As far as I can tell the corner radius doesn’t seem to follow a particular formula or pattern. It is on average about 20% of the Width or 17% of the Height, but actually varies quite a lot between models.

And thus any hope I had for coming up with a general solution for this layout went out the window and I was on to manual, pixel perfect layout per device.

This isn’t too bad, thankfully I only have five watch screens to worry about and since the Apple Watch doesn’t seem to scale the status bar with Dynamic Type changes I don’t need to adjust for that either.

So I instead just spent a while trying out slight shifts one-pixel and a time until I felt that things looked ‘right’ to my eye. This was highly unscientific and I’m sure that my results would be different to that of another designer. I took my cues from how Apple has laid out the time label but ultimately I had to find a balance between left and top padding that just visually looked good to me

The result a handful of lookup tables like this:

Which adjust the padding of the various elements to suit.

Generally I’d prefer to avoid this kind of special casing in my designs. It is brittle to future devices and will need to be tweaked for each new Apple Watch that comes out. However, sometimes it is just unavoidable to get the layout to look right and especially on screens this small, every pixel really does count.

Postscript, Another Pixel Perfection

Another little bit of pixel perfection I was chasing today was adjusting the width of the “reverse” button for this control when viewing the metrics view. This just contains a Map glyph and no text. However, it is placed exactly in the same spot as this textual button so I want there to be a smooth transition between them:

The challenge I run into is that this button’s width is highly variable based on the distance you have walked. So needs to grow and shrink accordingly.

To accomplish this I had to build in a bit of logic to size the green, map button based on how the alternate view will look when tapped. Honestly I doubt anyone will ever notice this little touch but I feel better with having it in there.



»

Widgetsmith += 100,000,000
8 March 2023 | 5:41 pm

Widgetsmith has just achieved a remarkable milestone, surpassing 100 million downloads since its launch in September 2020. A number that I can’t really wrap my mind around. A number larger than the population of all but 14 countries (🤯).

I was very conflicted about whether I should share and observe this milestone publicly. I am by nature a very shy, quiet person and not one to seek the spotlight.

Also, in the many years I’ve been working at this career I have very often been someone struggling to find traction and stability for my apps, and while I could be genuinely happy for the success of others, it also still stung painfully when I saw it.

My hope is that my 12+ years of consistent podcasting and blogging can bear witness to my motives here in communicating encouragement, not boasting.

Ultimately I decided to share this milestone for two reasons: Gratitude & Community.

Gratitude

I am immensely grateful that I’ve been fortunate enough to make something that has reached so many, and I believe that gratitude when left unexpressed is ultimately selfish.

It barely seems possible that an app made by a single person could have such a wide audience. This is only possible because of the mobile revolution and the App Store more specifically.

The success of Widgetsmith was made possible by the amazing platform Apple has made and the amazing users it has attracted. While my work is the middle conduit between Apple’s engineering on one side and the end user’s creativity on the other, my work could not exist without either side of that equation.

Thank you to all the people who work at Apple who have built the platform and distribution methods in iOS which enable my work.

They built the tools, which I was then able to use to make something now beloved by so many. ClockKit and WidgetKit specifically are the technologies that inspired and facilitated this app, and my deep thanks go to the folks behind them.

Also, on the App Store and Developer Relations side of things I am very grateful to the people who have supported and guided my work over the years. There is a very special cadre of folks who make up the Developer Evangelism team, who work tirelessly to help developers like me do our best work, and I am extremely grateful for their efforts.

On the user side, I am very grateful for the users who find Widgetsmith useful. There are few feelings as gratifying as seeing something you made enriching the lives of others. In this case, seeing Widgetsmith allow people to express their creativity and personality on their iPhones has been remarkable to observe. Every time I see a Widgetsmith widget out in the ‘real world’ it is an absolute thrill.

Also, I am incredibly thankful for all my users who have shared Widgetsmith with their friends and family. I am not a big company with a gigantic marketing budget, I’m a single developer with no marketing budget. Widgetsmith’s growth is entirely down to word-of-mouth sharing, which I am incredibly thankful for.

Community

I am an Indie App Developer and very proud of that fact. I believe there is something truly special about this community. A group of people who care deeply about craft, quality and improvement.

The Indie Developer community has demonstrated time and time again the tremendous capability of the individual or small team. Showing that it doesn’t take massive teams with giant budgets to create things with enduring value. Indeed, moreover, it regularly demonstrates that the quality of the output is a reflection of the care and consideration that goes into the creation.

As a proud member of this community I wanted to share this milestone because I hope it will inspire and push out the ceiling of what people think is possible for an Indie. While I’m sure I’m not the first Indie developer to reach this wide an audience, I want to place down my marker as an indication of what is possible.

It took me a long time to get here, Widgetsmith was the 59th app I launched over 12 years, and there are no guarantees that anything we make will ever find its audience. However, I do know that if if we don’t get started, we can never find out.

So get started and find out: launch lots of ideas, fail many times, improve your craft, pay attention to the little things, share your learnings, be kind to yourself and those around you, work diligently…because you never know where you’ll end up.



»

Getting Unstuck after a Launch
7 March 2023 | 12:48 pm

I often find the period directly after a launch to be a really complicated time to be motivated to work. The excitement of the release is now behind me. A daunting list of tasks, which were waiting until the launch to become available, is in front of me.

So I often need to find a little project to get me going. Once I’m moving again, I can then turn my attention towards the actual work that needs to be done. Very often this ritual has taken the form of designing of a Watch Face, but today I found something else.

The rest of this article is a cursory walkthrough of the project I made this morning to “clean my palate”, which may or may not be of any interest. However, before you bounce away, the main point I want to make is that finding these little, few hour coding projects is a fantastic tool to kickstart you out of a motivational slump. Give it a try!

My Project

When I was doing my main work for Pedometer++’s mapping features I came across an algorithm for drawing contour lines on an elevation map, the Marching Squares method. While I have no actual need of this in my app itself, the concept behind it was really intriguing. So for my little coding treat to get myself going, I decided to try it out.

To get started, I watched this excellent overview video by Daniel Shiffman. Which walked through the concept in a very approachable manner.

Watch the video to actually learn the method but at a high level the method involves looking for the boundaries between different height thresholds and then using a series of precomputed shapes to then draw the outlines.

Data

For my little experiment I chose to try and draw a map of the Scafell Pike area in the Lake District.

I poked around the internet a bit and found this dataset available for download, which included elevations at a roughly 1-second increments. A little bit of data transformation in a script later I had the data in a format I could read from Swift.

The first thing I did then was to visualize the heights using a super simple ZStack with a collection of Rectangle elements positioned within it. These are colored to reflect their elevations.

After more false starts than I’d like to admit (mostly getting the signs and sample ordering wrong), I had the data rendered on the screen.

The red part in the middle is Scafell Pike, with the surrounding mountains visible as well.

Drawing the Lines

Next I wrote up a very basic version of this algorithm which iterates through the entire array of data points and determines if the points at a given vertex lie above or below a threshold value. For example, I might look for the points which span the elevation of 800m. Once I find these points I then apply the Marching Squares lookup table to determine which shape to draw at this point:

The result of this is a rather coarse visualization of the contours.

The sharp corners in the graph are an artifact of drawing the line segments from the middle of the sides. This means that you don’t smoothly move from one cell to the next. It is always a fixed jump.

To address this you can use linear interpolation to determine where along the cell edge you should draw from. The result is much, much smoother.

I’m quite pleased with that as my result. It matches reasonably closely with an actual topographic map of the area.

This code isn’t something that I expect to use in any of my apps directly. If I want a topographic map I’ll use a mapping service to generate this, where they can take care of all the weird edge cases I’m not covering. But I’m glad to have done this exercise and feel much better as a result. So now, on to the actual work.


If you wanted to give the code a look…it is here. Though I will freely admit it is super rough, slow and inelegant. But it did the job today.



»


More News from this Feed See Full Web Site