Add SpaceEvenly to flex justification
[platform/core/uifw/dali-toolkit.git] / docs / content / programming-guide / flex-container.md
1 <!--
2 /**-->
3
4 # Flex Container  {#flex-container}
5
6 Flexbox is a CSS3 web layout model which allows responsive elements within a container, automatically arranged to different size screens or devices.
7  
8 FlexContainer implements a subset of the Flexbox spec (defined by W3C) at: https://www.w3.org/TR/css-flexbox-1/
9  
10 The flex container has the ability to alter the width and/or height of its children (i.e. flex items) to best fill the available space on any display device.
11 The container expands items to fill available free space, or shrinks them to prevent overflow.
12  
13 Below is an illustration of the various directions and terms as applied to a flex container with the "flex direction" defined as "row".
14  
15 ![ ](flex-container/flex-container.jpg)
16  
17 DALi supports the following subset of Flexbox properties.
18  
19 ## Properties supported by flex container:
20
21  + [contentDirection](@ref content-direction)
22  + [flexDirection](@ref flex-direction)
23  + [flexWrap](@ref flex-wrap)
24  + [justifyContent](@ref justify-content)
25  + [alignItems](@ref align-items)
26  + [alignContent](@ref align-content)
27  
28 ___________________________________________________________________________________________________
29
30 ## contentDirection {#content-direction}
31  
32 contentDirection specifies the primary direction in which content is ordered on a line.
33  
34 | LTR (left-to-right) | RTL (right-to-left) |
35 |--------|--------|
36 | ![ ](flex-container/content-direction-ltr.jpg) | ![ ](flex-container/content-direction-rtl.jpg) |
37  
38 The possible values for this property are:
39  
40 | Property Value | Description                                 |
41 |----------------|---------------------------------------------|
42 | INHERIT        | Inherits the same direction from the parent |
43 | LTR            | From left to right                          |
44 | RTL            | From right to left                          |
45  
46 ### Usage
47
48 ~~~{.cpp}
49 // C++
50 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
51 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::CONTENT_DIRECTION, Dali::Toolkit::FlexContainer::RTL );
52 ~~~
53
54 ___________________________________________________________________________________________________
55
56 ## flexDirection {#flex-direction}
57  
58 flexDirection specifies the direction of the main axis which determines the direction that flex items are laid out.
59  
60 ![ ](flex-container/flex-direction.jpg)
61  
62 The possible values for this property are:
63  
64 | Property Value | Description                                 |
65 |----------------|---------------------------------------------|
66 | COLUMN         | The flex items are laid out vertically as a column                          |
67 | COLUMN_REVERSE | The flex items are laid out vertically as a column, but in reverse order    |
68 | ROW            | The flex items are laid out horizontally as a row                       |
69 | ROW_REVERSE    | The flex items are laid out horizontally as a row, but in reverse order |
70  
71 ### Usage
72
73 ~~~{.cpp}
74 // C++
75 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
76 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::ROW_REVERSE );
77 ~~~
78
79 ___________________________________________________________________________________________________
80
81 ## flexWrap {#flex-wrap}
82  
83 flexWrap specifies whether the flex items should wrap or not if there is no enough room for them on one flex line.
84  
85 ![ ](flex-container/flex-wrap.jpg)
86  
87 The possible values for this property are:
88  
89 | Property Value | Description                                 |
90 |----------------|---------------------------------------------|
91 | NO_WRAP        | Flex items laid out in single line (shrunk to fit the flex container along the main axis) |
92 | WRAP           | Flex items laid out in multiple lines if needed                                           |
93  
94 ### Usage
95
96 ~~~{.cpp}
97 // C++
98 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
99 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_WRAP, Dali::Toolkit::FlexContainer::NO_WRAP );
100 ~~~
101
102 ___________________________________________________________________________________________________
103
104 ## justifyContent {#justify-content}
105  
106 justifyContent specifies the alignment of flex items when they do not use all available space on the main axis.
107  
108 ![ ](flex-container/justify-content.jpg)
109  
110 The possible values for this property are:
111  
112 | Property Value | Description                                 |
113 |----------------|---------------------------------------------|
114 | JUSTIFY_FLEX_START      | Items are positioned at the beginning of the container                     |
115 | JUSTIFY_CENTER          | Items are positioned at the center of the container                        |
116 | JUSTIFY_FLEX_END        | Items are positioned at the end of the container                           |
117 | JUSTIFY_SPACE_BETWEEN   | Items are positioned with equal space between the lines                    |
118 | JUSTIFY_SPACE_AROUND    | Items are positioned with equal space before, and after the lines          |
119 | JUSTIFY_SPACE_EVENLY    | Items are positioned with equal space before, between, and after the lines |
120  
121 ### Usage
122
123 ~~~{.cpp}
124 // C++
125 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
126 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::JUSTIFY_CONTENT, Dali::Toolkit::FlexContainer::JUSTIFY_SPACE_BETWEEN );
127 ~~~
128
129 ___________________________________________________________________________________________________
130
131 ## alignItems {#align-items}
132  
133 alignItems specifies the alignment of flex items when they do not use all available space on the cross axis.
134  
135 ![ ](flex-container/align-items.jpg)
136  
137 The possible values for this property are:
138  
139 | Property Value | Description                                 |
140 |----------------|---------------------------------------------|
141 | ALIGN_FLEX_START | Items are aligned at the beginning of the container |
142 | ALIGN_CENTER     | Items are aligned at the center of the container    |
143 | ALIGN_FLEX_END   | Items are aligned at the end of the container       |
144 | ALIGN_STRETCH    | Items are stretched to fit the container            |
145  
146 ### Usage
147
148 ~~~{.cpp}
149 // C++
150 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
151 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_ITEMS, Dali::Toolkit::FlexContainer::ALIGN_FLEX_START );
152 ~~~
153
154 ___________________________________________________________________________________________________
155
156 ## alignContent {#align-content}
157  
158 alignContent specifies the alignment of flex lines when they do not use all available space on the cross axis, so only works when there are multiple lines.
159  
160 ![ ](flex-container/align-content.jpg)
161  
162 The possible values for this property are:
163  
164 | Property Value | Description                                 |
165 |----------------|---------------------------------------------|
166 | ALIGN_FLEX_START | Items are aligned at the beginning of the container |
167 | ALIGN_CENTER     | Items are aligned at the center of the container    |
168 | ALIGN_FLEX_END   | Items are aligned at the end of the container       |
169  
170 ### Usage
171
172 ~~~{.cpp}
173 // C++
174 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
175 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_CONTENT, Dali::Toolkit::FlexContainer::ALIGN_FLEX_END );
176 ~~~
177
178 ___________________________________________________________________________________________________
179
180 ## Custom properties supported by flex item:
181
182  + [flex](@ref flex)
183  + [alignSelf](@ref align-self)
184  + [flexMargin](@ref flex-margin)
185  
186 These non-animatable properties are registered dynamically to each child which would be added to the flex container, and once added their values can not be changed.
187  
188 When an actor is added to the flex container, these properties are checked to decide how to lay out the actor inside the flex container.
189  
190 ___________________________________________________________________________________________________
191
192 ## flex {#flex}
193  
194 By default, the items in the flex container are not flexible. If set, this property makes the item flexible, which means the item can alter its width/height in order to receive the specified proportion of the free space in the flex container.
195 If all items in the flex container use this pattern, their sizes will be proportional to the specified flex factor.
196 Flex items will not shrink below their minimum size (if set using Dali::Actor::SetMinimumSize).
197  
198 ![ ](flex-container/flex.jpg)
199  
200
201 ### Usage
202
203 Below is the example code for the items to achieve the proportion of free space as illustrated above.
204  
205 ~~~{.cpp}
206 // C++
207
208 // Create the flex container
209 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
210
211 // Set the flex direction to lay out the items horizontally
212 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::ROW );
213
214 // Create flex items and set the proportion
215 Dali::Toolkit::Control item1 = Dali::Toolkit::Control::New();
216 item1.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 1.0f );
217 flexContainer.Add( item1 );
218
219 Dali::Toolkit::Control item2 = Dali::Toolkit::Control::New();
220 item2.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 3.0f );
221 flexContainer.Add( item2 );
222
223 Dali::Toolkit::Control item3 = Dali::Toolkit::Control::New();
224 item3.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 1.0f );
225 flexContainer.Add( item3 );
226
227 Dali::Toolkit::Control item4 = Dali::Toolkit::Control::New();
228 item4.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 2.0f );
229 flexContainer.Add( item4 );
230
231 Dali::Toolkit::Control item5 = Dali::Toolkit::Control::New();
232 item5.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 1.0f );
233 flexContainer.Add( item5 );
234
235 ~~~
236
237 ___________________________________________________________________________________________________
238
239 ## alignSelf {#align-self}
240  
241 alignSelf specifies how the item will align along the cross axis, if set, this overrides the default alignment for all items defined by the container’s [alignItems](@ref align-items) property.
242  
243 ![ ](flex-container/align-self.jpg)
244  
245 The possible values for this property are:
246  
247 | Property Value | Description                                 |
248 |----------------|---------------------------------------------|
249 | ALIGN_AUTO       | Items inherit the same alignment from the parent by default (as specified by the container’s [alignItems](@ref align-items) property) |
250 | ALIGN_FLEX_START | Items are aligned at the beginning of the container |
251 | ALIGN_CENTER     | Items are aligned at the center of the container    |
252 | ALIGN_FLEX_END   | Items are aligned at the end of the container       |
253 | ALIGN_STRETCH    | Items are stretched to fit the container            |
254  
255 ### Usage
256
257 Below is the example code for the items to achieve the alignment on the cross axis as illustrated above.
258  
259 ~~~{.cpp}
260 // C++
261
262 // Create the flex container
263 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
264
265 // Set the flex direction to lay out the items horizontally
266 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::ROW );
267
268 // Set the items to be aligned at the beginning of the container on the cross axis by default
269 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_ITEMS, Dali::Toolkit::FlexContainer::ALIGN_FLEX_START );
270
271 // Create flex items and add them to the flex container
272 Dali::Toolkit::Control item1 = Dali::Toolkit::Control::New();
273 item1.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::ALIGN_SELF, Dali::Toolkit::FlexContainer::ALIGN_CENTER ); // Align item1 at the center of the container
274 flexContainer.Add( item1 );
275
276 Dali::Toolkit::Control item2 = Dali::Toolkit::Control::New();
277 flexContainer.Add( item2 ); // item2 is aligned at the beginning of the container
278
279 Dali::Toolkit::Control item3 = Dali::Toolkit::Control::New();
280 item3.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::ALIGN_SELF, Dali::Toolkit::FlexContainer::ALIGN_FLEX_END ); // Align item3 at the bottom of the container
281 flexContainer.Add( item3 );
282
283 Dali::Toolkit::Control item4 = Dali::Toolkit::Control::New();
284 flexContainer.Add( item4 ); // item4 is aligned at the beginning of the container
285
286 ~~~
287
288 ___________________________________________________________________________________________________
289
290 ## flexMargin {#flex-margin}
291  
292 Each flex item inside the flex container is treated as a box (in CSS term) which is made up of:
293
294  + content: The content of the item.
295  + padding: The space around the content (inside the border) of the item.
296  + border: The border that goes around the padding and the content of the item.
297  + flexMargin: The space outside the border.
298  
299 ![ ](flex-container/flex-margin.jpg)
300  
301 In DALi, the size of the flex item = content size + padding + border.
302  
303 flexMargin specifies the space around the flex item.
304  
305 ### Usage
306
307 ~~~{.cpp}
308 // C++
309
310 // Create the flex container
311 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
312
313 // Create flex item
314 Dali::Toolkit::Control item = Dali::Toolkit::Control::New();
315
316 // Add the margin around the item
317 item.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN, Vector4(10.0f, 10.0f, 10.0f, 10.0f) );
318
319 // Add the item to the container
320 flexContainer.Add( item );
321 ~~~
322
323 ___________________________________________________________________________________________________
324
325 ## Example of creating Flexbox layout using FlexContainer
326
327 Now let's see how to create a Gallery like layout (as shown below) using FlexContainer.
328
329 ![ ](flex-container/flexbox-demo.jpg)
330  
331 Firstly, we create a flex container as the whole view and set its resize policy to fill its parent (i.e. the stage).
332
333 ~~~{.cpp}
334 // C++
335
336 // Create the main flex container
337 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
338 flexContainer.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
339 flexContainer.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
340 flexContainer.SetResizePolicy( Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS );
341 flexContainer.SetBackgroundColor( Dali::Color::WHITE ); // set the background color to be white
342
343 // Add it to the stage
344 Dali::Stage::GetCurrent().Add( flexContainer );
345 ~~~
346
347  
348 We want to set the flex direction of this main container to column, as we want the toolbar and the actual content to be displayed vertically.
349  
350 ~~~{.cpp}
351 // C++
352
353 // Display toolbar and content vertically
354 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::COLUMN );
355 ~~~
356
357 Now we create a flex container as the toolbar and add it to the main container. Because the flex direction in the main container is column, the toolbar will be arranged on the top of the main container.
358  
359 ~~~{.cpp}
360 // C++
361
362 // Create the toolbar
363 Dali::Toolkit::FlexContainer toolBar = Dali::Toolkit::FlexContainer::New();
364 toolBar.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
365 toolBar.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
366 toolBar.SetBackgroundColor( Dali::Color::CYAN ); // Set the background color for the toolbar
367
368 // Add it to the main container
369 flexContainer.Add( toolBar );
370 ~~~
371
372 We want the buttons and title to be displayed horizontally and vertically aligned to the center of the toolbar, so we set its flex direction to row and set its alignItems property to center.
373 We also want the toolbar and the actual content to share the height of the main container, so that the toolbar will occupy 10 percent of the whole vertical space and the content will occupy the rest of the vertical space.
374 This can be achieved by setting the flex property.
375  
376 ~~~{.cpp}
377 // C++
378
379 toolBar.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::ROW ); // display toolbar items horizontally
380 toolBar.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_ITEMS, Dali::Toolkit::FlexContainer::ALIGN_CENTER ); // align toolbar items vertically center
381 toolBar.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 0.1f ); // 10 percent of available space in the cross axis
382 ~~~
383
384 Then we create another flex container as the content area to display the image, and it will be displayed in the bottom of the main container.
385 We want the item inside it to be horizontally and vertically centered, so that the image will always be in the center of the content area.
386
387 ~~~{.cpp}
388 // C++
389
390 // Create the content area
391 Dali::Toolkit::FlexContainer content = Dali::Toolkit::FlexContainer::New();
392 content.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
393 content.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
394 content.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::ROW ); // display items horizontally
395 content.SetProperty( Dali::Toolkit::FlexContainer::Property::JUSTIFY_CONTENT, Dali::Toolkit::FlexContainer::JUSTIFY_CENTER ); // align items horizontally center
396 content.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_ITEMS, Dali::Toolkit::FlexContainer::ALIGN_CENTER ); // align items vertically center
397 content.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 0.9f ); // 90 percent of available space in the cross axis
398
399 // Add it to the main container
400 flexContainer.Add( content );
401 ~~~
402
403 Now we start to add items to the toolbar. The toolbar will have one button on the left, one button on the right, and a title always in the center (regardless of the screen size).
404 To achieve that, we can simply make the title flexible so that it will automatically take all the available horizontal space left.
405 We will also add some space around the items so that the layout looks nicer.
406  
407 ~~~{.cpp}
408 // C++
409
410 // Add a button to the left of the toolbar
411 Dali::Toolkit::PushButton prevButton = Dali::Toolkit::PushButton::New();
412 prevButton.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
413 prevButton.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
414 prevButton.SetProperty( Dali::Actor::Property::MINIMUM_SIZE, Dali::Vector2( 100.0f, 60.0f ) ); // this is the minimum size the button should keep
415 prevButton.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN, Dali::Vector4(10.0f, 10.0f, 10.0f, 10.0f) ); // set 10 pixel margin around the button
416 toolBar.Add( prevButton );
417
418 // Set the button text
419 Dali::Property::Map labelMap;
420 labelMap[ "text" ]      = "Prev";
421 labelMap[ "textColor" ] = Dali::Color::BLACK;
422 prevButton.SetProperty( Dali::Toolkit::Button::Property::LABEL, labelMap );
423
424 // Add a title to the center of the toolbar
425 Dali::Toolkit::TextLabel title = Dali::Toolkit::TextLabel::New( "Gallery" );
426 title.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
427 title.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
428 title.SetResizePolicy( Dali::ResizePolicy::USE_NATURAL_SIZE, Dali::Dimension::ALL_DIMENSIONS );
429 title.SetProperty( Dali::Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
430 title.SetProperty( Dali::Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
431 title.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 1.0f ); // take all the available space left apart from the two buttons
432 title.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN, Dali::Vector4(10.0f, 10.0f, 10.0f, 10.0f) ); // set 10 pixel margin around the title
433 toolBar.Add( title );
434
435 // Add a button to the right of the toolbar
436 Dali::Toolkit::PushButton nextButton = Dali::Toolkit::PushButton::New();
437 nextButton.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
438 nextButton.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
439 nextButton.SetProperty( Dali::Actor::Property::MINIMUM_SIZE, Dali::Vector2( 100.0f, 60.0f ) ); // this is the minimum size the button should keep
440 nextButton.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN, Dali::Vector4(10.0f, 10.0f, 10.0f, 10.0f) ); // set 10 pixel margin around the button
441 toolBar.Add( nextButton );
442
443 // Set the button text
444 labelMap[ "text" ] = "Next";
445 nextButton.SetProperty( Dali::Toolkit::Button::Property::LABEL, labelMap );
446 ~~~
447
448 This is really neat when running on devices with different size or changing from different orientation, because the toolbar will expand or shrink based on the available space and the title will always be in the center, therefore the layout of the toolbar will keep the same.
449  
450 Finally, we will add the image to the content area.
451  
452 ~~~{.cpp}
453 // C++
454
455 // Add an image to the center of the content area
456 Dali::Toolkit::ImageView imageView = Dali::Toolkit::ImageView::New( "image.jpg" );
457 imageView.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
458 imageView.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
459 content.Add( imageView );
460 ~~~
461
462 As you can see, it is easy to make flexible containers in DALi. We can use these concepts to create responsive layouts.
463  
464
465 */