Teacup is a library for RubyMotion that let's you create views and layouts in simple declarative code. The simplest way to understand it is that it's "CSS for iOS", but that would be to heavily underestimate what it can do. Perhaps a better analogy is "Interface Builder for RubyMotion", as both tools solve the same problem.
Once you've added teacup to your app, you can get started immediately by creating views in your controller:
class MyViewController < UIViewController attr_accessor :button layout do subview UILabel, text: "Hello World" self.button = subview( UIButton.buttonWithType(UIButtonTypeCustom), title: "Click me!" ) end end
MyViewController is shown, it will contain both a label and a button.
You'll also notice that I've stashed the button away on
self.button so that I can refer
to it later in the controller. I won't need to use the label in my code, so I can just
rely on the view heirarchy to retain it as necessary.
Making them pretty
Unfortunately the code in the previous section had a bit of a flaw; when you run it the label and the button don't actually appear. This is because Cocoa defaults all elements to zero width and zero height, and is really easy to fix:
class MyViewController < UIViewController attr_accessor :button layout do subview(UILabel, text: "Hello World", top: 60, left: 60, width: 200, height: 100, backgroundColor: UIColor.blueColor ) self.button = subview( UIButton.buttonWithType(UIButtonTypeCustom), title: "Click me!", top: 200, left: 60, width: 200, height: 100 ) end end
Again this hopefully stating the obvious, but I should now have a blue label a short distance from the top of the screen and a button just underneath that. Both of them are 60px from the left and 200px wide so that they appear centered.
While the code in the previous section works just fine, it's somewhat ugly on two fronts. The most obvious issue is that if I want to change the left margin I have to do that in multiple places, but also my controller is being filled with irrelevant details. It really doesn't matter what size the button has, from a controller's point of view, that's a view-level concern.
To solve these problems teacup provides you with stylesheets:
# app/controllers/my_view_controller.rb class MyViewController < UIViewController attr_accessor :button stylesheet :iphone layout do subview(UILabel, :hello_world) self.button = subview(UIButton, :click_me) end end
# style/iphone.rb Teacup::Stylesheet.new :iphone do style :widget, left: 60, width: 200, height: 100 style :hello_world, extends: :widget, text: "Hello World", top: 60, backgroundColor: UIColor.blueColor style :click_me, extends: :widget, title: "Click me!", top: 200 end
This new code solves both of the code structure problems; the nitty-gritty of making the
view look right is no-longer polluting the controller, and the left-margin is only
specified in one place due to use of the
To get the example code created in this blog post you can clone the git repository. Other example uses of teacup can be found in the sample app that's included with teacup itself, and the Commune app which is where some of the initial experiments were done.