Até agora, discutimos apenas como implementar o comportamento do aplicativo, mas não sua aparência. Neste capítulo, vamos nos concentrar nesse tópico.
Estrutura e noções básicas de layout
Assim como o fluxo de trabalho, o layout do seu aplicativo também é definido em XML. Os layouts consistem em um LayoutPage
que define um quadro reutilizável para várias telas e um LayoutModel
que é usado para projetar as especificidades de uma tela específica. Além disso, podemos definir o estilo
a ser aplicado a vários elementos de layout e o PartTemplate
, que torna reutilizáveis partes específicas do layout.
Todos esses elementos estruturais são definidos em seus arquivos separados. Obviamente, eles ainda precisam ser preenchidos com conteúdo como texto, botões ou imagens. Você pode dar uma olhada na lista de elementos da interface do usuário para ter uma visão geral.
A página de layout do nosso componente "Choice" inclui apenas a barra de status, um título e uma seção de conteúdo usando a tag <ContentPlaceHolder>
, que será preenchida pelo "LayoutModel".
<LayoutPage Name="DefaultMaster">
<Part Template="STATUS_BAR" Weight="0.1"/>
<Text Name="Topic" Weight=".15" Style="TitleStyle" Content="Pick a fruit"/>
<Panel Weight="0.75">
<ContentPlaceHolder Name="Content"/>
</Panel>
</LayoutPage>
O "LayoutModel" tem a seguinte aparência:
<LayoutModel Name="ChoiceScreen" Page="DefaultMaster" Orientation="Vertical">
<Content PlaceHolder="Content" Weight="1" Orientation="Horizontal">
<Button Name="Apple" FocusOrder="0" Weight="0.5" Style="ImageButtonStyle">
<Text Name="LEFT_TEXT" Style="FooterButtonTextStyle" Weight="1" MaxSize="30" Content="Apple"/>
<Events/>
</Button>
<Button Name="Pear" FocusOrder="1" Weight="0.5" Style="ImageButtonStyle">
<Text Name="RIGHT_TEXT" Style="FooterButtonTextStyle" Weight="1" MaxSize="30" Content="Pear"/>
<Events/>
</Button>
</Content>
</LayoutModel>
"LayoutModel" é o elemento que conectamos ao fluxo de trabalho. Isso é feito ao definir uma etapa do fluxo de trabalho: <step id="choose" descriptor="the user selects between two options" uitemplate="ChoiceScreen">.
Como você pode ver acima, o "LayoutModel" se refere à Page="DefaultMaster
para obter seu quadro externo. A partir da "LayoutPage", ele faz referência ao <ContentPlaceHolder Name="Content
"/> usando <Content PlaceHolder="Content"....
Dimensionamento e orientação
Dependendo do tipo de elemento da interface do usuário, é possível usar uma série de atributos para estilizar a interface do usuário a seu gosto. Os dois atributos que você deve observar primeiro são peso
e orientação
, pois eles ajudam a projetar a estrutura geral da interface do usuário.
O peso
define o tamanho de um elemento em um intervalo entre 0 e 1, em que 1 é 100% do tamanho do elemento pai.A orientação
é aplicada a um elemento pai e determina se os elementos filhos estão na horizontal
(um ao lado do outro) ou na vertical
(um em cima do outro) dentro do elemento pai.
Em nosso "LayoutModel" acima, o elemento Content
tem orientação horizontal
, portanto os botões serão exibidos um ao lado do outro. Cada um deles pode usar Weight="0.5"
(ou seja, 50%) do tamanho disponível para o elemento Content
. Os elementos de texto dentro dos botões, por outro lado, usam todo o espaço disponível para seu elemento pai (o botão) com Weight="1".
Muitas vezes, ao configurar o tamanho e a orientação de seus elementos, é útil usar os elementos Panel
. Esses elementos são puramente estruturais e podem ser usados para alterar facilmente a orientação em um elemento pai ou subdividir seu espaço.
Botões e ordem de foco
Ao trabalhar com botões, um atributo é especialmente importante: FocusOrder
. Esse atributo define a ordem em que os botões serão focalizados se você os percorrer usando botões de hardware. Ele também define qual botão será pré-selecionado, ou seja, o botão com FocusOrder="0".
Cada botão em seu layout precisa ter um FocusOrder
diferente. Mesmo que alguns botões estejam em um PartTemplate e, portanto, em um arquivo diferente, eles ainda precisam estar nessa ordem geral do seu layout.
Dicas e truques: O FocusOrder do seu layout precisa começar em 0 e ser sequencial, sem lacunas ou duplicatas. Se esse não for o caso, seu aplicativo provavelmente travará ao tentar carregar o layout. Se você já teve um travamento repentino do aplicativo durante o desenvolvimento, a verificação do FocusOrder deve vir imediatamente à sua mente.
Alterações no layout
O que está sendo mostrado ao usuário raramente é estático. Qualquer interação do usuário normalmente também resultará em alguma alteração na interface do usuário. Obviamente, não queremos criar um novo layout e uma nova etapa sempre que o conteúdo de um campo de texto for alterado. Há duas maneiras de adaptar a IU dinamicamente: criar um <mapping>
no fluxo de trabalho e usar a ação ui_update
.
Mapeamento
O mapeamento permite que você associe permanentemente um valor ou uma variável a um atributo de um elemento da interface do usuário. Se você mapear uma variável, o atributo do elemento da interface do usuário será automaticamente alterado sempre que o valor da variável for alterado.
<step ...>
<states>...</states>
<mapping>
<ui_element name="LEFT_TEXT">
<param name="content">#{left_option}</param>
<param name="text_color">#{option_color}</param>
</ui_element>
</mapping>
</step>
O exemplo acima mostra que o mapeamento é adicionado como um filho da tag step. Você pode adicionar qualquer número de tags ui_element aqui, o que faria referência a um elemento de IU do seu layout. Nesse caso, name="LEFT_TEXT
, o texto do botão representa nossa primeira opção. Sempre que a variável #{lef_option}
for alterada em seu fluxo de trabalho, a interface do usuário mostrará um texto diferente nesse botão.
A ação ui_update
Outra opção para fazer alterações dinâmicas em seu layout é a ação ui_update
. Essa ação executa uma alteração única no layout:
<ui_update id="change_left_button_text">
<widget_params>
<ui_element name="LEFT_TEXT">
<param name="content">#{left_option}</param>
<param name="text_color">#{option_color}</param>
</ui_element>
</widget_params>
</ui_update>
Na maioria dos casos de uso, é preferível apenas configurar um mapeamento em vez de usar essa ação. Há, no entanto, um caso de uso em que o mapeamento não funciona e você precisa usar a ação ui_update
:
O JavaScript dentro de um mapeamento só é executado uma vez, portanto, se você precisar usar JS e o valor for alterado durante o ciclo de vida da etapa, será necessário atualizar manualmente a interface do usuário usando a ação ui_update
.
É possível formatar os textos que são exibidos nos óculos inteligentes com tags.html
. Você pode adicionar a formatação a um modelo de interface do usuário, em um arquivo de layout ou a um componente ao criar um novo texto no código.
<Text Name="LEFT_TEXT" Style="FooterButtonTextStyle" Weight="1" MaxSize="30" Content="<h1>Red Apples taste the best</h1> green Apples<br>are not so <sub>tasty</sub>"/>
O resultado da formatação pode variar de acordo com o componente do Layout ao qual está atribuído e com a configuração do componente específico.
Consulte Formatação de texto na seção Referência do mecanismo de fluxo de trabalho.
Atribuição
Atribuição 1:
Até agora, escolhemos entre duas opções textuais. Agora, queremos adicionar imagens à mistura:
- Adicione um elemento Image UI aos botões.
- Adicione as imagens abaixo aos recursos de seu fluxo de trabalho (no editor avançado).
- Você pode simplesmente arrastar e soltar as imagens da lista de recursos no
atributo contentattribute
da tag de imagem.
Componente de download (pré-atribuição)
Ajuda e recursos
Faça o download das imagens de dois itens.
Solução
Abaixo está uma solução exemplar:
<Button Name="Apple" FocusOrder="0" Weight="0.5" Style="ImageButtonStyle">
<Image Name="LEFT_IMAGE" Weight="0.8" Margin="0,0,0,0" Content="§{apple.jpg}§" ScaleType="CenterCrop"/>
<Text Name="LEFT_TEXT" Style="FooterButtonTextStyle" Weight=".2" MaxSize="30" Content="Apple"/>
<Events/>
</Button>
<Button Name="Pear" FocusOrder="1" Weight="0.5" Style="ImageButtonStyle">
<Image Name="RIGHT_IMAGE" Weight="0.8" Margin="0,0,0,0" Content="§{pear.jpg}§" ScaleType="CenterCrop"/>
<Text Name="RIGHT_TEXT" Style="FooterButtonTextStyle" Weight=".2" MaxSize="30" Content="Pear"/>
<Events/>
</Button>
Componente de download (pós-atribuição)
Na próxima lição, você aprenderá como tornar o componente configurável para que ele realmente se torne reutilizável.