diff options
-rw-r--r-- | Xamarin.Forms.Core.UnitTests/RelativeLayoutTests.cs | 41 | ||||
-rw-r--r-- | Xamarin.Forms.Core/RelativeLayout.cs | 62 | ||||
-rw-r--r-- | docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout.xml | 84 |
3 files changed, 179 insertions, 8 deletions
diff --git a/Xamarin.Forms.Core.UnitTests/RelativeLayoutTests.cs b/Xamarin.Forms.Core.UnitTests/RelativeLayoutTests.cs index 96b3dfc8..fdbcdfc0 100644 --- a/Xamarin.Forms.Core.UnitTests/RelativeLayoutTests.cs +++ b/Xamarin.Forms.Core.UnitTests/RelativeLayoutTests.cs @@ -75,6 +75,47 @@ namespace Xamarin.Forms.Core.UnitTests } [Test] + public void LayoutIsUpdatedWhenConstraintsChange() + { + var relativeLayout = new RelativeLayout + { + Platform = new UnitPlatform(), + IsPlatformEnabled = true + }; + + var child = new View + { + IsPlatformEnabled = true + }; + + relativeLayout.Children.Add(child, + Constraint.Constant(30), + Constraint.Constant(20), + Constraint.RelativeToParent(parent => parent.Height / 2), + Constraint.RelativeToParent(parent => parent.Height / 4)); + + relativeLayout.Layout(new Rectangle(0, 0, 100, 100)); + + Assert.AreEqual(new Rectangle(30, 20, 50, 25), child.Bounds); + + RelativeLayout.SetXConstraint(child, Constraint.Constant(40)); + + Assert.AreEqual(new Rectangle(40, 20, 50, 25), child.Bounds); + + RelativeLayout.SetYConstraint(child, Constraint.Constant(10)); + + Assert.AreEqual(new Rectangle(40, 10, 50, 25), child.Bounds); + + RelativeLayout.SetWidthConstraint(child, Constraint.RelativeToParent(parent => parent.Height / 4)); + + Assert.AreEqual(new Rectangle(40, 10, 25, 25), child.Bounds); + + RelativeLayout.SetHeightConstraint(child, Constraint.RelativeToParent(parent => parent.Height / 2)); + + Assert.AreEqual(new Rectangle(40, 10, 25, 50), child.Bounds); + } + + [Test] public void SimpleExpressionLayout () { var relativeLayout = new RelativeLayout { diff --git a/Xamarin.Forms.Core/RelativeLayout.cs b/Xamarin.Forms.Core/RelativeLayout.cs index b3a1b615..2b835013 100644 --- a/Xamarin.Forms.Core/RelativeLayout.cs +++ b/Xamarin.Forms.Core/RelativeLayout.cs @@ -8,13 +8,13 @@ namespace Xamarin.Forms { public class RelativeLayout : Layout<View> { - public static readonly BindableProperty XConstraintProperty = BindableProperty.CreateAttached("XConstraint", typeof(Constraint), typeof(RelativeLayout), null); + public static readonly BindableProperty XConstraintProperty = BindableProperty.CreateAttached("XConstraint", typeof(Constraint), typeof(RelativeLayout), null, propertyChanged: ConstraintChanged); - public static readonly BindableProperty YConstraintProperty = BindableProperty.CreateAttached("YConstraint", typeof(Constraint), typeof(RelativeLayout), null); + public static readonly BindableProperty YConstraintProperty = BindableProperty.CreateAttached("YConstraint", typeof(Constraint), typeof(RelativeLayout), null, propertyChanged: ConstraintChanged); - public static readonly BindableProperty WidthConstraintProperty = BindableProperty.CreateAttached("WidthConstraint", typeof(Constraint), typeof(RelativeLayout), null); + public static readonly BindableProperty WidthConstraintProperty = BindableProperty.CreateAttached("WidthConstraint", typeof(Constraint), typeof(RelativeLayout), null, propertyChanged: ConstraintChanged); - public static readonly BindableProperty HeightConstraintProperty = BindableProperty.CreateAttached("HeightConstraint", typeof(Constraint), typeof(RelativeLayout), null); + public static readonly BindableProperty HeightConstraintProperty = BindableProperty.CreateAttached("HeightConstraint", typeof(Constraint), typeof(RelativeLayout), null, propertyChanged: ConstraintChanged); public static readonly BindableProperty BoundsConstraintProperty = BindableProperty.CreateAttached("BoundsConstraint", typeof(BoundsConstraint), typeof(RelativeLayout), null); @@ -72,6 +72,25 @@ namespace Xamarin.Forms } } + static void ConstraintChanged(BindableObject bindable, object oldValue, object newValue) + { + View view = bindable as View; + + (view?.Parent as RelativeLayout)?.UpdateBoundsConstraint(view); + } + + void UpdateBoundsConstraint(View view) + { + if (GetBoundsConstraint(view) == null) + return; // Bounds constraint hasn't been calculated yet, no need to update just yet + + CreateBoundsFromConstraints(view, GetXConstraint(view), GetYConstraint(view), GetWidthConstraint(view), GetHeightConstraint(view)); + + _childrenInSolveOrder = null; // New constraints may have impact on solve order + + InvalidateLayout(); + } + public static BoundsConstraint GetBoundsConstraint(BindableObject bindable) { return (BoundsConstraint)bindable.GetValue(BoundsConstraintProperty); @@ -102,6 +121,26 @@ namespace Xamarin.Forms bindable.SetValue(BoundsConstraintProperty, value); } + public static void SetHeightConstraint(BindableObject bindable, Constraint value) + { + bindable.SetValue(HeightConstraintProperty, value); + } + + public static void SetWidthConstraint(BindableObject bindable, Constraint value) + { + bindable.SetValue(WidthConstraintProperty, value); + } + + public static void SetXConstraint(BindableObject bindable, Constraint value) + { + bindable.SetValue(XConstraintProperty, value); + } + + public static void SetYConstraint(BindableObject bindable, Constraint value) + { + bindable.SetValue(YConstraintProperty, value); + } + protected override void LayoutChildren(double x, double y, double width, double height) { foreach (View child in ChildrenInSolveOrder) @@ -248,13 +287,13 @@ namespace Xamarin.Forms static Rectangle SolveView(View view) { BoundsConstraint boundsConstraint = GetBoundsConstraint(view); - var result = new Rectangle(); if (boundsConstraint == null) { throw new Exception("BoundsConstraint should not be null at this point"); } - result = boundsConstraint.Compute(); + + var result = boundsConstraint.Compute(); return result; } @@ -280,7 +319,7 @@ namespace Xamarin.Forms public void Add(View view, Expression<Func<Rectangle>> bounds) { if (bounds == null) - throw new ArgumentNullException("bounds"); + throw new ArgumentNullException(nameof(bounds)); SetBoundsConstraint(view, BoundsConstraint.FromExpression(bounds)); base.Add(view); @@ -308,7 +347,14 @@ namespace Xamarin.Forms public void Add(View view, Constraint xConstraint = null, Constraint yConstraint = null, Constraint widthConstraint = null, Constraint heightConstraint = null) { - Parent.CreateBoundsFromConstraints(view, xConstraint, yConstraint, widthConstraint, heightConstraint); + view.BatchBegin(); + + RelativeLayout.SetXConstraint(view, xConstraint); + RelativeLayout.SetYConstraint(view, yConstraint); + RelativeLayout.SetWidthConstraint(view, widthConstraint); + RelativeLayout.SetHeightConstraint(view, heightConstraint); + + view.BatchCommit(); base.Add(view); } diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout.xml index 8d1082e9..6a8c498b 100644 --- a/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout.xml +++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout.xml @@ -446,6 +446,90 @@ public class RelativeLayoutExample : ContentPage <remarks>To be added.</remarks> </Docs> </Member> + <Member MemberName="SetHeightConstraint"> + <MemberSignature Language="C#" Value="public static void SetHeightConstraint (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.Constraint value);" /> + <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetHeightConstraint(class Xamarin.Forms.BindableObject bindable, class Xamarin.Forms.Constraint value) cil managed" /> + <MemberType>Method</MemberType> + <AssemblyInfo> + <AssemblyVersion>2.0.0.0</AssemblyVersion> + </AssemblyInfo> + <ReturnValue> + <ReturnType>System.Void</ReturnType> + </ReturnValue> + <Parameters> + <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" /> + <Parameter Name="value" Type="Xamarin.Forms.Constraint" /> + </Parameters> + <Docs> + <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> to which the constraint will be applied.</param> + <param name="value">The <see cref="T:Xamarin.Forms.Constraint" /> on the height of the <paramref name="bindable" />.</param> + <summary>Sets <paramref name="value" /> as a constraint on the height of the <paramref name="bindable" />.</summary> + <remarks>To be added.</remarks> + </Docs> + </Member> + <Member MemberName="SetWidthConstraint"> + <MemberSignature Language="C#" Value="public static void SetWidthConstraint (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.Constraint value);" /> + <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetWidthConstraint(class Xamarin.Forms.BindableObject bindable, class Xamarin.Forms.Constraint value) cil managed" /> + <MemberType>Method</MemberType> + <AssemblyInfo> + <AssemblyVersion>2.0.0.0</AssemblyVersion> + </AssemblyInfo> + <ReturnValue> + <ReturnType>System.Void</ReturnType> + </ReturnValue> + <Parameters> + <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" /> + <Parameter Name="value" Type="Xamarin.Forms.Constraint" /> + </Parameters> + <Docs> + <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> to which the constraint will be applied.</param> + <param name="value">The <see cref="T:Xamarin.Forms.Constraint" /> on the width of the <paramref name="bindable" />.</param> + <summary>Sets <paramref name="value" /> as a constraint on the width of the <paramref name="bindable" />.</summary> + <remarks>To be added.</remarks> + </Docs> + </Member> + <Member MemberName="SetXConstraint"> + <MemberSignature Language="C#" Value="public static void SetXConstraint (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.Constraint value);" /> + <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetXConstraint(class Xamarin.Forms.BindableObject bindable, class Xamarin.Forms.Constraint value) cil managed" /> + <MemberType>Method</MemberType> + <AssemblyInfo> + <AssemblyVersion>2.0.0.0</AssemblyVersion> + </AssemblyInfo> + <ReturnValue> + <ReturnType>System.Void</ReturnType> + </ReturnValue> + <Parameters> + <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" /> + <Parameter Name="value" Type="Xamarin.Forms.Constraint" /> + </Parameters> + <Docs> + <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> to which the constraint will be applied.</param> + <param name="value">The <see cref="T:Xamarin.Forms.Constraint" /> on the X position of the <paramref name="bindable" />.</param> + <summary>Sets <paramref name="value" /> as a constraint on the X position of the <paramref name="bindable" />.</summary> + <remarks>To be added.</remarks> + </Docs> + </Member> + <Member MemberName="SetYConstraint"> + <MemberSignature Language="C#" Value="public static void SetYConstraint (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.Constraint value);" /> + <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetYConstraint(class Xamarin.Forms.BindableObject bindable, class Xamarin.Forms.Constraint value) cil managed" /> + <MemberType>Method</MemberType> + <AssemblyInfo> + <AssemblyVersion>2.0.0.0</AssemblyVersion> + </AssemblyInfo> + <ReturnValue> + <ReturnType>System.Void</ReturnType> + </ReturnValue> + <Parameters> + <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" /> + <Parameter Name="value" Type="Xamarin.Forms.Constraint" /> + </Parameters> + <Docs> + <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> to which the constraint will be applied.</param> + <param name="value">The <see cref="T:Xamarin.Forms.Constraint" /> on the Y position of the <paramref name="bindable" />.</param> + <summary>Sets <paramref name="value" /> as a constraint on the Y position of the <paramref name="bindable" />.</summary> + <remarks>To be added.</remarks> + </Docs> + </Member> <Member MemberName="WidthConstraintProperty"> <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty WidthConstraintProperty;" /> <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty WidthConstraintProperty" /> |