第四章:滚动堆栈(6)

2100阅读 0评论2018-03-22 renxiao2003
分类:Android平台

StackLayout中的ScrollView?
将StackLayout放在ScrollView中很常见,但是您可以将ScrollView放入StackLayout中吗? 为什么你还想要?
这是布局系统中的一个通用规则,就像Xamarin中的布局系统一样。您不能将滚动放入堆栈中。 ScrollView需要有一个特定的高度来计算它的内容高度和它自己的高度之间的差异。 这种差异是ScrollView可以滚动其内容的量。 如果ScrollView在StackLayout中,它不会得到该特定的高度。 StackLayout希望ScrollView越短越好,这就是ScrollView内容的高度或零,并且这两种解决方案都不起作用。
那么为什么你要在StackLayout中使用ScrollView呢?
有时恰恰是你需要的。考虑一个实现滚动的原始电子书阅读器。您可能需要页面顶部的Label始终显示书的标题,后面跟着一个包含带书本身内容的StackLayout的ScrollView。将Label和ScrollView作为填充页面的StackLayout的子元素会很方便。
有了Xamarin.Forms,这样的事情是可能的。如果您为ScrollView提供了LayoutOptions.FillAndExpand的VerticalOptions设置,它确实可以是StackLayout的子项。 StackLayout将为ScrollView提供其他子项不需要的所有额外空间,并且ScrollView将具有特定的高度。有趣的是,Xamarin.Forms可以防止VerticalOptions属性的其他设置,因此它适用于您设置的任何内容。
BlackCat项目显示Edgar Allan Poe的短篇小说“The Black Cat”的文本,该短篇故事以一行一行的格式存储在名为TheBlackCat.txt的文本文件中。
BlackCat程序如何通过这个简短故事访问文件?也许最简单的方法是将文本文件嵌入到可执行程序中,或者在Xamarin.Forms应用程序的情况下,直接嵌入到可移植类库DLL中。这些文件被称为嵌入式资源,这就是TheBlackCat.txt文件在这个程序中。
要在Visual Studio或Xamarin Studio中创建嵌入式资源,您可能首先需要通过从项目菜单中选择添加>新建文件夹选项来在项目中创建一个文件夹。例如,文本文件的文件夹可能被称为文本。该文件夹是可选的,但它有助于组织程序资产。然后,在该文件夹中,您可以选择在Visual Studio中添加>现有项目或在Xamarin Studio中添加>添加文件。导航到该文件,选择它,然后单击在Visual Studio中添加或在Xamarin Studio中打开。
现在这是重要的部分:一旦文件是项目的一部分,从与文件关联的菜单调出属性对话框。指定该文件的Build Action为EmbeddedResource。这是一个容易忘记的步骤,但它是至关重要的。
这是为BlackCat项目完成的,因此TheBlackCat.txt文件将嵌入到BlackCat.dll文件中。
在代码中,可以通过调用System.Reflection命名空间中Assembly类定义的GetManifestResourceStream方法来检索文件。要获得PCL的组装,您需要做的就是获取组件中定义的任何类的类型。您可以使用typeof与您从该类的实例上的ContentPage或GetType派生的页面类型。然后在这个Type对象上调用GetTypeInfo。 Assembly是生成的TypeInfo对象的一个属性:


点击(此处)折叠或打开

  1. Assembly assembly = GetType().GetTypeInfo().Assembl

在Assembly的GetManifestResourceStream方法中,您需要指定资源的名称。对于嵌入式资源,该名称不是资源的文件名,而是资源ID。这很容易混淆,因为这个ID可能看起来像一个完全合格的文件名。
资源ID以程序集的默认名称空间开始。这不是.NET命名空间!要在Visual Studio中获取程序集的默认名称空间,请从项目菜单中选择属性,然后在属性对话框中,选择左侧的Library并查找Default namespace字段。在Xamarin Studio中,从项目菜单中选择选项,然后在项目选项对话框中,选择左侧的主设置,然后查找标有默认名称空间的字段。
对于BlackCat项目,该默认名称空间与程序集“BlackCat”相同。但是,实际上可以将该默认名称空间设置为任何所需的名称空间。
资源ID以默认名称空间开头,后跟句点,后跟您可能使用的文件夹名称,后跟另一个句点和文件名。在这个例子中,资源ID是“BlackCat.Texts.TheBlackCat.txt” - 这就是你要传递给代码中的GetManifestResourceStream方法。该方法返回一个.NET Stream对象,并从中可以创建StreamReader以读取文本行。
将Get语句与从GetManifestResourceStream和StreamReader对象返回的Stream对象一起使用是一个不错的主意,因为当对象不再需要或者它们引发异常时,它会正确处理对象。
出于布局的目的,BlackCatPage构造函数创建两个StackLayout对象:mainStack和textStack。文件的第一行(包含故事的标题和作者)在mainStack中成为粗体和居中标签;所有后续的行都在textStack中。 mainStack实例还包含一个带有textStack的ScrollView。


