In this chapter, you will learn how to lay out your user interface components using Titanium's various positioning properties. You will examine the coordinates system used by Titanium, its view hierarchy, and the layering and positioning rules that it follows when rendering your UI.
In this guide, we're going to explore the following factors that affect how you position elements within your app's UI:
- The coordinates grid
- Positioning and the view hierarchy
- Layout modes
- zIndex & default stacking order
Placement and dimensions of UI elements are specified using a numeric value plus an implicit or explicit unit of measurement. If you don't specify a unit of measurement, the "system" unit is assumed. You can also set a default unit of measurement to use in your app by setting a tiapp.xml property.
First, a couple of definitions we'll use in the rest of this guide:
- dip: Density-independent pixels. A measurement which is translated natively to a corresponding pixel measure using a scale factor based on a platform-specific "default" density, and the device's physical density.
- System unit: A platform-dependent unit which is the default for how the system presents its view information to the native layout system. On Android this is pixels; on iOS it is dip.
Supported units are:
- Absolute measurements
- px: pixels
- mm: millimeters
- cm: centimeters
- in: inches
- dp/dip: Density-independent pixels (we sometimes call these "points")
- Android: actual pixels = dip * (screen density) / 160
- iOS: actual pixels = dip * (screen density) / 163 (effectively 1dip=1px on standard, 1dip=2px on retina)
- Windows: actual pixels = dip * (screen density) / 96
- Relative measurements
- %: Percentage of the size of the parent.
- For x-axis values (width, left, right, center.x) this is relative to the parent's width
- For y-axis values (height, top, bottom, center.y) this is relative to the parent's height.
- %: Percentage of the size of the parent.
You would use these units of measurement like this:
Setting default units in tiapp.xml
You can specify the default unit type to use with untyped values. In the tiapp.xml file, you would add:
value can be set to
system. The "system" value corresponds to the platform-dependent system unit as described above. If you do not specify this property in the tiapp.xml, then the units default to "system".
As of SDK 8.0.0,
dp starts supported for default unit on Windows. Since Windows default unit has been
px in previous versions this means this may cause breaking change. You might want to update your
tiapp.xml to use
px for default unit explicitly like
<property name="ti.ui.defaultunit" type="string">px</property> to keep consistency between previous SDK versions.
The coordinates grid
Titanium uses a grid coordinate system for layout. Grid locations are based on the system unit (platform-dependent unit). This means that by default on iOS, elements are positioned on a density-independent grid and on Android on a density-dependent grid. The net result is that on iOS, elements are positioned in visually the same locations regardless of the actual density of the screen. On Android, elements are positioned at the same absolute pixel locations and might lay out differently depending on the device.
- iPhone with either original or retina display is based on a 320 x 480 dip grid.
- iPad is based on a 1024 x 768 dip grid.
- Android device screen sizes vary. Considering these emulator examples:
- HVGA emulator is 320 x 480 px
- WVGA800 emulator is 480 x 800 px
- WVGA854 emulator is 480 x 854 px
Remember that you can specify
dip units on Android (and even set an app-level default in tiapp.xml) to achieve the same density-independent grid as offered by default on iOS.
Positioning and dimensions of elements
Elements in Titanium are positioned relative to their parent container, such as a window or view. The positional options are:
topproperty which is relative to the parent's top edge.
leftproperty which is relative to the parent's left edge.
bottomproperty which is relative to the parent's bottom edge. (Zero is located at the parent's bottom edge and higher numbers are above the bottom edge.)
rightproperty which is relative to the parent's right edge. (Zero is located at the parent's right edge and higher numbers are to the left of the right edge.)
centerproperty specifying the position of the view's center point relative to the parent's top/left corner.
size property is available, which provides the
height of a view after it has been laid out by the window. This property won't provide the actual size of the view until a postlayout event has been received.)
You specify a view's dimensions by setting the
height properties. If you omit the
height property, but set the
bottom properties, then the view's height will be calculated dynamically relative to the parent's top and bottom edges. The same is true when you omit the
width property, but set
Each of these attributes accept values with or without units, including percentage-based relative measurements as described above.
In the following example, the red view is positioned at the 20,20 point relative to the window's top/left corner. The yellow view's bottom/right corner is 100 points/pixels from the bottom/right corner of the display. The blue view's center is at 160,240 and given its width of 50, this means its top-left corner would be at 135,215. The green view has a sufficiently negative
top value given its width that it is positioned off the top of the screen.
Titanium Windows and Views can employ one of three layout modes by setting its
layout property to one of the following values:
composite- This is the default mode. Views are stacked on top of each other, where the last view added will be on top (unless zIndex is specified). Positional properties are relative to the parent container.
vertical- This layout mode stacks child views vertically and are horizontally centered. The child's
topproperty becomes an offset value. It describes the number of units below the previously added view's bottom edge and can be used as padding.
horizontal- This layout mode lines up child views horizontally from left to right, starting from the parent's top/left corner. If horizontalWrap is set true, will wrap views to the next row if they don't fit on the current row. The child's
leftproperty becomes an offset. It's the position from the previous sibling's right edge and can be used as padding.
Here's an example of these layouts in action:
You can auto-size a UI element by setting its
height properties to one of the following constants:
Ti.UI.SIZEwill set the width or height to just-fit the view's contents
Ti.UI.FILLwill set the width or height to fill the parent. For a composite layout , this will be equal to the parent's width or height and will disregard previously added child views. For horizontal and vertical layouts, this takes into account previously added child views and will fill the remaining width or height available within the parent
UI components exhibit default SIZE or FILL behaviors, as listed in this table:
Toolbar: FILL for width, SIZE for height
TableViewRow: FILL for width, SIZE for height
Slider: FILL for width, SIZE for height
ScrollView content sizes
In the case of ScrollView,
contentHeight may also be set to "auto" or Ti.UI.SIZE, and in those cases, this is the expected behavior:
- When all children views have FILL behavior, the content area of the scroll view will be clipped to the physical size of the scroll view
- Otherwise, the content area will grow according to the bottom offset of the bottom-most View and the right offset of right-most View. In some cases the bottom-most and right-most View may be the same View.
zIndex & default stacking
You can position elements atop one another. By default, as you add views to a parent container, they will overlay any views you previously added (assuming their boundaries overlap). You can control the stacking order by either changing the order you add elements to the container (not always convenient) or by setting the
zIndex property. As with HTML elements,
zIndex accepts an integer value of zero or greater. The higher the
zIndex value, the closer to the top of the stack a view will become.
zIndex is only supported by
composite layouts. This property is ignored by
In this activity, you will test the position behavior of elements by implementing some of the code examples in this chapter.
To perform the steps in this activity, you will need the gridlines module from https://gist.github.com/1187384.
- Create a new Titanium Mobile project.
- Create a gridlines.js file containing the code shown at the Gist linked to above.
- In app.js, remove all of the existing code. Declare a window, require the grid line module, and draw grid lines every 20 points, following the example code as shown in the Gist.
- Implement the positioning code shown in the example labeled "Positioning" above. This will draw red, blue, yellow, and green boxes at various positions on the screen.
- Build and run the project. Count the gridlines to confirm that elements were placed as described in this chapter.
- Adjust the positioning properties of the various boxes to test positioning rules.
- Try setting the window's
horizontalto see the effect on the lines and boxes. Adjust the code so that the boxes are visible.
In this section, you learned how to lay out your user interface components using the various positioning properties. You examined the coordinates system used by Titanium, the view hierarchy, and the layering and positioning rules that Titanium follows when rendering your UI. Next we'll discuss how you can handle user interaction via events.