Environment

Titanium SDK

Contents

UI Composite Layout Behavior Spec

Contents

Overview

Titanium's UI behavior has remained unspecified and fragmented across platforms, which makes cross-platform development difficult for users and designing tests to evaluate UI impractical. With proposed changes to the layout system, and more advanced testing frameworks, it has become necessary to explicitly define UI behavior in as many situations as possible.

This document is a codification of UI behavior (the "Composite" layout) for both Android and iOS platforms, including explicit specifications for unit types, order in which layout properties are valuated, "auto" behavior, and dealing with unset values.

The behavior for "Horizontal" and "Vertical" layouts will be specified in another document.

Backwards Compatibility and Deprecation

In Titanium Mobile 2.0, the value of any layout parameter on a View will always maintain that value, making it "static". The properties size, and rect, will now serve as the "dynamic" APIs that provide position and size. We will also maintain backwards compatibility with the current "immediate mode" layout scheme, but this behavior will be marked as DEPRECATED. Moving forward, we will drop support for this method in favor of the the startLayout / finishLayout, and updateLayout semantics.

Definitions

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.

Layout parameters

This is the list of Layout Parameters used by "Composite", "Horizontal", and "Vertical" layouts. Layout Parameters are discussed in more detail in the Layout specification, but these all correspond to existing layout settings.

width : The width of the view

left : Pins left side of the view to this x position in the parent, measured from the parent's left bound.

right : Pins right side of the view to this x position in the parent, measured from the parent's right bound.

height : The height of the view

top : Pins top side of the view to this y position in the parent, measured from the parent's top bound.

bottom : Pins bottom side of the view to this y position in the parent, measured from the parent's bottom bound.

center : (x, y) : Pins the view's center to the specified point:

center.x : The x-coordinate, measured from the parent's left bound

center.y : The y-coordinate, measured from the parent's top bound

layout : The layout type to use. The default value is for the "Composite" layout. Other valid values are "vertical" and "horizontal". This property is intended to be replaced by the new UI Layout API Spec

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.

Precedence of layoutParams

Certain parameters influence the calculation of others when they are unset (see UNDEFINED behavior ). The purpose of establishing an order of precedence is only to determine when certain settings override others when there is an obvious conflict, or determine which properties are used for computing implicit values.

In order of precedence, from 'evaluated first' to 'evaluated last':

width : overrides implicit width calculations

left : overrides horizontal positioning determined by center.x, right

center.x : overrides horizontal positioning determined by other pins

right

height : overrides implicit height calculations

top : overrides vertical positioning determined by other pins

center.y : overrides vertical positioning determined by other pins

bottom

When a conflict occurs between the different layout params, the order of precedence will determine which params will be ignored. If a view has a width of 200, a left value of 100, and a right value of 10, then the view would be 200 wide, and 100 from the left of its parent view. The right value is ignored since it conflicts the width and left values, and has lower precedence.

Auto size behaviors

"auto" (sometimes refered to as "psychic") is a measurement specification for width/height which "sizes the view appropriately given the type of view and its contents." This is a vague descriptor, and has been broken up into two general specified behaviors: SIZE and FILL.

"auto" will be deprecated in 2.0.0, to be replaced with Ti.UI.SIZE and Ti.UI.FILL constants which represent explicit "auto" behavior. As a result, this section codifies existing "auto" behavior into these two subtypes, and declares which views use which type when their width or height is set to "auto" under the present system.

ScrollView content size

In the case of ScrollView, contentWidth and contentHeight may also be set to "auto", 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.

SIZE behavior

This behavior represents constraining a view size to fit its contents.

height only : Constrained by view's width, or if width is incalcuable (<2 horizontal pinning properties) and unset, then constrained by parent's width.

width only : Constrained by view's height, or if height is incalculable (<2 vertical pinning properties) and unset, then constrained by parent's height.

ScrollView SIZE

Scrollview contentWidth or contentHeight can be set to Ti.UI.SIZE. This value behaves as SIZE is described above, where the scrollview itself first sizes to contents, and then if those contents extend beyond the bounds of the scrollview, the content view sizes to fit the contents appropriately.

FILL behavior

This behavior represents growing a view size to fill its parent.

height only : Fills all available vertical space inside the parent

width only : Fills all available horizontal space inside the parent

height + width : Fills all available space inside the parent\

NOTE: The fill behavior does not take any other views into account except for its parent. i.e. If the parent view has 2 children, the first with a static width/height and the second with fill behavior for both, the second view will still fill its parent.

If the parent does not have a height/width constraint (i.e. The parent has size behavior for width/height while the child has fill behavior), then the view will recursively go through the parents to find a width/height constraint and fill to that constraint.

ScrollView FILL

Scrollview contentWidth or contentHeight can be set to Ti.UI.FILL. Regardless of contents, this behaves as described above, meaning that the content view bounds fill the scrollview. This has the side-effect that the scrollview does not scroll, so using this value is considered undesirable.

View auto size classification

Views are logically grouped into either SIZE or FILL for their auto behavior. Windows FILL the screen by default.

SIZE Views

Button

Label

ImageView

ProgressBar

Switch

TextArea

TextField

Picker

SearchBar

height only, FILL width

ButtonBar

TableViewSection

FILL Views

View

TabGroup

VideoView

Toolbar

width only, SIZE height

TableView

TableViewRow

width only, SIZE height

WebView

ScrollView

ScrollableView

Slider

width only, SIZE height

UNDEFINED behavior

If layout parameter values are undefined, then this means that they need to be computed based on existing values if possible, and if not, then have some sensible default.

Icon

The layout parameters themselves will not actually change value, the dynamic APIsrectandsizewill contain the actual system values.

width : implicit based on horizontal pins (left, center.x, right)

If two (or more) horizontal pins are available, computed from these values

Otherwise, follows view's "auto" behavior

On "auto" deprecation, follows SIZE behavior

If width is dependent on the parent (e.g. percentage), and the parent is set to SIZE, width is undefined

left : implicit based on other horizontal pins (center.x, right)

If no pinning properties are set : The view is centered horizontally in it's parent

Otherwise, no left side pinning

center.x : No center pinning (horizontal)

right : No right side pinning

height : implicit based on vertical pins (top, center.y, bottom)

If two (or more) vertical pins are available, computed from these values

Otherwise, follows view's "auto" behavior

On "auto" deprecation, follows SIZE behavior

If height is dependent on the parent (e.g. percentage), and the parent is set to SIZE, height is undefined

top : implicit based on other vertical pins (center.y, bottom)

If no pinning properties are set : The view is centered vertically in it's parent

Otherwise, no top side pinning

center.y : No center pinning (vertical)

bottom : No bottom side pinning

zIndex: implementation treats as 0, but will still be undefined in the View's layout params. Views are stacked in order of being added to the parent based on their index.

UNDEFINED and scrollview contents

For clarity, scrollview contentWidth and contentHeight behave as if they were set to "auto" when undefined. This is consistent with the behavior described above.

Code Examples

Each of these examples contrast the way something is done today ("old") with the way it will be done with the new dynamic size / rect properties, and batch updating semantics ("new").

convertToUnits : The unit to convert to from one of the UNIT_* constants above

NOTE we will need to accomodate for multiple displays in future revisions of this API

NOTE because parent/self information is required for converting % values, there is no unit constant for '%' or conversions allowed to/from this value. If a percent value is passed in, this method returns 0.

Events

'postlayout' : This event will be fired after a layout pass has occurred.