[dali_2.3.19] Merge branch 'devel/master'
[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, between, and after the lines |
119  
120 ### Usage
121
122 ~~~{.cpp}
123 // C++
124 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
125 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::JUSTIFY_CONTENT, Dali::Toolkit::FlexContainer::JUSTIFY_SPACE_BETWEEN );
126 ~~~
127
128 ___________________________________________________________________________________________________
129
130 ## alignItems {#align-items}
131  
132 alignItems specifies the alignment of flex items when they do not use all available space on the cross axis.
133  
134 ![ ](flex-container/align-items.jpg)
135  
136 The possible values for this property are:
137  
138 | Property Value | Description                                 |
139 |----------------|---------------------------------------------|
140 | ALIGN_FLEX_START | Items are aligned at the beginning of the container |
141 | ALIGN_CENTER     | Items are aligned at the center of the container    |
142 | ALIGN_FLEX_END   | Items are aligned at the end of the container       |
143 | ALIGN_STRETCH    | Items are stretched to fit the container            |
144  
145 ### Usage
146
147 ~~~{.cpp}
148 // C++
149 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
150 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_ITEMS, Dali::Toolkit::FlexContainer::ALIGN_FLEX_START );
151 ~~~
152
153 ___________________________________________________________________________________________________
154
155 ## alignContent {#align-content}
156  
157 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.
158  
159 ![ ](flex-container/align-content.jpg)
160  
161 The possible values for this property are:
162  
163 | Property Value | Description                                 |
164 |----------------|---------------------------------------------|
165 | ALIGN_FLEX_START | Items are aligned at the beginning of the container |
166 | ALIGN_CENTER     | Items are aligned at the center of the container    |
167 | ALIGN_FLEX_END   | Items are aligned at the end of the container       |
168  
169 ### Usage
170
171 ~~~{.cpp}
172 // C++
173 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
174 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_CONTENT, Dali::Toolkit::FlexContainer::ALIGN_FLEX_END );
175 ~~~
176
177 ___________________________________________________________________________________________________
178
179 ## Custom properties supported by flex item:
180
181  + [flex](@ref flex)
182  + [alignSelf](@ref align-self)
183  + [flexMargin](@ref flex-margin)
184  
185 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.
186  
187 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.
188  
189 ___________________________________________________________________________________________________
190
191 ## flex {#flex}
192  
193 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.
194 If all items in the flex container use this pattern, their sizes will be proportional to the specified flex factor.
195 Flex items will not shrink below their minimum size (if set using Dali::Actor::SetMinimumSize).
196  
197 ![ ](flex-container/flex.jpg)
198  
199
200 ### Usage
201
202 Below is the example code for the items to achieve the proportion of free space as illustrated above.
203  
204 ~~~{.cpp}
205 // C++
206
207 // Create the flex container
208 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
209
210 // Set the flex direction to lay out the items horizontally
211 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::ROW );
212
213 // Create flex items and set the proportion
214 Dali::Toolkit::Control item1 = Dali::Toolkit::Control::New();
215 item1.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 1.0f );
216 flexContainer.Add( item1 );
217
218 Dali::Toolkit::Control item2 = Dali::Toolkit::Control::New();
219 item2.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 3.0f );
220 flexContainer.Add( item2 );
221
222 Dali::Toolkit::Control item3 = Dali::Toolkit::Control::New();
223 item3.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 1.0f );
224 flexContainer.Add( item3 );
225
226 Dali::Toolkit::Control item4 = Dali::Toolkit::Control::New();
227 item4.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 2.0f );
228 flexContainer.Add( item4 );
229
230 Dali::Toolkit::Control item5 = Dali::Toolkit::Control::New();
231 item5.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 1.0f );
232 flexContainer.Add( item5 );
233
234 ~~~
235
236 ___________________________________________________________________________________________________
237
238 ## alignSelf {#align-self}
239  
240 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.
241  
242 ![ ](flex-container/align-self.jpg)
243  
244 The possible values for this property are:
245  
246 | Property Value | Description                                 |
247 |----------------|---------------------------------------------|
248 | ALIGN_AUTO       | Items inherit the same alignment from the parent by default (as specified by the container’s [alignItems](@ref align-items) property) |
249 | ALIGN_FLEX_START | Items are aligned at the beginning of the container |
250 | ALIGN_CENTER     | Items are aligned at the center of the container    |
251 | ALIGN_FLEX_END   | Items are aligned at the end of the container       |
252 | ALIGN_STRETCH    | Items are stretched to fit the container            |
253  
254 ### Usage
255
256 Below is the example code for the items to achieve the alignment on the cross axis as illustrated above.
257  
258 ~~~{.cpp}
259 // C++
260
261 // Create the flex container
262 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
263
264 // Set the flex direction to lay out the items horizontally
265 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::ROW );
266
267 // Set the items to be aligned at the beginning of the container on the cross axis by default
268 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_ITEMS, Dali::Toolkit::FlexContainer::ALIGN_FLEX_START );
269
270 // Create flex items and add them to the flex container
271 Dali::Toolkit::Control item1 = Dali::Toolkit::Control::New();
272 item1.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::ALIGN_SELF, Dali::Toolkit::FlexContainer::ALIGN_CENTER ); // Align item1 at the center of the container
273 flexContainer.Add( item1 );
274
275 Dali::Toolkit::Control item2 = Dali::Toolkit::Control::New();
276 flexContainer.Add( item2 ); // item2 is aligned at the beginning of the container
277
278 Dali::Toolkit::Control item3 = Dali::Toolkit::Control::New();
279 item3.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::ALIGN_SELF, Dali::Toolkit::FlexContainer::ALIGN_FLEX_END ); // Align item3 at the bottom of the container
280 flexContainer.Add( item3 );
281
282 Dali::Toolkit::Control item4 = Dali::Toolkit::Control::New();
283 flexContainer.Add( item4 ); // item4 is aligned at the beginning of the container
284
285 ~~~
286
287 ___________________________________________________________________________________________________
288
289 ## flexMargin {#flex-margin}
290  
291 Each flex item inside the flex container is treated as a box (in CSS term) which is made up of:
292
293  + content: The content of the item.
294  + padding: The space around the content (inside the border) of the item.
295  + border: The border that goes around the padding and the content of the item.
296  + flexMargin: The space outside the border.
297  
298 ![ ](flex-container/flex-margin.jpg)
299  
300 In DALi, the size of the flex item = content size + padding + border.
301  
302 flexMargin specifies the space around the flex item.
303  
304 ### Usage
305
306 ~~~{.cpp}
307 // C++
308
309 // Create the flex container
310 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
311
312 // Create flex item
313 Dali::Toolkit::Control item = Dali::Toolkit::Control::New();
314
315 // Add the margin around the item
316 item.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN, Vector4(10.0f, 10.0f, 10.0f, 10.0f) );
317
318 // Add the item to the container
319 flexContainer.Add( item );
320 ~~~
321
322 ___________________________________________________________________________________________________
323
324 ## Example of creating Flexbox layout using FlexContainer
325
326 Now let's see how to create a Gallery like layout (as shown below) using FlexContainer.
327
328 ![ ](flex-container/flexbox-demo.jpg)
329  
330 Firstly, we create a flex container as the whole view and set its resize policy to fill its parent (i.e. the stage).
331
332 ~~~{.cpp}
333 // C++
334
335 // Create the main flex container
336 Dali::Toolkit::FlexContainer flexContainer = Dali::Toolkit::FlexContainer::New();
337 flexContainer.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
338 flexContainer.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
339 flexContainer.SetResizePolicy( Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS );
340 flexContainer.SetBackgroundColor( Dali::Color::WHITE ); // set the background color to be white
341
342 // Add it to the stage
343 Dali::Stage::GetCurrent().Add( flexContainer );
344 ~~~
345
346  
347 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.
348  
349 ~~~{.cpp}
350 // C++
351
352 // Display toolbar and content vertically
353 flexContainer.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::COLUMN );
354 ~~~
355
356 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.
357  
358 ~~~{.cpp}
359 // C++
360
361 // Create the toolbar
362 Dali::Toolkit::FlexContainer toolBar = Dali::Toolkit::FlexContainer::New();
363 toolBar.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
364 toolBar.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
365 toolBar.SetBackgroundColor( Dali::Color::CYAN ); // Set the background color for the toolbar
366
367 // Add it to the main container
368 flexContainer.Add( toolBar );
369 ~~~
370
371 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.
372 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.
373 This can be achieved by setting the flex property.
374  
375 ~~~{.cpp}
376 // C++
377
378 toolBar.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::ROW ); // display toolbar items horizontally
379 toolBar.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_ITEMS, Dali::Toolkit::FlexContainer::ALIGN_CENTER ); // align toolbar items vertically center
380 toolBar.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 0.1f ); // 10 percent of available space in the cross axis
381 ~~~
382
383 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.
384 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.
385
386 ~~~{.cpp}
387 // C++
388
389 // Create the content area
390 Dali::Toolkit::FlexContainer content = Dali::Toolkit::FlexContainer::New();
391 content.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
392 content.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
393 content.SetProperty( Dali::Toolkit::FlexContainer::Property::FLEX_DIRECTION, Dali::Toolkit::FlexContainer::ROW ); // display items horizontally
394 content.SetProperty( Dali::Toolkit::FlexContainer::Property::JUSTIFY_CONTENT, Dali::Toolkit::FlexContainer::JUSTIFY_CENTER ); // align items horizontally center
395 content.SetProperty( Dali::Toolkit::FlexContainer::Property::ALIGN_ITEMS, Dali::Toolkit::FlexContainer::ALIGN_CENTER ); // align items vertically center
396 content.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 0.9f ); // 90 percent of available space in the cross axis
397
398 // Add it to the main container
399 flexContainer.Add( content );
400 ~~~
401
402 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).
403 To achieve that, we can simply make the title flexible so that it will automatically take all the available horizontal space left.
404 We will also add some space around the items so that the layout looks nicer.
405  
406 ~~~{.cpp}
407 // C++
408
409 // Add a button to the left of the toolbar
410 Dali::Toolkit::PushButton prevButton = Dali::Toolkit::PushButton::New();
411 prevButton.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
412 prevButton.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
413 prevButton.SetProperty( Dali::Actor::Property::MINIMUM_SIZE, Dali::Vector2( 100.0f, 60.0f ) ); // this is the minimum size the button should keep
414 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
415 toolBar.Add( prevButton );
416
417 // Set the button text
418 Dali::Property::Map labelMap;
419 labelMap[ "text" ]      = "Prev";
420 labelMap[ "textColor" ] = Dali::Color::BLACK;
421 prevButton.SetProperty( Dali::Toolkit::Button::Property::LABEL, labelMap );
422
423 // Add a title to the center of the toolbar
424 Dali::Toolkit::TextLabel title = Dali::Toolkit::TextLabel::New( "Gallery" );
425 title.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
426 title.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
427 title.SetResizePolicy( Dali::ResizePolicy::USE_NATURAL_SIZE, Dali::Dimension::ALL_DIMENSIONS );
428 title.SetProperty( Dali::Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
429 title.SetProperty( Dali::Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
430 title.SetProperty( Dali::Toolkit::FlexContainer::ChildProperty::FLEX, 1.0f ); // take all the available space left apart from the two buttons
431 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
432 toolBar.Add( title );
433
434 // Add a button to the right of the toolbar
435 Dali::Toolkit::PushButton nextButton = Dali::Toolkit::PushButton::New();
436 nextButton.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
437 nextButton.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
438 nextButton.SetProperty( Dali::Actor::Property::MINIMUM_SIZE, Dali::Vector2( 100.0f, 60.0f ) ); // this is the minimum size the button should keep
439 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
440 toolBar.Add( nextButton );
441
442 // Set the button text
443 labelMap[ "text" ] = "Next";
444 nextButton.SetProperty( Dali::Toolkit::Button::Property::LABEL, labelMap );
445 ~~~
446
447 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.
448  
449 Finally, we will add the image to the content area.
450  
451 ~~~{.cpp}
452 // C++
453
454 // Add an image to the center of the content area
455 Dali::Toolkit::ImageView imageView = Dali::Toolkit::ImageView::New( "image.jpg" );
456 imageView.SetParentOrigin( Dali::ParentOrigin::TOP_LEFT );
457 imageView.SetProperty( Dali::Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::TOP_LEFT );
458 content.Add( imageView );
459 ~~~
460
461 As you can see, it is easy to make flexible containers in DALi. We can use these concepts to create responsive layouts.
462  
463
464 */