第十七章:掌握网格(三)
网格条形图
由Grid的Children集合定义的AddVertical和AddHorizontal方法可以一次性将整个视图集合添加到Grid。 默认情况下,新行或列的高度或宽度为“*”(星号),因此生成的Grid包含多个行或列,每个行或列的大小相同。
让我们使用AddHorizontal方法制作一个小条形图,其中包含50个具有随机高度的BoxView元素。 GridBarChart程序的XAML文件定义了一个AbsoluteLayout,它是Grid和Frame的父级。 此框架用作覆盖图,以显示条形图中特定条形图的信息。 它的Opacity设置为0,因此它最初是不可见的:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="GridBarChart.GridBarChartPage">
<AbsoluteLayout>
<!-- Grid occupying entire page. -->
<Grid x:Name="grid"
ColumnSpacing="1"
AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
AbsoluteLayout.LayoutFlags="All" />
<!-- Overlay in center of screen. -->
<Frame x:Name="overlay"
OutlineColor="Accent"
BackgroundColor="#404040"
Opacity="0"
AbsoluteLayout.LayoutBounds="0.5, 0.5, AutoSize, AutoSize"
AbsoluteLayout.LayoutFlags="PositionProportional">
<Label x:Name="label"
TextColor="White"
FontSize="Large" />
</Frame>
</AbsoluteLayout>
</ContentPage>
代码隐藏文件创建了50个BoxView元素,其随机HeightRequest属性介于0和300之间。此外,每个BoxView的StyleId属性都被赋予一个字符串,该字符串由交替的随机辅音和元音组成,类似于某个名称(可能是某个人) 来自另一个星球)。 所有这些BoxView元素都累积在一个通用的List集合中,然后添加到Grid中。 该作业是构造函数中的大部分代码:
public partial class GridBarChartPage : ContentPage
{
const int COUNT = 50;
Random random = new Random();
public GridBarChartPage()
{
InitializeComponent();
List<View> views = new List<View>();
TapGestureRecognizer tapGesture = new TapGestureRecognizer();
tapGesture.Tapped += OnBoxViewTapped;
// Create BoxView elements and add to List.
for (int i = 0; i < COUNT; i++)
{
BoxView boxView = new BoxView
{
Color = Color.Accent,
HeightRequest = 300 * random.NextDouble(),
VerticalOptions = LayoutOptions.End,
StyleId = RandomNameGenerator()
};
boxView.GestureRecognizers.Add(tapGesture);
views.Add(boxView);
}
// Add whole List of BoxView elements to Grid.
grid.Children.AddHorizontal(views);
// Start a timer at the frame rate.
Device.StartTimer(TimeSpan.FromMilliseconds(15), OnTimerTick);
}
// Arrays for Random Name Generator.
string[] vowels = { "a", "e", "i", "o", "u", "ai", "ei", "ie", "ou", "oo" };
string[] consonants = { "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "z" };
string RandomNameGenerator()
{
int numPieces = 1 + 2 * random.Next(1, 4);
StringBuilder name = new StringBuilder();
for (int i = 0; i < numPieces; i++)
{
name.Append(i % 2 == 0 ?
consonants[random.Next(consonants.Length)] :
vowels[random.Next(vowels.Length)]);
}
name[0] = Char.ToUpper(name[0]);
return name.ToString();
}
// Set text to overlay Label and make it visible.
void OnBoxViewTapped(object sender, EventArgs args)
{
BoxView boxView = (BoxView)sender;
label.Text = String.Format("The individual known as {0} " +
"has a height of {1} centimeters.",
boxView.StyleId, (int)boxView.HeightRequest);
overlay.Opacity = 1;
}
// Decrease visibility of overlay.
bool OnTimerTick()
{
overlay.Opacity = Math.Max(0, overlay.Opacity - 0.0025);
return true;
}
}
Children集合的AddHorizontal方法将多个BoxView元素添加到网格中,并为它们提供顺序的Grid.Column设置。 默认情况下,每列的宽度为“*”(星号),因此每个BoxView的宽度相同,而高度由HeightRequest设置控制。 在XAML文件中设置为网格的间距值1提供了条形图条形之间的一点间隔:
当您将手机侧向转动以增加宽度时,条形更明显:
此程序还有另一个功能:当您点击其中一个条形图时,覆盖图将变为可见并显示有关该条形图条的信息 - 特别是来自StyleId的行星际访客名称和条形图的高度。 但是构造函数中设置的计时器会不断降低叠加层上的不透明度值,因此此信息会逐渐淡出视图:
即使没有原生图形系统,Xamarin.Forms也能够显示看起来非常像图形的东西。