如果你像大多数程序员一样,只要看到上一章中的静态颜色属性列表,就想编写一个程序来显示它们,也许使用Label的Text属性来识别颜色,而TextColor属性显示实际的颜色。
尽管可以使用FormattedString对象通过单个Label实现此操作,但使用多个Label对象更容易。由于涉及多个Label对象,因此此作业还需要某种方法才能在屏幕上显示所有Label对象。
ContentPage类定义了一个View类型的Content属性,您可以将其设置为一个对象,但只能设置一个对象。显示多个视图需要将Content设置为可以有多个View类型的子类的实例。这样的类是Layout ,它定义了一个IList 类型的Children属性。
按照字母顺序,这四个类是:
AbsoluteLayout
Grid
RelativeLayout
StackLayout
他们每个人都以特有的方式安排子控件。 本章重点介绍StackLayout。
视图堆
StackLayout类将其子项排列在一个堆栈中。 它自己只定义了两个属性:
类型的方向StackOrientation,一个枚举与两个成员:垂直(默认)和水平。
类型double的间距,初始化为6。
StackLayout似乎是列表颜色的理想选择。 您可以使用由IList 定义的Add方法将子项添加到StackLayout实例的Children集合中。 这里有一些代码可以从两个数组中创建多个Label对象,然后将每个Label添加到StackLayout的Children集合中:
点击(此处)折叠或打开
Color[] colors =
{
Color.White, Color.Silver, Color.Gray, Color.Black, Color.Red,
Color.Maroon, Color.Yellow, Color.Olive, Color.Lime, Color.Green,
Color.Aqua, Color.Teal, Color.Blue, Color.Navy, Color.Pink,
Color.Fuchsia, Color.Purple
};
string[] colorNames =
{
"White", "Silver", "Gray", "Black", "Red",
"Maroon", "Yellow", "Olive", "Lime", "Green",
"Aqua", "Teal", "Blue", "Navy", "Pink",
"Fuchsia", "Purple"
};
StackLayout stackLayout = new StackLayout();
for (int i = 0; i < colors.Length; i++)
{
Label label = new Label
{
Text = colorNames[i],
TextColor = colors[i],
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
};
stackLayout.Children.Add(label);
}
然后可以将StackLayout对象设置为页面的Content属性。
但是使用并行阵列的技术相当危险。 如果他们不同步或有不同数量的元素呢? 一个更好的方法是将颜色和名称保持在一起,或许以Color和Name字段的小结构,或者作为Tuple 值的数组,或者作为匿名类型,如ColorLoop程序中所示:
点击(此处)折叠或打开
class ColorLoopPage : ContentPage
{
public ColorLoopPage()
{
var colors = new[]
{
new { value = Color.White, name = "White" },
new { value = Color.Silver, name = "Silver" },
new { value = Color.Gray, name = "Gray" },
new { value = Color.Black, name = "Black" },
new { value = Color.Red, name = "Red" },
new { value = Color.Maroon, name = "Maroon" },
new { value = Color.Yellow, name = "Yellow" },
new { value = Color.Olive, name = "Olive" },
new { value = Color.Lime, name = "Lime" },
new { value = Color.Green, name = "Green" },
new { value = Color.Aqua, name = "Aqua" },
new { value = Color.Teal, name = "Teal" },
new { value = Color.Blue, name = "Blue" },
new { value = Color.Navy, name = "Navy" },
new { value = Color.Pink, name = "Pink" },
new { value = Color.Fuchsia, name = "Fuchsia" },
new { value = Color.Purple, name = "Purple" }
};
StackLayout stackLayout = new StackLayout();
foreach (var color in colors)
{
stackLayout.Children.Add(
new Label
{
Text = color.name,
TextColor = color.value,
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
});
}
Padding = new Thickness(5, Device.OnPlatform(20, 5, 5), 5, 5);
Content = stackLayout;
}
}
或者你可以用一个显式的视图集合来初始化StackLayout的Children属性(类似于上一章中初始化的一个FormattedString对象的Spans集合)。 ColorList程序将页面的Content属性设置为StackLayout对象,然后使用17个Label视图初始化其Children属性:
点击(此处)折叠或打开
class ColorListPage : ContentPage
{
public ColorListPage()
{
Padding = new Thickness (5, Device.OnPlatform (20, 5, 5), 5, 5);
double fontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label));
Content = new StackLayout
{
Children =
{
new Label
{
Text = "White",
TextColor = Color.White,
FontSize = fontSize
},
new Label
{
Text = "Silver",
TextColor = Color.Silver,
FontSize = fontSize
},
new Label
{
Text = "Fuchsia",
TextColor = Color.Fuchsia,
FontSize = fontSize
},
new Label
{
Text = "Purple",
TextColor = Color.Purple,
FontSize = fontSize
}
}
};
}
}
你不需要看到所有17个孩子的代码来获得这个想法! 不管你如何填写儿童收藏,结果如下:
显然,这不是最佳的。 有些颜色根本看不到,有些颜色太淡,看不清楚。 而且,这个列表在两个平台上溢出了页面,而且没有办法将其向上滚动。
一种解决方法是减小文本大小。 而不是使用NamedSize.Large,请尝试其中一个较小的值。
另一个部分解决方案可以在StackLayout本身中找到:StackLayout定义了一个类型为double的Spacing属性,用于指示在子节点之间留出多少空间。 默认情况下,它是6.0,但您可以将其设置为较小(例如,零),以帮助确保所有项目都适合:
点击(此处)折叠或打开
Content = new StackLayout
{
Spacing = 0,
Children =
{
new Label
{
Text = "White",
TextColor = Color.White,
FontSize = fontSize
},
…
现在所有的Label视图只占用文本所需的垂直空间。 您甚至可以将间距设置为负值以使项目重叠!
但最好的解决方案是滚动。 StackLayout不自动支持滚动,并且必须添加另一个名为ScrollView的元素,如下一节所述。
但到目前为止显示的颜色程序还有一个问题:它们需要显式地创建一个颜色和名称数组,或者显式地为每个颜色创建Label视图。 对于程序员来说,这有点乏味,因此有点令人厌恶。 可能是自动的?