1. 程式人生 > >UWP中實現大爆炸效果(一)

UWP中實現大爆炸效果(一)

ID eight 爆炸效果 foo 更新 The 選中 wid 重寫

自從老羅搞出大爆炸之後,各家安卓都內置了類似功能。UWP怎麽能落下呢,在這裏我們就一起擼一個簡單的大爆炸實現。

閑話不說,先上效果:

技術分享圖片

因為代碼太多,所以我打算寫成一個系列,下面是第一篇的正文:

首先,我們構思一下BigbangView需要哪些部分:

1、一個能多選的控件;

2、一個能給Item布局的面板;

3、選中之後出現的Header和Footer。

這裏我們先來實現第二項,BigbangPanel。

BigbangPanel繼承自Panel,重載MeasureOverride和ArrangeOverride方法。

MeasureOverride實現調用此方法以形成遞歸布局更新;

ArrangeOverride為其子元素實現自定義布局的父對象應從其布局重寫實現調用此方法以形成遞歸布局更新。

我們對面板子元素布局的思路是,遍歷子元素,從左到右依次排列,若當前行子元素總寬度超過Panel寬度,則換一行從頭繼續排列。

(在此我們只實現一個簡單版,不考慮子元素的VerticalAlignment)

protected override Size MeasureOverride(Size availableSize)
{
    foreach (var child in Children)
    {
        child.Measure(availableSize);
    }

    double width = 0d, height = 0d;
    double col_width = 0d, row_height = 0d;
    int end_row_count = -1;

    for (int i = 0; i < Children.Count; i++)
    {
        if (Children[i].DesiredSize.Width + col_width > availableSize.Width)
        {
            end_row_count = i;
            height += row_height;
            width = Math.Max(width, col_width);
            col_width = 0;
            row_height = 0;
        }
        col_width += Children[i].DesiredSize.Width;
        row_height = Math.Max(row_height, Children[i].DesiredSize.Height);
    }

    //計算最後一行
    if (end_row_count != -1)
    {
        col_width = 0;
        row_height = 0;
        for (int i = end_row_count; i < Children.Count; i++)
        {
            row_height = Math.Max(row_height, Children[i].DesiredSize.Height);
            col_width += Children[i].DesiredSize.Width;
        }
        height += row_height;
        width = Math.Max(width, col_width);
    }

    return new Size(width, height);
}

  

protected override Size ArrangeOverride(Size finalSize)
{
    double x = 0d, y = 0d;
    double items_height = 0d;
    int end_count = -1;
    int row_start_index = 0;

    for (int i = 0; i < Children.Count; i++)
    {
        if (Children[i].DesiredSize.Width + x > finalSize.Width)
        {
            x = 0;
            y += items_height;

            items_height = 0;
            end_count = i;
            row_start_index = i;
        }
        Children[i].Arrange(new Rect(x, y, Children[i].DesiredSize.Width, Children[i].DesiredSize.Height));
        x += Children[i].DesiredSize.Width;
        items_height = Math.Max(items_height, Children[i].DesiredSize.Height);
    }
    return finalSize;
}

  

現在可以測試一下,新建一個頁面,添加一個ListView,修改ListView的ItemsPanel

技術分享圖片
<ListView.ItemsPanel>
    <ItemsPanelTemplate>
        <control:BigbangPanel >
            <control:BigbangPanel.ChildrenTransitions>
                <TransitionCollection>
                <AddDeleteThemeTransition />
                </TransitionCollection>
            </control:BigbangPanel.ChildrenTransitions>
        </control:BigbangPanel>
    </ItemsPanelTemplate>
</ListView.ItemsPanel>
View Code

後臺代碼:

public sealed partial class BigbangPage : Page
{
    public BigbangPage()
    {
        this.InitializeComponent();
        for(int i = 0; i < 50; i++)
        {
            list.Add(rnd.Next(100000).ToString());
        }
    }

    public static Random rnd = new Random();
    ObservableCollection<string> list { get; set; } = new ObservableCollection<string>();
}

  

然後設置ListView的ItemSource="{x:Bind list}",然後我懶得新建個項目截圖了,大佬們自行測試一下吧。

下集預告:實現可以選中的BigbangView

UWP中實現大爆炸效果(一)