如何使用Xamarin Forms使按钮像标签云一样环绕? [英] How can I make buttons wrap around like in a tag cloud with Xamarin Forms?

查看:86
本文介绍了如何使用Xamarin Forms使按钮像标签云一样环绕?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的代码:

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

我想做的是使按钮看起来像标签云,并扩大ViewCell的高度以容纳它们.

What I would like to do is to make the buttons look like a tag cloud and have the ViewCell height expand to accommodate them.

我没有看到任何有关如何执行此操作的示例,希望能得到一些反馈/建议.

I didn't see any examples of how I could do this and would appreciate some feedback / suggestions.

谢谢

更新1-这是我尝试的操作但不起作用

Update 1 - Here 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 was buttons on the first row and then on the second row another four buttons with the view cell expanding in height to fit.

推荐答案

正如Diego所建议的,我们可以自定义Layout以获得期望的样式.

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

创建一个从Layout<View>派生的新子类,我们只需要

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

  1. 覆盖OnMeasure以返回此布局的大小.

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

覆盖LayoutChildren以确定子代的位置和大小.

Override LayoutChildren to determine positions and sizes of the children.

创建Bindable Properties来个性化每种需求的使用.

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

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

测试

这篇关于如何使用Xamarin Forms使按钮像标签云一样环绕?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