How to make buttons wrap around like in a tag cloud using Xamarin Forms?

I have a code like this:

<TableSection>
   <ViewCell Height="200">
      <Button Text="ABCDEFG"></Button>
      <Button Text="ABCDEFG"></Button>
      <Button Text="ABCDEFG"></Button>
      <Button Text="ABCDEFG"></Button>      
      <Button Text="ABCDEFG"></Button>
      <Button Text="ABCDEFG"></Button>
      <Button Text="ABCDEFG"></Button>
   </ViewCell>
</TableSection>

What I would like to do is make the buttons look like a tag cloud and increase the height of the ViewCell to place them.

I have not seen examples of how I could do this, and would appreciate some feedback / suggestions.

thanks

Update 1 is what I tried , but it doesn't work

   <ViewCell Height="200">
      <StackLayout Orientation="Horizontal" IsClippedToBounds="false" Spacing="5">
         <Button Text="ABCDEF1" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
                                </Button>
         <Button Text="ABCDEF2" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
                                </Button>
         <Button Text="ABCDEF3" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
                                </Button>
         <Button Text="ABCDEF4" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
                                </Button>
         <Button Text="ABCDEF5" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
                                </Button>
         <Button Text="ABCDEF6" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
                                </Button>
         <Button Text="ABCDEF7" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
                                </Button>
         <Button Text="ABCDEF8" TextColor="Blue" BackgroundColor="Transparent" WidthRequest="90" HeightRequest="30">
                                </Button>
      </StackLayout>
   </ViewCell>

Unfortunately, all I see is the first four buttons, and then nothing after that. What I was hoping to see are the buttons in the first row, and then in the second row four more buttons with a height-expanded view cell.

+2
source share
3 answers

, Layout .

, Layout<View>,

  • OnMeasure, .

  • LayoutChildren, .

  • Bindable Properties, .

:

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;
        }
    }
}

Xmal

<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>

Test

+3

why not use 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>
+1
source

All Articles