Professional Layouts in OS X and iOS – Open Source View Position Utility

Introducing JFViewPositionUtil

I created JFViewPositionUtil for KEYBOX 2.0. I hand code my interfaces rather than use Interface Builder, and version 1.0 proved extremely difficult to lay out professionally while also balancing the consideration of localization.

Why would anybody in their right mind NOT use Interface Builder? Don’t get me wrong, it’s a fine tool but for the degree of customization I and many developers require it doesn’t quite cut it.

In the case of KEYBOX 1.0, a layout that would look good in English might make Japanese look awful. My initial approach to handle this was to adjust the font size on a per-language basis. It worked but was nowhere near optimal.

In version 2.0 I resolved to fix this and since its release I’ve used this class in all my products. It’s matured to the point where I believe it to be beneficial to others as well, and to this end I’ve decided to open source it.


Class Design

I designed this class to be goal oriented. That is, whatever your goal, you typically only need to invoke a single method offered by this class. It’s even a singleton so there is no need to instantiate it.

This utility class works with both OS X and iOS projects but it should be noted that it is designed to work in coordinate systems where the point of origin (0, 0) is the top left corner. In other words, you’ll want to flip your views in OS X projects when using this class.

Lazy-initialization of views

A quick note, since this utility class operates mainly on the notion of positioning views relative to others, it is beneficial to adopt a lazy-initialization approach to view creation. This way sibling views upon which your view depends will be initialized and positioned by the time you need to base your view’s position on them. All of the below examples in this post will use lazy-initialization of UIViews for iOS.


Common Layouts

The best way to demonstrate this class’ abilities is to simply show you. Since this class is goal oriented I’ll break things down by common layout goals.

■ Label to the right of an icon
This is a common layout pattern, and the code might look something like this…

Label right of icon

One variation of this is the case of a multiline label. You probably wouldn’t want to vertically center your label to the right of your icon. Instead, it might look more professional to snap the icon’s top right anchor point 5 points left of the label’s top left point. I’ll discuss this technique a bit later.

■ Center aligned titles/headers

Sounds simple enough right? The title is a label with a bold font. Here’s the code…
Centered Header

It’s generally a good idea to first call sizeToFit on labels prior to aligning them with JFViewPositionUtil, especially when you intend to center align them.

■ Text field under a label

Have a text field that should appear left aligned, say, 10 points under a label explaining its purpose? Here is how to accomplish this…

Left Aligned Textfield

And to right align it instead…
Right Aligned Textfield

This just touches upon some of the high-level functionality of this class.  Other useful methods exist, each aptly named for its purpose.

Going Beyond

If JFViewPositionUtil’s high levels actions don’t suffice its low-level anchoring system will. The code is based on anchoring points (shown below) at the cardinal points on a rectangle as well as a center point and allow for snapping of any anchor point of one view to any point of another while also allowing for offsets from this snap point for pixel-perfect precision.

Anchor Names

Earlier I mentioned aligning a multilined label’s top left corner 5 points to the right of an icon’s top right corner. Here is how to accomplish this…

Multilined Label

Notice that I’m aligning the label to the icon. You could just as easily do the reverse.


Going Even Further

JFViewPositionUtil’s high and low-level methods ought to satisfy all your view positioning needs, but if your app has some specialized effect that isn’t handled you might also find the pointForAnchorPoint:ofView: method useful. It retrieves the location (relative to the parent view) of any of the subview’s anchor points. Armed with this information you can create your own frames to position views just the way you want.

Grouped Layout Strategy

With this introduction to the class’ capabilities out of the way it’s now time to talk layout strategies.

While there is nothing wrong with laying out each control in relation to a sibling control it often makes sense to group controls within an otherwise invisible NSView/UIView and adjust the size of that parent view perfectly for the subviews it contains.

Why would you want to do this? This approach allows for a group view to be dynamically slid in between two others and to have them adjust their positions to accommodate it. Having to re-adjust dozens of controls in tandem is a lot harder than re-adjusting a single group view acting as the parent view for these controls.

JFViewPositionUtil offers the setHeightOfSuperview:toFitAllSubviewsWithMargin: method to help you in this regard. Think of this method as being like the UIView sizeToFit method except that it allows for an adjustable margin on the bottom of the lowest subview.

