How can I make buttons wrap around like in a tag cloud with Xamarin Forms?

后端 未结 3 911
温柔的废话
温柔的废话 2021-01-21 18:05

I have code like this:


   
      
      
相关标签:
3条回答
  • 2021-01-21 18:54

    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>
    
    0 讨论(0)
  • 2021-01-21 19:06

    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:

    1. Implement the methods to handle the children arrangemeant
    2. Provide bindable properties to personalize the use on each need
    3. Consume it as you wish

    You may get results like this:

    0 讨论(0)
  • 2021-01-21 19:07

    As Diego suggested , we can custom Layout to achieve the expect style.

    Create new subclass which derives from Layout<View> , we just need to

    1. Override OnMeasure to return the size of this layout .

    2. Override LayoutChildren to determine positions and sizes of the children.

    3. Create Bindable Properties to personalize the use on each need.

    Custom Layout:

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

    In 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

    0 讨论(0)
提交回复
热议问题