自从老罗搞出大爆炸之后,各家安卓都内置了类似功能。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>
后台代码:
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