This method is also quite useful for adjusting the vertical height of UIScrollViews, even if you don’t plan to dynamically insert or remove group views within them. The logic has a special handler for UIScrollViews to set their content size in addition to their regular view size.

One last thing to note: The lazy-initialization approach I advocated earlier comes into play again here. Keep in mind that the group view needs to ensure that all its subviews are initialized and positioned prior to adjusting its own size to fit them. By going with lazy-initialization the group view doesn’t need to worry about the possibility of re-initializing its subviews.

Localization Concerns

As I mentioned earlier it was when I was localizing KEYBOX that I encountered difficulty with laying out my views. Japanese is a very compact language whereas French and Spanish are comparatively stretched out. English is somewhere in the middle.

The approach I took in version 2.0 was to use fixed size font, multilined labels to handle any text length and have any sibling controls appearing under them dynamically adjust their y positions to always be N points away. As long as the parent view had enough vertical room or was UIScrollView-based it worked like magic.


Animated Views

In case you were wondering, this class is also compatible with the animation systems of both OS X and iOS. Simply use JFViewPositionUtil to set the new position within an animation context and watch iOS do the rest for you.  For OS X you can use a view’s animator for the same effect or directly reset the view position at each progress step of an NSAnimation if need be.

Lastly, if you are developing an OS X project and use auto-resizing views (setAutoResizingMask:) you’ll be happy to know that they are completely supported as usual in much the same manner as animated views are.


In Closing

JFViewPositionUtil is the result of my own frustrations with dynamic, hand-coded views.  If you are equally frustrated with the difficulties of having to code your UI by hand but simply cannot rely on Interface Builder to meet your exacting needs JFViewPositionUtil might be the sweet spot for you. I invite you to give it a try and find out for yourself!

If you have any questions or comments please contact me at jay [AT] this domain.

Open Source Code for Developing Sudoku for iPhone and OS X

My Love For Sudoku

I’m a Sudoku addict. My love for Sudoku has most certainly surpassed unhealthy levels.  Naturally, being a developer I at one point had an interest in developing my own Sudoku game just to see what it entails.

The concept of Sudoku is a very ancient one but the game’s recent popularity is attributed to the company NIKOLI which owns the copyright to the word “Sudoku” and the Japanese “数独” (lit: “number alone”) within Japan.

Game concepts, in and of themselves, cannot be copyrighted and to get around any copyright disputes I considered calling my game “9 Lives” and varying the gameplay enough by employing a strict rule of allowing up to 9 mistakes before the player loses. Essentially I was interested in making a Sudoku game for pros (no hints or anything).

However, I later learned through the Quinn/Tetris debacle that even though game concepts cannot be copyrighted, the owners of such games still show their legal fangs if you encroach on their territory and considering that my presence here in Japan is also where NIKOLI is based I reconsidered developing my own game.

That was 5 years ago, when I was just beginning to learn Objective C and OS X development. While cleaning some things up on my Mac I recently rediscovered my old Sudoku board generator code and it feels like a waste to just let it sit there unused.  Instead I decided to rewrite it (the original code is too embarassing to release) and donate it to others interested in making their own Sudoku games.

Most of the Sudoku games I have played only offer pregenerated boards. My code creates random ones each and every time. As such it depends on a random number generator, in this case my JFRandom utility class which is available on github.

If you are outside Japan and interested in making your own sudoku game check out my Sudoku Board Generator.

 

How To Use It

This one line is all you need to generate a random Sudoku board…

SudokuBoard *board = [SudokuBoardGenerator generate];

Outputting the resulting Sudoku board with NSLog will show the board in full like below…

7 1 8 5 4 3 6 2 9 

6 9 3 2 1 8 5 7 4 

5 4 2 9 7 6 3 1 8 

4 3 5 7 9 1 8 6 2 

1 6 7 8 3 2 4 9 5 

2 8 9 4 6 5 7 3 1 

8 5 1 6 2 7 9 4 3 

9 2 6 3 5 4 1 8 7 

3 7 4 1 8 9 2 5 6 


The board exposes 9 sectors (3×3 grid) and the numbers contained within for you to display in your game.  That’s all there is to it.  The details are all abstracted away from you.  If you have any questions please don’t hesitate to contact me at jay [AT] this domain.