Hi, I've been trying to wrap my head around what is necessary to dynamically add controls and have the system correctly update the layout, and I'm having a lot of problems with it. Either I'm missing something or the layout system is badly broken.
Scenario: As soon as you start dynamically adding controls to a child layout control (e.g. a StackLayout) of a ScrollView, and you have other layout controls in the same page, the system starts badly screwing up the layout.
In this particular test case, what happens is that the alignment of the text on buttons jumps to the left.
This is tested on Android with the 1.1.6202 release of Xamarin.Forms and the 19.1.0 release of Xamarin.Android.Support.v4. But I've seen the same kind of problems on the latest 1.2.1 releases of Xamarin.Forms.
Here is the test code. If you run it, and click on one of the buttons to dynamically insert, add or delete a control into the StackList child of the ScrollView you'll see the buttons text jump to the left. Note, it does not do this when the buttons themselves are not enclosed within another StackLayout. Of course this needs to work - it's not practical to say you cannot use other layout controls within the same page!
You will see code in here which calls ForceLayout on both the StackLayout contained within the ScrollView and on the ScrollView itself. This is necessary because when you add/insert/remove a control into the StackLayout it does not re-layout the controls.
Am I doing something wrong? Is there some missing magic for dealing with dynamically adding controls, or is this really badly broken?
public class App
{
static ScrollView _scrollView;
static StackLayout _buttonsStack;
public static Page GetMainPage()
{
_scrollView = new ScrollView
{
Orientation = ScrollOrientation.Horizontal,
Content = new StackLayout { Orientation = StackOrientation.Horizontal },
HeightRequest = 100
};
_buttonsStack =
new StackLayout
{
Children =
{
new Button { Text = "Add Control", Command = new Command(OnAddControl) },
new Button { Text = "Insert Control", Command = new Command(OnInsertControl) },
new Button { Text = "Remove Control", Command = new Command(OnRemoveControl) }
}
};
return new ContentPage
{
Content = new StackLayout
{
Orientation = StackOrientation.Vertical,
Children =
{
_scrollView,
_buttonsStack
}
}
};
}
private static StackLayout ScrollStackLayout
{
get { return (StackLayout)_scrollView.Content; }
}
private static void OnAddControl()
{
ScrollStackLayout.Children.Add(new Button { Text = "Hello" });
ForceRelayout();
}
private static void OnInsertControl()
{
ScrollStackLayout.Children.Insert(0, new Button { Text = "Hello" });
ForceRelayout();
}
private static void OnRemoveControl()
{
if (ScrollStackLayout.Children.Count > 0)
{
ScrollStackLayout.Children.RemoveAt(0);
ForceRelayout();
}
}
private static void ForceRelayout()
{
ScrollStackLayout.ForceLayout();
_scrollView.ForceLayout();
}
}