Carregar imagens e ativos personalizados para escala, tema, alto contraste e outros

Seu aplicativo pode carregar arquivos de recurso de imagem (ou outros arquivos de ativo) personalizados para fator de escala de exibição, tema, alto contraste e outros contextos de tempo de execução. Essas imagens podem ser referenciadas a partir de código imperativo ou de marcação XAML, por exemplo, como a propriedade Source de uma imagem. Eles também podem aparecer no arquivo de origem do manifesto do pacote do aplicativo (o Package.appxmanifest arquivo), por exemplo, como o valor do Ícone do Aplicativo na guia Ativos Visuais do Designer de Manifesto do Visual Studio, ou em seus blocos e notificações do sistema. Usando qualificadores nos nomes de arquivo de suas imagens e, opcionalmente, carregando-os dinamicamente com a ajuda de um ResourceContext, você pode fazer com que seja carregado o arquivo de imagem mais apropriado que melhor corresponda às configurações de tempo de execução do usuário para escala de exibição, tema, alto contraste, idioma e outros contextos.

Um recurso de imagem está contido em um arquivo de recurso de imagem. Você também pode pensar na imagem como um ativo e no arquivo que a contém como um arquivo de ativo; e você pode encontrar esses tipos de arquivos de recursos na pasta \Assets do seu projeto. Para obter informações sobre como usar qualificadores nos nomes de seus arquivos de recurso de imagem, consulte Personalizar seus recursos para idioma, escala e outros qualificadores.

Alguns qualificadores comuns para imagens são:

Qualificar um recurso de imagem para escala, tema e contraste

O valor padrão para o scale qualificador é scale-100. Portanto, essas duas variantes são equivalentes (ambas fornecem uma imagem na escala 100 ou fator de escala 1).

\Assets\Images\logo.png
\Assets\Images\logo.scale-100.png

Você pode usar qualificadores em nomes de pastas em vez de nomes de arquivos. Essa é uma estratégia melhor quando você tem vários arquivos de ativos por qualificador. Para fins de ilustração, essas duas variantes são equivalentes às duas acima.

\Assets\Images\logo.png
\Assets\Images\scale-100\logo.png

O exemplo a seguir mostra como você pode fornecer variantes de um recurso de imagem, chamado /Assets/Images/logo.png—para diferentes configurações de escala de exibição, tema e alto contraste. Este exemplo usa nomenclatura de pasta.

\Assets\Images\contrast-standard\theme-dark
    \scale-100\logo.png
    \scale-200\logo.png
\Assets\Images\contrast-standard\theme-light
    \scale-100\logo.png
    \scale-200\logo.png
\Assets\Images\contrast-high
    \scale-100\logo.png
    \scale-200\logo.png

Fazer referência a uma imagem ou outro ativo da marcação e do código XAML

O nome — ou identificador — de um recurso de imagem é seu caminho e nome de arquivo com todo e qualquer qualificador removido. Se você nomear pastas e/ou arquivos como em qualquer um dos exemplos da seção anterior, terá um único recurso de imagem e seu nome (como um caminho absoluto) será /Assets/Images/logo.png. Veja como você usa esse nome na marcação XAML.

<Image x:Name="myXAMLImageElement" Source="ms-appx:///Assets/Images/logo.png"/>

Observe que você usa o ms-appx esquema de URI porque está se referindo a um arquivo que vem do pacote do seu aplicativo. Consulte Esquemas de URI na documentação da UWP. É assim que você se refere ao mesmo recurso de imagem no código imperativo.

this.myXAMLImageElement.Source = new BitmapImage(new Uri("ms-appx:///Assets/Images/logo.png"));

Você pode usar ms-appx para carregar qualquer arquivo arbitrário do pacote do aplicativo.

var uri = new System.Uri("ms-appx:///Assets/anyAsset.ext");
var storagefile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(uri);

O ms-appx-web esquema acessa os mesmos arquivos que ms-appxo , mas no compartimento da Web.

<WebView x:Name="myXAMLWebViewElement" Source="ms-appx-web:///Pages/default.html"/>
this.myXAMLWebViewElement.Source = new Uri("ms-appx-web:///Pages/default.html");

Para qualquer um dos cenários mostrados nesses exemplos, use a sobrecarga do construtor Uri que infere o UriKind. Especifique um URI absoluto válido, incluindo o esquema e a autoridade, ou apenas deixe a autoridade usar o pacote do aplicativo como padrão, como no exemplo acima.

Observe como nesses URIs de exemplo o esquema ("ms-appx" ou "ms-appx-web") é seguido por "://", que é seguido por um caminho absoluto. Em um caminho absoluto, o "/" inicial faz com que o caminho seja interpretado a partir da raiz do pacote.

Observação

Os ms-resource esquemas de URI (para recursos de cadeia de caracteres) e ms-appx(-web) (para imagens e outros ativos) executam a correspondência automática de qualificador para encontrar o recurso mais apropriado para o contexto atual. O ms-appdata esquema de URI (que é usado para carregar dados do aplicativo) não executa nenhuma correspondência automática, mas você pode responder ao conteúdo de ResourceContext.QualifierValues e carregar explicitamente os ativos apropriados dos dados do aplicativo usando o nome completo do arquivo físico no URI. Para obter informações sobre dados de aplicativos, consulte Armazenar e recuperar configurações e outros dados de aplicativos. Os esquemas de URI da Web (por exemplo, http, https, e ftp) também não executam a correspondência automática. Para obter informações sobre o que fazer nesse caso, consulte Hospedando e carregando imagens na nuvem.

