Lidando com imagens e mudanças de temas no windows phone
Estou no meio de um update para meu jogo Caça-Palavras. Uma das funcionalidades que estou adicionando é a capacidade de rotacionar o grid de letras para uma melhor visão de possíveis palavras.
Para isso, coloquei um botão com uma flecha branca na parte de baixo da tela, mas de cara já lembrei de um problema:
E se o usuário estiver utilizando o tema claro? A flecha branca com certeza iria “sumir” no fundo branco, impedindo a aplicação de ser aprovada no marketplace.
Bom, vamos as soluções:
Solução 1: Utilize 2 imagens e deixe a do tema não usado invisível:
O próprio framework nos dá a possibilidade de saber se um determinado tema está sendo usado ou não. Podemos tirar proveito disso e fazer um bind com essas propriedades em 2 imagens.
[xml]
<StackPanel>
<Image Visibility=”{StaticResource PhoneLightThemeVisibility}”
Source=”images/imageDarkTheme.png” />
<Image Visibility=”{StaticResource PhoneDarkThemeVisibility}”
Source=”images/imageLightTheme.png” />
</StackPanel>
[/xml]
Solução 2: Usando uma OpacityMask:
A OpacityMask é uma imagem extra que você utiliza como máscara para determinar quais pixels serão visíveis na imagem original. Tudo que importa nela é o canal Alpha, sua informação de cores é ignorada.
Desta forma, você pode utilizar uma OpacityMask para esconder a parte branca de sua imagem quando o tema é claro (resultando em uma imagem escura) e vice-versa quando o tema é escuro.
O código fica mais ou menos assim:
[xml]
<Rectangle Fill=”#FFAAAAAA” Height=”50″ Width=”50″>
<Rectangle.OpacityMask>
<ImageBrush Stretch=”Fill” ImageSource=”images/myImage.png”/>
</Rectangle.OpacityMask>
</Rectangle>
[/xml]
Solução 3: Criando um custom control
Particularmente eu prefiro a solução 1 a 2, mas acho que podemos simplificar bastante o processo criando um user control para fazer esta tarefa.
Primeiro, crie um novo controle e nomeie-o ThemableImage. No xaml, apenas adicione um controle de imagem.
[xml]
<UserControl x:Class=”CacaPalavras.Controls.ThemableImage”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″
xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006″
mc:Ignorable=”d”
x:Name=”ImageControl”>
<Image x:Name=”Image” />
</UserControl>
[/xml]
No code-behind, vamos adicionar 2 dependecy properties:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
public partial class ThemableImage : UserControl { public ThemableImage() { InitializeComponent(); } public ImageSource SourceWhenLight { get { return (ImageSource) GetValue(SourceWhenLightProperty); } set { SetValue(SourceWhenLightProperty, value); } } public static readonly DependencyProperty SourceWhenLightProperty = DependencyProperty.Register("SourceWhenLight", typeof (ImageSource), typeof (ThemableImage), new PropertyMetadata(null, OnSourceChanged)); private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((ThemableImage) d).Refresh(); } public ImageSource SourceWhenDark { get { return (ImageSource) GetValue(SourceWhenDarkProperty); } set { SetValue(SourceWhenDarkProperty, value); } } public static readonly DependencyProperty SourceWhenDarkProperty = DependencyProperty.Register("SourceWhenDark", typeof (ImageSource), typeof (ThemableImage), new PropertyMetadata(null, OnSourceChanged)); public void Refresh() { ImageSource source = IsDarkTheme() ? SourceWhenDark : SourceWhenLight; if(source != null) { Image.Source = source; } } private bool IsDarkTheme() { if (DesignerProperties.IsInDesignTool) { return true; } return (Visibility) Resources["PhoneDarkThemeVisibility"] == Visibility.Visible; } } |
E para utilizar o controle, basta fazer assim:
[xml]
<Controls:ThemableImage
SourceWhenLight=”/Content/image_light.png”
SourceWhenDark=”/Content/image_dark.png”
/>
[/xml]
Espero que isso ajude. Happy coding :)