1 /* Copyright (c) 2020 Samsung Electronics Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 using System.ComponentModel;
18 using Tizen.NUI.BaseComponents;
19 using Tizen.NUI.Binding;
24 /// RelativeLayout calculates the size and position of all the children based on their relationship to each other.
26 /// <since_tizen> 9 </since_tizen>
27 public partial class RelativeLayout : LayoutGroup
30 /// LeftTargetProperty
32 [EditorBrowsable(EditorBrowsableState.Never)]
33 public static readonly BindableProperty LeftTargetProperty = BindableProperty.CreateAttached("LeftTarget", typeof(View), typeof(RelativeLayout), null, propertyChanged: OnChildPropertyChanged);
36 /// RightTargetProperty
38 [EditorBrowsable(EditorBrowsableState.Never)]
39 public static readonly BindableProperty RightTargetProperty = BindableProperty.CreateAttached("RightTarget", typeof(View), typeof(RelativeLayout), null, propertyChanged: OnChildPropertyChanged);
44 [EditorBrowsable(EditorBrowsableState.Never)]
45 public static readonly BindableProperty TopTargetProperty = BindableProperty.CreateAttached("TopTarget", typeof(View), typeof(RelativeLayout), null, propertyChanged: OnChildPropertyChanged);
48 /// BottomTargetProperty
50 [EditorBrowsable(EditorBrowsableState.Never)]
51 public static readonly BindableProperty BottomTargetProperty = BindableProperty.CreateAttached("BottomTarget", typeof(View), typeof(RelativeLayout), null, propertyChanged: OnChildPropertyChanged);
54 /// LeftRelativeOffsetProperty
56 [EditorBrowsable(EditorBrowsableState.Never)]
57 public static readonly BindableProperty LeftRelativeOffsetProperty = BindableProperty.CreateAttached("LeftRelativeOffset", typeof(float), typeof(RelativeLayout), 0.0f, propertyChanged: OnChildPropertyChanged);
60 /// RightRelativeOffsetProperty
62 [EditorBrowsable(EditorBrowsableState.Never)]
63 public static readonly BindableProperty RightRelativeOffsetProperty = BindableProperty.CreateAttached("RightRelativeOffset", typeof(float), typeof(RelativeLayout), 0.0f, propertyChanged: OnChildPropertyChanged);
66 /// TopRelativeOffsetProperty
68 [EditorBrowsable(EditorBrowsableState.Never)]
69 public static readonly BindableProperty TopRelativeOffsetProperty = BindableProperty.CreateAttached("TopRelativeOffset", typeof(float), typeof(RelativeLayout), 0.0f, propertyChanged: OnChildPropertyChanged);
72 /// BottomRelativeOffsetProperty
74 [EditorBrowsable(EditorBrowsableState.Never)]
75 public static readonly BindableProperty BottomRelativeOffsetProperty = BindableProperty.CreateAttached("BottomRelativeOffset", typeof(float), typeof(RelativeLayout), 0.0f, propertyChanged: OnChildPropertyChanged);
78 /// HorizontalAlignmentProperty
80 [EditorBrowsable(EditorBrowsableState.Never)]
81 public static readonly BindableProperty HorizontalAlignmentProperty = BindableProperty.CreateAttached("HorizontalAlignment", typeof(Alignment), typeof(RelativeLayout), default(Alignment), propertyChanged: OnChildPropertyChanged);
84 /// VerticalAlignmentProperty
86 [EditorBrowsable(EditorBrowsableState.Never)]
87 public static readonly BindableProperty VerticalAlignmentProperty = BindableProperty.CreateAttached("VerticalAlignment", typeof(Alignment), typeof(RelativeLayout), default(Alignment), propertyChanged: OnChildPropertyChanged);
90 /// FillHorizontalProperty
92 [EditorBrowsable(EditorBrowsableState.Never)]
93 public static readonly BindableProperty FillHorizontalProperty = BindableProperty.CreateAttached("FillHorizontal", typeof(bool), typeof(RelativeLayout), false, propertyChanged: OnChildPropertyChanged);
96 /// FillVerticalProperty
98 [EditorBrowsable(EditorBrowsableState.Never)]
99 public static readonly BindableProperty FillVerticalProperty = BindableProperty.CreateAttached("FillVertical", typeof(bool), typeof(RelativeLayout), false, propertyChanged: OnChildPropertyChanged);
104 /// <since_tizen> 9 </since_tizen>
105 public RelativeLayout() { }
108 /// Gets left target object whose size and position is being used as reference.
110 /// <param name="view">The child view whose size and position is being changed.</param>
111 /// <returns>The object whose size and position is being used as reference.</returns>
112 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
113 /// <since_tizen> 9 </since_tizen>
114 [Binding.TypeConverter(typeof(RelativeTargetConverter))]
115 public static View GetLeftTarget(BindableObject view) => GetAttachedValue<View>(view, LeftTargetProperty);
118 /// Gets right target object whose size and position is being used as reference.
120 /// <param name="view">The child view whose size and position is being changed.</param>
121 /// <returns>The object whose size and position is being used as reference.</returns>
122 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
123 /// <since_tizen> 9 </since_tizen>
124 [Binding.TypeConverter(typeof(RelativeTargetConverter))]
125 public static View GetRightTarget(BindableObject view) => GetAttachedValue<View>(view, RightTargetProperty);
128 /// Gets top target object whose size and position is being used as reference.
130 /// <param name="view">The child view whose size and position is being changed.</param>
131 /// <returns>The object whose size and position is being used as reference.</returns>
132 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
133 /// <since_tizen> 9 </since_tizen>
134 [Binding.TypeConverter(typeof(RelativeTargetConverter))]
135 public static View GetTopTarget(BindableObject view) => GetAttachedValue<View>(view, TopTargetProperty);
138 /// Gets bottom target object whose size and position is being used as reference.
140 /// <param name="view">The child view whose size and position is being changed.</param>
141 /// <returns>The object whose size and position is being used as reference.</returns>
142 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
143 /// <since_tizen> 9 </since_tizen>
144 [Binding.TypeConverter(typeof(RelativeTargetConverter))]
145 public static View GetBottomTarget(BindableObject view) => GetAttachedValue<View>(view, BottomTargetProperty);
148 /// Gets left relative offset.
150 /// <param name="view">The child view whose size and position is being changed.</param>
151 /// <returns>The ratio between left and right of the <seealso cref="LeftTargetProperty"/>.</returns>
152 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
153 /// <since_tizen> 9 </since_tizen>
154 public static float GetLeftRelativeOffset(View view) => GetAttachedValue<float>(view, LeftRelativeOffsetProperty);
157 /// Gets right relative offset.
159 /// <param name="view">The child view whose size and position is being changed.</param>
160 /// <returns>The ratio between left and right of the <seealso cref="RightTargetProperty"/>.</returns>
161 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
162 /// <since_tizen> 9 </since_tizen>
163 public static float GetRightRelativeOffset(View view) => GetAttachedValue<float>(view, RightRelativeOffsetProperty);
166 /// Gets top relative offset.
168 /// <param name="view">The child view whose size and position is being changed.</param>
169 /// <returns>The ratio between top and bottom of the <seealso cref="TopTargetProperty"/>.</returns>
170 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
171 /// <since_tizen> 9 </since_tizen>
172 public static float GetTopRelativeOffset(View view) => GetAttachedValue<float>(view, TopRelativeOffsetProperty);
175 /// Gets bottom relative offset.
177 /// <param name="view">The child view whose size and position is being changed.</param>
178 /// <returns>The ratio between top and bottom of the <seealso cref="BottomTargetProperty"/>.</returns>
179 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
180 /// <since_tizen> 9 </since_tizen>
181 public static float GetBottomRelativeOffset(View view) => GetAttachedValue<float>(view, BottomRelativeOffsetProperty);
184 /// Gets the horizontal alignment
186 /// <param name="view">The child view.</param>
187 /// <returns>The horizontal alignment of <paramref name="view"/>.</returns>
188 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
189 /// <since_tizen> 9 </since_tizen>
190 public static Alignment GetHorizontalAlignment(View view) => GetAttachedValue<Alignment>(view, HorizontalAlignmentProperty);
193 /// Gets the vertical alignment
195 /// <param name="view">The child view.</param>
196 /// <returns>The vertical alignment of <paramref name="view"/>.</returns>
197 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
198 /// <since_tizen> 9 </since_tizen>
199 public static Alignment GetVerticalAlignment(View view) => GetAttachedValue<Alignment>(view, VerticalAlignmentProperty);
202 /// Gets the boolean value whether child fills its horizontal space.
204 /// <param name="view">The child view.</param>
205 /// <returns>True if to fill the space, false otherwise.</returns>
206 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
207 /// <since_tizen> 9 </since_tizen>
208 public static bool GetFillHorizontal(View view) => GetAttachedValue<bool>(view, FillHorizontalProperty);
211 /// Gets the boolean value whether child fills its vertical space.
213 /// <param name="view">The child view.</param>
214 /// <returns>True if to fill the space, false otherwise.</returns>
215 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
216 /// <since_tizen> 9 </since_tizen>
217 public static bool GetFillVertical(View view) => GetAttachedValue<bool>(view, FillVerticalProperty);
220 /// Specifies the left side edge of the child view relative to the target view. <br/>
221 /// null <paramref name="reference"/> means parent relative layout.
223 /// <param name="view">The child view whose size and position is being changed.</param>
224 /// <param name="reference">The object whose size and position is being used as reference.</param>
225 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
226 /// <since_tizen> 9 </since_tizen>
227 public static void SetLeftTarget(View view, View reference) => SetAttachedValue(view, LeftTargetProperty, reference);
230 /// Specifies the right side edge of the child view relative to the target view. <br/>
231 /// null <paramref name="reference"/> means parent relative layout.
233 /// <param name="view">The child view whose size and position is being changed.</param>
234 /// <param name="reference">The object whose size and position is being used as reference.</param>
235 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
236 /// <since_tizen> 9 </since_tizen>
237 public static void SetRightTarget(View view, View reference) => SetAttachedValue(view, RightTargetProperty, reference);
240 /// Specifies the top side edge of the child view relative to the target view. <br/>
241 /// null <paramref name="reference"/> means parent relative layout.
243 /// <param name="view">The child view whose size and position is being changed.</param>
244 /// <param name="reference">The object whose size and position is being used as reference.</param>
245 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
246 /// <since_tizen> 9 </since_tizen>
247 public static void SetTopTarget(View view, View reference) => SetAttachedValue(view, TopTargetProperty, reference);
250 /// Specifies the bottom side edge of the child view relative to the target view. <br/>
251 /// null <paramref name="reference"/> means parent relative layout.
253 /// <param name="view">The child view whose size and position is being changed.</param>
254 /// <param name="reference">The object whose size and position is being used as reference.</param>
255 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
256 /// <since_tizen> 9 </since_tizen>
257 public static void SetBottomTarget(View view, View reference) => SetAttachedValue(view, BottomTargetProperty, reference);
260 /// Sets the relative offset for left target.
261 /// When <paramref name="value"/> is 0 the left edges of the left target and <paramref name="view"/> are aligned.<br/>
262 /// When <paramref name="value"/> is 1 the left edge of the <paramref name="view"/> is aligned to the right edge of the left target.
264 /// <param name="view">The child view whose size and position is being changed.</param>
265 /// <param name="value">The ratio between left and right of the <seealso cref="LeftTargetProperty"/>.</param>
266 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
267 /// <since_tizen> 9 </since_tizen>
268 public static void SetLeftRelativeOffset(View view, float value) => SetAttachedValue(view, LeftRelativeOffsetProperty, value);
271 /// Sets the relative offset for right target.
272 /// When <paramref name="value"/> is 0 the right edge of the <paramref name="view"/> is aligned to the left edge of the right target.<br/>
273 /// When <paramref name="value"/> is 1 the right edges of the right target and <paramref name="view"/> are aligned.
275 /// <param name="view">The child view whose size and position is being changed.</param>
276 /// <param name="value">The ratio between left and right of the <seealso cref="RightTargetProperty"/>.</param>
277 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
278 /// <since_tizen> 9 </since_tizen>
279 public static void SetRightRelativeOffset(View view, float value) => SetAttachedValue(view, RightRelativeOffsetProperty, value);
282 /// Sets the relative offset for top target.
283 /// When <paramref name="value"/> is 0 the top edges of the top target and <paramref name="view"/> are aligned.<br/>
284 /// When <paramref name="value"/> is 1 the top edge of the <paramref name="view"/> is aligned to the bottom edge of the top target.
286 /// <param name="view">The child view whose size and position is being changed.</param>
287 /// <param name="value">The ratio between left and right of the <seealso cref="TopTargetProperty"/>.</param>
288 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
289 /// <since_tizen> 9 </since_tizen>
290 public static void SetTopRelativeOffset(View view, float value) => SetAttachedValue(view, TopRelativeOffsetProperty, value);
293 /// Sets the relative offset for bottom target.
294 /// When <paramref name="value"/> is 0 the bottom edge of the <paramref name="view"/> is aligned to the top edge of the right target.<br/>
295 /// When <paramref name="value"/> is 1 the bottom edges of the bottom target and <paramref name="view"/> are aligned.
297 /// <param name="view">The child view whose size and position is being changed.</param>
298 /// <param name="value">The ratio between left and right of the <seealso cref="BottomTargetProperty"/>.</param>
299 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
300 /// <since_tizen> 9 </since_tizen>
301 public static void SetBottomRelativeOffset(View view, float value) => SetAttachedValue(view, BottomRelativeOffsetProperty, value);
304 /// Sets the horizontal alignment of this child view.
306 /// <param name="view">The child view.</param>
307 /// <param name="value">The horizontal alignment of <paramref name="view"/>.</param>
308 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
309 /// <since_tizen> 9 </since_tizen>
310 public static void SetHorizontalAlignment(View view, Alignment value) => SetAttachedValue(view, HorizontalAlignmentProperty, value);
313 /// Sets the vertical alignment of this child view.
315 /// <param name="view">The child view.</param>
316 /// <param name="value">The vertical alignment of <paramref name="view"/>.</param>
317 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
318 /// <since_tizen> 9 </since_tizen>
319 public static void SetVerticalAlignment(View view, Alignment value) => SetAttachedValue(view, VerticalAlignmentProperty, value);
322 /// Sets the boolean value whether child fills its horizontal space.
324 /// <param name="view">The child view.</param>
325 /// <param name="value">True if to fill the space, false otherwise.</param>
326 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
327 /// <since_tizen> 9 </since_tizen>
328 public static void SetFillHorizontal(View view, bool value) => SetAttachedValue(view, FillHorizontalProperty, value);
331 /// Sets the boolean value whether child fills its vertical space.
333 /// <param name="view">The child view.</param>
334 /// <param name="value">True if to fill the space, false otherwise.</param>
335 /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
336 /// <since_tizen> 9 </since_tizen>
337 public static void SetFillVertical(View view, bool value) => SetAttachedValue(view, FillVerticalProperty, value);
340 /// <since_tizen> 9 </since_tizen>
341 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
343 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
344 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
346 for (int i = 0; i < LayoutChildren.Count; i++)
348 LayoutItem childLayout = LayoutChildren[i];
349 if (childLayout != null)
351 MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0));
353 if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
355 childWidthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
357 if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
359 childHeightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
364 (float childrenWidth, float childrenHeight) = CalculateChildrenSize(widthMeasureSpec.Size.AsDecimal(), heightMeasureSpec.Size.AsDecimal());
365 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(childrenWidth), widthMeasureSpec, childWidthState),
366 ResolveSizeAndState(new LayoutLength(childrenHeight), heightMeasureSpec, childHeightState));
370 /// <since_tizen> 9 </since_tizen>
371 protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
373 for (int i = 0; i < LayoutChildren.Count; i++)
375 LayoutItem childLayout = LayoutChildren[i];
376 if (childLayout != null)
378 Geometry horizontalGeometry = GetHorizontalLayout(childLayout.Owner);
379 Geometry verticalGeometry = GetVerticalLayout(childLayout.Owner);
381 LayoutLength childLeft = new LayoutLength(horizontalGeometry.Position);
382 LayoutLength childRight = new LayoutLength(horizontalGeometry.Position + horizontalGeometry.Size);
383 LayoutLength childTop = new LayoutLength(verticalGeometry.Position);
384 LayoutLength childBottom = new LayoutLength(verticalGeometry.Position + verticalGeometry.Size);
386 childLayout.Layout(childLeft, childTop, childRight, childBottom);
389 HorizontalRelativeCache.Clear();
390 VerticalRelativeCache.Clear();
393 /// <summary>The alignment of the relative layout child.</summary>
394 /// <since_tizen> 9 </since_tizen>
395 public enum Alignment
397 /// <summary>At the start of the container.</summary>
398 /// <since_tizen> 9 </since_tizen>
400 /// <summary>At the center of the container.</summary>
401 /// <since_tizen> 9 </since_tizen>
403 /// <summary>At the end of the container.</summary>
404 /// <since_tizen> 9 </since_tizen>
409 // Extension Method of RelativeLayout.Alignment.
410 internal static partial class RelativeLayoutAlignmentExtension
412 public static float ToFloat(this RelativeLayout.Alignment align)
414 return 0.5f * (float)align;