点击(此处)折叠或打开

  1. class BlackCatPage : ContentPage
  2. {
  3.  public BlackCatPage()
  4.  {
  5.  StackLayout mainStack = new StackLayout();
  6.  StackLayout textStack = new StackLayout
  7.  {
  8.  Padding = new Thickness(5),
  9.  Spacing = 10
  10.  };
  11.  // Get access to the text resource.
  12.  Assembly assembly = GetType().GetTypeInfo().Assembly;
  13.  string resource = "BlackCat.Texts.TheBlackCat.txt";
  14.  using (Stream stream = assembly.GetManifestResourceStream (resource))
  15.  {
  16.  using (StreamReader reader = new StreamReader (stream))
  17.  {
  18.  bool gotTitle = false;
  19.  string line;
  20.  // Read in a line (which is actually a paragraph).
  21.  while (null != (line = reader.ReadLine()))
  22.  {
  23.  Label label = new Label
  24.  {
  25.  Text = line,
  26.  // Black text for ebooks!
  27.  TextColor = Color.Black
  28.  };
  29.  if (!gotTitle)
  30. {
  31.  // Add first label (the title) to mainStack.
  32. label.HorizontalOptions = LayoutOptions.Center;
  33.  label.FontSize = Device.GetNamedSize(NamedSize.Medium, label);
  34.  label.FontAttributes = FontAttributes.Bold;
  35. mainStack.Children.Add(label);
  36. gotTitle = true;
  37.  }
  38.  else
  39. {
  40.  // Add subsequent labels to textStack.
  41. textStack.Children.Add(label);
  42.  }
  43.  }
  44.  }
  45.  }
  46.  // Put the textStack in a ScrollView with FillAndExpand.
  47.  ScrollView scrollView = new ScrollView
  48.  {
  49.  Content = textStack,
  50.  VerticalOptions = LayoutOptions.FillAndExpand,
  51.  Padding = new Thickness(5, 0),
  52.  };
  53.  // Add the ScrollView as a second child of mainStack.
  54.  mainStack.Children.Add(scrollView);
  55.  // Set page content to mainStack.
  56.  Content = mainStack;
  57.  // White background for ebooks!
  58.  BackgroundColor = Color.White;
  59.  
  60.  // Add some iOS padding for the page.
  61.  Padding = new Thickness (0, Device.OnPlatform (20, 0, 0), 0, 0);
  62.  }
  63. }

由于这基本上是一本电子书阅读器,人类几百年来一直在白纸上阅读黑色文本,所以页面的BackgroundColor被设置为白色,并且每个标签的TextColor被设置为黑色:


BlackCat是一个PCL应用程序。 也可以使用共享资产项目而不是PCL编写该程序。 为了证明这一点,本章的代码中包含了一个BlackCatSap项目。 但是,由于资源实际上已成为应用程序项目的一部分,因此您需要应用程序的默认名称空间,并且这对每个平台都是不同的。 设置资源变量的代码如下所示:

点击(此处)折叠或打开

  1. #if __IOS__
  2.  string resource = "BlackCatSap.iOS.Texts.TheBlackCat.txt";
  3. #elif __ANDROID__
  4.  string resource = "BlackCatSap.Droid.Texts.TheBlackCat.txt";
  5. #elif WINDOWS_UWP
  6.  string resource = "BlackCatSap.UWP.Texts.TheBlackCat.txt";
  7. #elif WINDOWS_APP
  8.  string resource = "BlackCatSap.Windows.Texts.TheBlackCat.txt";
  9. #elif WINDOWS_PHONE_APP
  10.  string resource = "BlackCatSap.WinPhone.Texts.TheBlackCat.txt";
  11. #endif

如果您在引用嵌入资源时遇到问题,则可能是使用了错误的名称。 尝试在Assembly对象上调用GetManifestResourceNames以获取所有嵌入式资源的资源ID列表。
上一篇:第四章:滚动堆栈(5)
下一篇:第五章:尺寸处理(1)