Um ScrollView numa StackLayout?
É comum colocar um StackLayout em um ScrollView, mas você pode colocar um ScrollView em um StackLayout? E por que você quer mesmo?
É uma regra geral em sistemas de layout como o do Xamarin.Forms que você não pode colocar uma rolagem de página em uma pilha. Um ScrollView precisa ter uma altura específica para calcular a diferença entre a altura do seu conteúdo e a sua própria altura. Essa diferença é o montante que o ScrollView pode rolar seus conteúdos. Se o ScrollView está em uma StackLayout, ele não recebe essa altura específica. O StackLayout quer que o ScrollView seja o mais curto possível, e isso é a altura do conteúdo do ScrollView ou zero, e nenhuma solução funciona.
Então, por que você quer um ScrollView em um StackLayout de qualquer maneira?
Às vezes é exatamente o que você precisa. Considere um leitor de e-book primitivo que implementa rolagem. Você pode querer uma label na parte superior da página exibindo sempre o título do livro, seguido por um ScrollView contendo uma StackLayout com o conteúdo do livro em si. Seria conveniente para esse label e para o ScrollView serem filhos de um StackLayout que preenche a página.
Com Xamarin.Forms, tal coisa é possível. Se você der a ScrollView um VerticalOptions definindo LayoutOptions.FillAndExpand, ele pode realmente ser um filho de um StackLayout. O StackLayout vai dar ao ScrollView todo o espaço extra não exigida pelos outros filhos, e a ScrollView terá, então, uma altura específica.
O projeto BlackCat exibe o texto de conto de Edgar Allan Poe "The Black Cat", que é armazenado em um arquivo de texto chamado TheBlackCat.txt em um formato de uma linha-por-parágrafo.
Como o programa BlackCat acessa o arquivo com este conto? Às vezes é conveniente incorporar arquivos que um aplicativo requer autorização no executável do programa ou - em caso de uma aplicação Xamarin.Forms - autorização direto na biblioteca DLL de Classes Portátil. Esses arquivos são conhecidos como recursos incorporados, e é isso que o arquivo TheBlackCat.txt é neste programa.
Para fazer um recurso incorporado no Visual Studio ou no Xamarin Studio, você provavelmente vai querer primeiro criar uma pasta no projeto, selecionando a opção Add > New Folder no menu projeto. A pasta para os arquivos de texto pode ser chamada de Textos, por exemplo. A pasta é opcional, mas ajuda a organizar ativos do programa. Então, para essa pasta, você pode selecionar o Add> Existing Item no Visual Studio ou Add > Add Files no Xamarin Studio. Navegue até o arquivo, selecione-o e clique em Add no Visual Studio ou Open em Xamarin Studio.
Agora aqui é a parte mais importante: Uma vez que o arquivo é parte do projeto, abra o diálogo a partir do menu associado com o arquivo e vá em Propriedades. Especifique que a Build Action para o arquivo é EmbeddedResource. Este é um passo fácil de esquecer, mas é essencial.
Isso foi feito para o projeto BlackCat, e, consequentemente, o arquivo TheBlackCat.txt fica embutido no arquivo BlackCat.dll.
No código, o arquivo pode ser recuperado chamando o método GetManifestResourceStream definido pela classe Assembly no namespace System.Reflection. Para chegar a assembly do PCL, tudo que você precisa fazer é obter o tipo de qualquer classe definida na assembly. Você pode usar typeof com o tipo de página derivada da ContentPage ou GetType na instância dessa classe. Em seguida, deve-se chamar GetTypeInfo neste objeto Type. Assembly é uma propriedade resultante do objeto TypeInfo:
No método GetManifestResourceStream da Assembly, você precisa especificar o nome do recurso. Para recursos incorporados, esse nome não é o filename do recurso, mas a resource ID. É fácil confundir estes porque que ID pode parecer vagamente como um nome de arquivo totalmente qualificado.
O resource ID começa com o namespace padrão do assembly. Este não é o namespace .NET! Para obter o namespace padrão do assembly no Visual Studio, selecione Properties do projeto no menu, e na caixa de diálogo Propriedades, selecione Library no lado esquerdo e veja o campo Default Namespace. Em Xamarin Studio, selecione Options no menu projeto e na caixa de diálogo Project Options, selecione Main Settings à esquerda, e veja um campo denominado Default Namespace.
Para o projeto BlackCat, o namespace padrão é o mesmo que o assembly: "BlackCat". No entanto, você pode redefinir o namespace padrão para o nome que quiser.
O resource ID começa com que há no namespace padrão, seguido por um período, seguido pelo nome da pasta que você pode ter usado, seguido por outro período e o nome do arquivo. Para este exemplo, o resource ID é "BlackCat.Texts.TheBlackCat.txt" - e isso é o que você verá passando para o método GetManifestResourceStream no código. O método retorna um objeto .NET Stream, e a partir desse, um StreamReader pode ser criado para ler as linhas de texto.
É uma boa idéia usar declarações using com o objeto Stream retornado de GetManifestResourceStream e o objeto StreamReader, porque isso irá descartar corretamente os objetos quando eles não forem mais necessários ou se causarem exceções.
Para fins de layout, o construtor BlackCatPage cria dois objetos StackLayout: mainStack e textStack. A primeira linha do arquivo (contendo título e autor da história) se torna um label em mainStack em negrito e centralizado; todas as linhas subsequentes ficarão em textStack. A instância mainStack também contém um ScrollView com textStack.
Observe que o ScrollView tem sua propriedade VerticalOptions definida para LayoutOptions.FillAndExpand. Sem isso, este programa não vai funcionar. Com ele, o texto é rolável enquanto o título permanece no lugar.
Pelo fato deste ser basicamente um leitor de e-book, e os seres humanos leem o texto preto em papel branco por centenas de anos, o BackgroundColor da página é definido como branco e o TextColor de cada label está definido para preto:

BlackCat é uma aplicação PCL. Também é possível escrever este programa usando um projeto de ativos compartilhados em vez de um PCL, e incluído com o código para este capítulo está BlackCatSap. No entanto, se você colocar um recurso incorporado em um SAP, o nome da pasta não é parte do resource ID. Ele será basicamente ignorado. Além disso, pelo fato do recurso tornar-se realmente parte do projeto de aplicativo, você irá precisar do namespace padrão para a aplicação, e isso é diferente para cada plataforma. O código para definir a variável de recurso parece com esse:
Se você estiver tendo problemas fazendo referência a um recurso incorporado, você pode estar usando um nome incorreto. Tente chamar GetManifestResourceNames no objeto Assembly para obter uma lista dos resource IDs de todos os recursos incorporados.