Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4114893
  • 博文数量: 855
  • 博客积分: 17977
  • 博客等级: 上将
  • 技术积分: 8236
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-26 09:59
  • 认证徽章:
个人简介

一个好老好老的老程序员了。

文章分类

全部博文(855)

文章存档

2019年(12)

2018年(88)

2017年(130)

2015年(5)

2014年(12)

2013年(41)

2012年(36)

2011年(272)

2010年(1)

2009年(53)

2008年(65)

2007年(47)

2006年(81)

2005年(12)

分类: Android平台

2018-07-08 15:46:13

自定义基于XAML的视图

上一章中的ScaryColorList程序使用Frame,BoxView和Label在StackLayout中列出了一些颜色。即使只有三种颜色,重复标记也开始变得非常不祥。遗憾的是,没有XAML标记复制C#for和while循环,因此您可以选择使用代码生成多个类似的项目,或者在标记中找到更好的方法。
在本书中,您将看到几种在XAML中列出颜色的方法,最终,一种非常干净和优雅的方式来完成这项工作将变得清晰。但这需要更多的步骤来学习Xamarin.Forms。在此之前,我们将研究一些您可能会在类似情况下发现有用的其他方法。
一种策略是创建一个自定义视图,其唯一目的是显示带有名称和彩色框的颜色。当我们在它的时候,让我们也显示颜色的十六进制RGB值。然后,您可以在XAML页面文件中将该自定义视图用于各个颜色。
在XAML中,对这样的自定义视图的引用可能是什么样的?
或者更好的问题是:你想看它怎么样?
如果标记看起来像这样,那么重复一点也不差,并且比在代码中明确定义Color值数组更糟糕:

点击(此处)折叠或打开

  1. <StackLayout>
  2.     <MyColorView Color="Red" />
  3.     <MyColorView Color="Green" />
  4.     <MyColorView Color="Blue" />
  5.  …
  6. </StackLayout>

嗯,实际上,它看起来不会那样。 MyColorView显然是一个自定义类,不是Xamarin.Forms API的一部分。 因此,如果没有XML名称空间声明中定义的名称空间前缀,它就不会出现在XAML文件中。
应用此XML前缀后,对于此自定义视图是Xamarin.Forms API的一部分不会有任何混淆,所以让我们给它一个更加尊严的ColorView名称而不是MyColorView。
这个假设的ColorView类是一个相当简单的自定义视图的示例,因为它仅包含使用StackLayout以特定方式排列的现有视图(特别是Label,Frame和BoxView)。 Xamarin.Forms定义了一个专门用于为这种视图排列提供父母的视图,它被称为ContentView。与ContentPage类似,ContentView具有一个Con?tent属性,您可以将其设置为其他视图的可视树。您可以在代码中定义Con?tentView的内容,但在XAML中执行它更有趣。
让我们整理一个名为ColorViewList的解决方案。此解决方案将具有两组XAML和代码隐藏文件,第一个用于名为ColorViewListPage的类,它派生自ContentPage(通常),第二个用于派生自ContentView的名为ColorView的类。
要在Visual Studio中创建ColorView类,请使用与向ColorViewList项目添加新XAML页面时相同的过程:在解决方案资源管理器中右键单击项目名称,然后从上下文菜单中选择“添加”>“新建项”。在Add New Item对话框中,选择左侧的Visual C#> Cross-Platform,然后选择Forms Xaml Page。输入名称ColorView.cs。但是,在您忘记之前,立即进入ColorView.xaml文件并将ContentPage开始和结束标记更改为ContentView。在ColorView.xaml.cs文件中,将基类更改为ContentView。
在Xamarin Studio中,这个过程稍微容易一些。从ColorViewList项目的工具菜单中,选择“添加”>“新建文件”。在“新建文件”对话框中,选择左侧的“表单”和“表单ContentView Xaml”(不是“表单ContentPage Xaml”)。给它一个ColorView的名字。
您还需要像往常一样为ColorViewListPage类创建XAML文件和代码隐藏文件。
ColorView.xaml文件描述了各个颜色项的布局,但没有任何实际颜色值。相反,BoxView和两个Label视图的名称是:

点击(此处)折叠或打开

  1. <ContentView xmlns="http://xamarin.com/schemas/2014/forms"
  2.              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  3.              x:Class="ColorViewList.ColorView">
  4.     <Frame OutlineColor="Accent">
  5.         <StackLayout Orientation="Horizontal">
  6.             <BoxView x:Name="boxView"
  7.                      WidthRequest="70"
  8.                      HeightRequest="70" />
  9.             <StackLayout>
  10.                 <Label x:Name="colorNameLabel"
  11.                        FontSize="Large"
  12.                        VerticalOptions="CenterAndExpand" />
  13.  
  14.                 <Label x:Name="colorValueLabel"
  15.                        VerticalOptions="CenterAndExpand" />
  16.             </StackLayout>
  17.         </StackLayout>
  18.     </Frame>
  19. </ContentView>

