I have code like this:
why not use a StackLayout ?
<StackLayout Orientation="Horizontal" IsClippedToBounds="false" Spacing="5" >
<Button Text="ABCDEFG" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30" ></Button>
<Button Text="ABCDEFG" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30" ></Button>
<Button Text="ABCDEFG" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30" ></Button>
<Button Text="ABCDEFG" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30" ></Button>
</StackLayout>
You can achieve this following the guide provided by the xamarin forms developers site at https://developer.xamarin.com/guides/xamarin-forms/user-interface/layouts/custom/
The problem you described is exactally what the sample code this guide shows. Creating a custom layout you can reuse this solution everywhere you need it.
Succinctly, what you have to do to create your WrapLayout:
You may get results like this:
As Diego suggested , we can custom Layout
to achieve the expect style.
Create new subclass which derives from Layout<View>
, we just need to
Override OnMeasure
to return the size of this layout .
Override LayoutChildren
to determine positions and sizes of the children.
Create Bindable Properties
to personalize the use on each need.
public class WrapLayout : Layout<View>
{
public static readonly BindableProperty SpacingProperty =
BindableProperty.Create
(
"Spacing",
typeof(double),
typeof(WrapLayout),
10.0,
propertyChanged: (bindable, oldvalue, newvalue) => ((WrapLayout)bindable).OnSizeChanged()
);
public double Spacing
{
get { return (double)GetValue(SpacingProperty); }
set { SetValue(SpacingProperty, value); }
}
private void OnSizeChanged()
{
this.ForceLayout();
}
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
if (WidthRequest > 0)
widthConstraint = Math.Min(widthConstraint, WidthRequest);
if (HeightRequest > 0)
heightConstraint = Math.Min(heightConstraint, HeightRequest);
double internalWidth = double.IsPositiveInfinity(widthConstraint) ? double.PositiveInfinity : Math.Max(0, widthConstraint);
double internalHeight = double.IsPositiveInfinity(heightConstraint) ? double.PositiveInfinity : Math.Max(0, heightConstraint);
return DoHorizontalMeasure(internalWidth, internalHeight);
}
private SizeRequest DoHorizontalMeasure(double widthConstraint, double heightConstraint)
{
int rowCount = 1;
double width = 0;
double height = 0;
double minWidth = 0;
double minHeight = 0;
double widthUsed = 0;
foreach (var item in Children)
{
var size = item.Measure(widthConstraint, heightConstraint);
height = Math.Max(height, size.Request.Height);
var newWidth = width + size.Request.Width + Spacing;
if (newWidth > widthConstraint)
{
rowCount++;
widthUsed = Math.Max(width, widthUsed);
width = size.Request.Width;
}
else
width = newWidth;
minHeight = Math.Max(minHeight, size.Minimum.Height);
minWidth = Math.Max(minWidth, size.Minimum.Width);
}
if (rowCount > 1)
{
width = Math.Max(width, widthUsed);
height = (height + Spacing) * rowCount - Spacing; // via MitchMilam
}
return new SizeRequest(new Size(width, height), new Size(minWidth, minHeight));
}
protected override void LayoutChildren(double x, double y, double width, double height)
{
double rowHeight = 0;
double yPos = y, xPos = x;
foreach (var child in Children.Where(c => c.IsVisible))
{
var request = child.Measure(width, height);
double childWidth = request.Request.Width;
double childHeight = request.Request.Height;
rowHeight = Math.Max(rowHeight, childHeight);
if (xPos + childWidth > width)
{
xPos = x;
yPos += rowHeight + Spacing;
rowHeight = 0;
}
var region = new Rectangle(xPos, yPos, childWidth, childHeight);
LayoutChildIntoBoundingRegion(child, region);
xPos += region.Width + Spacing;
}
}
}
<local:WrapLayout Spacing="5">
<Button Text="111111111111111" BackgroundColor="Red"/>
<Button Text="222" BackgroundColor="Green"/>
<Button Text="33333333333333333333333333" BackgroundColor="Gray"/>
<Button Text="444444" BackgroundColor="Blue"/>
<Button Text="5" BackgroundColor="Orange"/>
<Button Text="6666666666666666" BackgroundColor="Aqua"/>
<Button Text="77777777" BackgroundColor="Yellow"/>
<Button Text="888" BackgroundColor="Pink"/>
<Button Text="9 9 9 9" BackgroundColor="Purple"/>
<Button Text="10" BackgroundColor="Brown"/>
</local:WrapLayout>