Os caminhos absolutos são uma boa opção se os arquivos de imagem permanecerem onde estão na estrutura do projeto. Se você quiser mover um arquivo de imagem, mas tiver cuidado para que ele permaneça no mesmo local em relação ao arquivo de marcação XAML de referência, em vez de um caminho absoluto, talvez você queira usar um caminho relativo ao arquivo de marcação que o contém. Se você fizer isso, não precisará usar um esquema de URI. Você ainda se beneficiará da correspondência automática de qualificador nesse caso, mas apenas porque está usando o caminho relativo na marcação XAML.

<Image Source="Assets/Images/logo.png"/>

Consulte também Suporte a blocos e notificações do sistema para idioma, escala e alto contraste.

Fazer referência a uma imagem ou outro ativo de uma biblioteca de classes

Você pode carregar imagens e outros recursos de um projeto de biblioteca de classes referenciado (WinUI 3 na área de trabalho) referenciando o recurso em um URI que usa o ms-appx esquema. O URI deve incluir o nome do projeto da biblioteca de classes e o caminho para o recurso dentro do projeto da biblioteca de classes. Por exemplo, se você tiver um projeto de biblioteca de classes chamado MyClassLibrary que contém uma imagem nomeada logo.png em uma pasta chamada Assets, poderá fazer referência à imagem em seu projeto de aplicativo da seguinte forma:

<Image Source="ms-appx:///MyClassLibrary/Assets/logo.png"/>

Você usará esse mesmo formato de URI para fazer referência a recursos em uma biblioteca de classes da marcação XAML ou do código. Por exemplo, você pode usar o seguinte código para carregar a imagem da biblioteca de classes e colocá-la em um objeto StorageFile :

private async Task<DateTimeOffset> GetLogoCreatedDateAsync()
{
    Uri uri = new($"ms-appx:///MyClassLibrary/Assets/logo.png");
    Windows.Storage.StorageFile file =
        await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(uri);

    return file.DateCreated;
}

Observe que você pode fazer referência a imagens da biblioteca de classes do projeto do aplicativo e do próprio projeto da biblioteca de classes.

Qualificar um recurso de imagem para targetsize

Você pode usar os scale qualificadores e targetsize em diferentes variantes do mesmo recurso de imagem; mas não pode usá-los em uma única variante de um recurso. Além disso, você precisa definir pelo menos uma variante sem um targetsize qualificador. Essa variante deve definir um valor para scale, ou deixá-la padronizada para scale-100. Portanto, essas duas variantes do /Assets/Square44x44Logo.png recurso são válidas.

\Assets\Square44x44Logo.scale-200.png
\Assets\Square44x44Logo.targetsize-24.png

E essas duas variantes são válidas.

\Assets\Square44x44Logo.png // defaults to scale-100
\Assets\Square44x44Logo.targetsize-24.png

Mas esta variante não é válida.

\Assets\Square44x44Logo.scale-200_targetsize-24.png

Consulte um arquivo de imagem do manifesto do pacote do aplicativo

Se você nomear pastas e/ou arquivos como em qualquer um dos dois exemplos válidos na seção anterior, terá um único recurso de imagem de ícone de aplicativo e seu nome (como um caminho relativo) será Assets\Square44x44Logo.png. No manifesto do pacote do aplicativo, basta consultar o recurso pelo nome. Não há necessidade de usar nenhum esquema de URI.

Adicionar recurso, inglês

Isso é tudo o que você precisa fazer, e o sistema operacional executará a correspondência automática de qualificadores para encontrar o recurso mais apropriado para o contexto atual. Para obter uma lista de todos os itens no manifesto do pacote do aplicativo que você pode localizar ou qualificar dessa maneira, consulte Itens de manifesto localizáveis.

Qualificar um recurso de imagem para layoutdirection

Consulte Espelhamento de imagens.

Carregar uma imagem para um idioma específico ou outro contexto

Para obter mais informações sobre a proposta de valor de localização do aplicativo, consulte Globalização e localização.

O ResourceContext padrão contém um valor de qualificador para cada nome de qualificador, representando o contexto de tempo de execução padrão (em outras palavras, as configurações para o usuário e o computador atuais). Os arquivos de imagem são comparados, com base nos qualificadores em seus nomes, com os valores do qualificador nesse contexto de tempo de execução.

Mas pode haver momentos em que você deseja que seu aplicativo substitua as configurações do sistema e seja explícito sobre o idioma, a escala ou outro valor de qualificador a ser usado ao procurar uma imagem correspondente para carregar. Por exemplo, talvez você queira controlar exatamente quando e quais imagens de alto contraste são carregadas.

Você pode fazer isso construindo um novo ResourceContext (em vez de usar o padrão), substituindo seus valores e, em seguida, usando esse objeto de contexto em suas pesquisas de imagem ResourceMap com GetValue ou TryGetValue.

var resourceManager = new Microsoft.Windows.ApplicationModel.Resources.ResourceManager();
var resourceContext = resourceManager.CreateResourceContext();
resourceContext.QualifierValues["Contrast"] = "high";
var resourceMap = resourceManager.MainResourceMap;
var namedResource = resourceMap.TryGetValue(@"Files/Assets/Logo.png", resourceContext);
var imageFileBytes = namedResource.ValueAsBytes;

using (var ms = new InMemoryRandomAccessStream())
{
    using (var writer = new DataWriter(ms.GetOutputStreamAt(0)))
    {
        writer.WriteBytes(imageFileBytes);
        writer.StoreAsync().GetResults();
    }
    var image = new BitmapImage();
    image.SetSource(ms);
    this.myXAMLImageElement.Source = image;
}

Por padrão, a classe ResourceManager usa o ResourceContext padrão.

APIs importantes

As seguintes APIs são importantes de entender ao trabalhar com recursos de imagem: