Now we are going to talk about different ways to set element's size and its position on the screen. But before we start we need to add a table view to use it as an example in this chapter.
Since our app will save user's mood for each period of time, we will need to show it somewhere. It can be a chart, a calendar or a table view that will show user's mood in the past. For now, we will start with a table view.
Let's create a new screen,
MoodHistoryScreen
.
It will have only a fullscreen table view inside. Later it will show
data taken from a real database, but for now, we are going to use
some fake pre-set data. We will also use this screen as our first screen,
instead of a
HomeScreen
. Let's get started with
/app/layouts/mood_history_layout.rb
. This layout will
have only one table view, but it's size and position will be set with
frames:
class MoodHistoryLayout < MotionKit::Layout
def layout
add UITableView, :table
end
def table_style
frame x: 0, y: 0, w: '100%', h: '100%'
end
end
frame
method here sets origin and size of an element.
Here we say that want the table to start from the top left corner,
and that element should be full-screen (width and height
take 100% of its container).
Now let's create the screen in a
/app/screens/mood_history_screen.rb
file that will use MoodHistoryLayout
:
class MoodHistoryScreen < PM::Screen
title "Mood History"
def load_view
@layout = MoodHistoryLayout.new
self.view = @layout.view
end
def on_load
self.view.backgroundColor = 0xffffff.uicolor
end
end
To show this MoodHistoryScreen
we need to update
App Delegate
.
We are going to remove modal screen for now, and will replace
HomeScreen
with
MoodHistoryScreen
:
class AppDelegate < PM::Delegate
def on_load(app, options={})
screen = MoodHistoryScreen.new
open screen
end
end
Let's launch the app now. The result will be an empty full-screen table.
You can try to rotate the Simulator with
CMD + Left
or
CMD + Right
Stop! When Simulator rotated to a landscape mode, something went wrong. The table takes only half of the screen, which is not what user expects. So what is the problem?
This is a good time to talk about frames and constraints. Frames set the origin point and the size of a table. These values do not update automatically. We wrote that we want our table to be as wide as device's screen, and iOS will always keep this width. We can only update it manually, and in this case, we would need to find a delegate method that would be called each time when a device is rotated, and then change the frame of the view.
Layout Constraints (or AutoLayout) are different. You tell your app: "I want the right border of the table to be always equal to the right side of the screen". And iOS will always keep it in mind. Has device rotated? Table's size will be updated. If you wanted some element to be always in the center of some other element, iOS will always keep it there, and will update position automatically, even when you will change the size of a container.
Layout Constraints were introduced only in iOS 6.0, so not all developers started to use it right away. Even at this moment, when iOS 9.1 is available, lots of apps still use frames instead of Constraints.
Layout Constraints are also one of the main reasons why we use motion-kit.
Let's rewrite our layout now, to use constraints:
class MoodHistoryLayout < MotionKit::Layout
def layout
add UITableView, :table
end
def table_style
constraints do
width.equals(:superview)
height.equals(:superview)
end
end
end
Even Layout Constraints code is beautiful! By the way, you could also
use next code:
constraints do
x 0
y 0
right.equals(:superview, :right)
bottom.equals(:superview, :bottom)
end
or this:
constraints do
right.equals(:superview, :right)
left.equals(:superview, :left)
bottom.equals(:superview, :bottom)
top.equals(:superview, :top)
end
If you try to rotate the phone now, you will see that everything
works correctly, and Layout Constraints resize the table automatically:
Now when we have some screens of the app ready, it is a good idea to make a new snapshot and save it with git:
git add .
git commit -m "Table View added"
In this chapter we learned that view frames are static - they do not update its values according to outside changes. To make views resize accordingly, we need to use AutoLayout (or Layout Constraints). They are set of simple rules that view will always follow, even if a device is rotated or superview's size has changed.
You can read more on AutoLayout at Apple Docs.