在现实生活中,您将有足够的时间来微调视觉效果。最初,您只想在那里获取所有命名视图。
除了视觉效果,此ColorView类还需要一个新属性来设置颜色。必须在代码隐藏文件中定义此属性。首先,为ColorView提供一个名为Color of Color的属性似乎是合理的(因为MyColorView的早期XAML片段似乎暗示)。但ColorView类需要显示颜色名称,并且无法从Color值中获取颜色名称。
相反,定义名为ColorName的类型为string的属性更有意义。然后,代码?后面的文件可以使用反射来获取与该名称对应的Color类的静态字段。
但是等待:Xamarin.Forms包含一个公共ColorTypeConverter类,XAML解析器使用该类将“Red”或“Blue”等文本颜色名称转换为Color值。为什么不利用这个呢?
这是ColorView的代码隐藏文件。它定义了一个带有set访问器的ColorName属性,该属性将colorNameLabel的Text属性设置为颜色名称,然后使用ColorType?Converter将名称转换为Color值。然后使用此Color值将boxView的Color属性和colorValueLabel的Text属性设置为RGB值:

点击(此处)折叠或打开

  1. public partial class ColorView : ContentView
  2. {
  3.     string colorName;
  4.     ColorTypeConverter colorTypeConv = new ColorTypeConverter();
  5.     public ColorView()
  6.     {
  7.         InitializeComponent();
  8.     }
  9.     public string ColorName
  10.     {
  11.         set
  12.         {
  13.             // Set the name.
  14.             colorName = value;
  15.             colorNameLabel.Text = value;
  16.             // Get the actual Color and set the other views.
  17.             Color color = (Color)colorTypeConv.ConvertFrom(colorName);
  18.             boxView.Color = color;
  19.             colorValueLabel.Text = String.Format("{0:X2}-{1:X2}-{2:X2}",
  20.                                                  (int)(255 * color.R),
  21.                                                  (int)(255 * color.G),
  22.                                                  (int)(255 * color.B));
  23.         }
  24.         get
  25.         {
  26.             return colorName;
  27.         }
  28.     }
  29. }

ColorView类已完成。 现在让我们看一下ColorViewListPage。 ColorViewList?Page.xaml文件必须列出多个ColorView实例,因此它需要一个带有新名称空间前缀的新XML名称空间声明来引用ColorView元素。
ColorView类与ColorViewListPage属于同一个项目。 通常,程序员在这种情况下使用本地的XML名称空间前缀。 新的名称空间声明出现在XAML文件的根元素中(与其他两个一样),格式如下:

点击(此处)折叠或打开

  1. xmlns:local="clr-namespace:ColorViewList;assembly=ColorViewList"

在一般情况下,XAML的自定义XML名称空间声明必须指定公共语言运行时(CLR)名称空间(也称为.NET名称空间)和程序集。指定这些的关键字是clr-namespace和assembly。通常,CLR命名空间与组件相同,就像它们在这种情况下一样,但它们不需要。这两部分用分号连接。
请注意,冒号跟在clr-namespace之后,但是在程序集之后有一个等号。这种明显的不一致是有意的:名称空间声明的格式旨在模仿传统名称空间声明中的URI,其中冒号遵循URI方案名称。
您使用相同的语法来引用外部可移植类库中的对象。在这些情况下唯一不同的是项目还需要参考外部PCL。 (您将在第10章“XAML标记扩展”中看到一个考试。)。
本地前缀对于同一程序集中的代码是通用的,在这种情况下,不需要组装部件:

点击(此处)折叠或打开

  1. xmlns:local="clr-namespace:ColorViewList"

对于PCL中的XAML文件,如果需要,可以包括装配部件以引用与?装配相同的内容,但不是必需的。 但是,对于SAP中的XAML文件,您不得包含程序集部件以引用本地类,因为没有与SAP关联的程序集。 SAP中的代码实际上是各个平台程序集的一部分,并且这些代码都具有不同的名称。
这是ColorViewListPage类的XAML。 代码隐藏文件除了InitializeComponent调用之外什么都不包含:

点击(此处)折叠或打开

  1. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
  2.              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  3.              xmlns:local="clr-namespace:ColorViewList"
  4.              x:Class="ColorViewList.ColorViewListPage">
  5.     <ContentPage.Padding>
  6.         <OnPlatform x:TypeArguments="Thickness"
  7.                     iOS="0, 20, 0, 0" />
  8.     </ContentPage.Padding>
  9.     <ScrollView>
  10.         <StackLayout Padding="6, 0">
  11.              <local:ColorView ColorName="Aqua" />
  12.              <local:ColorView ColorName="Black" />
  13.              <local:ColorView ColorName="Blue" />
  14.              <local:ColorView ColorName="Fuchsia" />
  15.              <local:ColorView ColorName="Gray" />
  16.              <local:ColorView ColorName="Green" />
  17.              <local:ColorView ColorName="Lime" />
  18.              <local:ColorView ColorName="Maroon" />
  19.              <local:ColorView ColorName="Navy" />
  20.              <local:ColorView ColorName="Olive" />
  21.              <local:ColorView ColorName="Purple" />
  22.              <local:ColorView ColorName="Pink" />
  23.              <local:ColorView ColorName="Red" />
  24.              <local:ColorView ColorName="Silver" />
  25.              <local:ColorView ColorName="Teal" />
  26.              <local:ColorView ColorName="White" />
  27.              <local:ColorView ColorName="Yellow" />
  28.         </StackLayout>
  29.     </ScrollView>
  30. </ContentPage>

这并不像前面的例子所暗示的那样令人厌恶,它演示了如何将视觉效果封装在他们自己的基于XAML的类中。 请注意,StackLayout是ScrollView的子项,因此可以滚动列表:

但是,ColorViewList项目的一个方面不符合“最佳实践”。它是ColorView中ColorName属性的定义。 这应该实现为BindableProperty对象。 深入研究可绑定对象和可绑定属性是一个高优先级,将在第11章“可绑定基础结构”中进行探讨。

阅读(1245) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册