I started doing iOS development in Xamarin in C# (one look at Objective-C was enough for me). Writing C# for iOS in Xamarin Studio is where I spend most of my days. Occasionally I switch over to Windows to lather in the Visual Studio goodness, however, Xamarin Studio is mostly enjoyable. When it comes to creating UIs in iOS, the standard approach is to fire up Xcode, build your UI in the WYSIWYG editor, wire up your outlets, save your changes, and hope Xamarin Studio picks up your changes. It’s a fairly arduous process, but it works.
My coworkers don’t have access to an instance of Xcode (there’s only one MacBook in my team). This means, they can’t make any UI changes. On top of that, I don’t like building UIs in the Xib interface builder. I find it rather confusing and overkill for my needs. I’m also the type of person who would rather build my UI out in Photoshop, and translate it directly to code. I guess that’s the web developer in me.
With iOS 6 came Auto Layout – the ability to create relationships between UI elements using constraints. Once you add all your elements to the parent element, you define the relationships between each of the objects. The platform will then draw the UI for you, honoring all of your constraints (if you specified them correctly).
Let’s say, I want to build the following view. Here’s what the code looks like (come back when you’re finished throwing up):
That just sucks.
XibFree is a really nice solution. It does what it says – let’s you build UIs without a XIB. It was the first solution I played around with. I’m not going to go into too many details about it (ironically, the documentation is what I find most lacking). It’s a lot less wordy and mostly uses the Android XML language. If you’re doing cross platform development AND you’re coming from Android, the learning curve is not as steep.
I guess my biggest issue with XibFree was animating, showing, hiding, etc. For the most part, it worked fine. As my interface got more and more complicated, it became difficult to debug some of these issues.
My favorite solution
If you aren’t familiar with @slodge or MvvmCross, get ready to have a good time.
In a mere couple hours, Stuart Lodge changed me life. To see how, read hist post (http://slodge.blogspot.com/2013/07/playing-with-constraints.html). In short, he’s build a library which allows you to use a declarative way to define your views using the native NSLayoutConstraints. Score!
It’s so easy to use, let’s make the example a little bit more complicated.
And another example.
I know you’re excited. Now go download the library and develop away. It’s available on GitHub – https://github.com/MvvmCross/MvvmCross.
What can you do
Like XibFree, the documentation is a little lacking. However, you have the source. So, let’s see what we can do with this library.
- child.AtTopOf(parent[, margin]) – attaches the top of the child’s frame to the top of parent’s frame
- child.AtLeftOf(parent[, margin]) – attaches the left side of the child’s frame to the left side of the parent’s frame
- child.AtRightOf(parent[, margin]) – attaches the right side of the child’s frame to the right side of the parent’s frame
- child.AtBottomOf(parent[, margin]) – attaches the bottom of child’s frame to the bottom of the parent’s frame
- view1.WithSameLeft(view2) – attaches the left value of view1 (view1.Frame.X) to the left X value of view2
- view1.WithSameRight(view2) – attaches the position of the right side of view1 (view1.Frame.Right) to the same right value as view2
- view1.WithSameTop(view2) – attaches the top Y value of view1’s frame (view1.Frame.Y) to the top Y value of view2
- view1.WithSameBottom(view2) – attaches the bottom of view1’s frame (view1.Frame.Bottom) to the bottom as view2
- view1.WithSameCenterX(view2) – attaches the horizontal center of view1 to the horizontal center of view2
- view1.WithSameCenterY(view2) – attaches the vertical center of view1 to the vertical center of view2
- view1.WithSameWidth(view2) – attaches the width of view1 to the width of view2
- view1.WithRelativeWidth(view2[, scale]) – attaches the width of view1 to the width of view2, with an optional scale factor
- view1.WithSameHeight(view2) – attaches the height of view1 to the height of view2
- view1.WithRelativeHeight(view2[, scale]) – attaches the height of view1 to the height of view2, with an optional scale factor
- view1.Below(view2[, margin]) – attaches the top value of view1 to the bottom value of view frame
- view1.Above(view2[, margin]) – attaches the bottom value view1 to the top value of view2
- view1.ToRightOf(view2[, margin]) – attaches the left value of view1 to the right value of view2
- view1.ToLeftOf(view2[, margin]) – attaches the right value of view1 to the left value of view2
- view1.FullWidthOf(view2[, margin]) – attaches the left and right values of view1 to view2
- view1.FullHeightOf(view2[, margin]) – attaches the top and bottom of view1 to view2