Recursos no Android: strings, cores, dimensões, temas e internacionalização

Capítulo 4

Tempo estimado de leitura: 14 minutos

+ Exercício

Por que usar Resources (recursos) no Android

No Android, recursos são valores externos ao código (textos, cores, dimensões, estilos, temas etc.) armazenados em arquivos dentro de res/. Centralizar esses valores traz benefícios práticos: manutenção mais simples, consistência visual, suporte a múltiplos idiomas, adaptação automática a modo escuro e a diferentes tamanhos de tela.

Em vez de “hardcode” (texto direto no XML/Kotlin, cores em hexadecimal espalhadas, tamanhos repetidos), você define tudo em arquivos como strings.xml, colors.xml, dimens.xml e temas/estilos. Depois, referencia por @string/..., @color/..., @dimen/... e atributos de tema como ?attr/colorPrimary.

Organização recomendada para manutenção

  • res/values/strings.xml: textos padrão (idioma base).
  • res/values-pt-rBR/strings.xml e res/values-en/strings.xml: traduções.
  • res/values/colors.xml: paleta (se necessário) e cores utilitárias.
  • res/values/dimens.xml: espaçamentos, tamanhos de texto, raios, alturas.
  • res/values/themes.xml: tema claro.
  • res/values-night/themes.xml: tema escuro.
  • res/values-sw600dp/dimens.xml: dimensões para tablets (telas “smallest width” ≥ 600dp).

Dica de manutenção: prefira nomes semânticos (o “porquê”) em vez de nomes visuais (o “como”). Ex.: spacing_screen é melhor que padding_16 quando o objetivo é padronizar o espaçamento de tela.

Strings: textos centralizados, placeholders e plurals

1) Criando strings básicas

Em res/values/strings.xml:

<resources>    <string name="app_name">Meu App</string>    <string name="welcome_title">Bem-vindo</string>    <string name="welcome_subtitle">Vamos começar</string></resources>

Referenciando no XML:

Continue em nosso aplicativo e ...
  • Ouça o áudio com a tela desligada
  • Ganhe Certificado após a conclusão
  • + de 5000 cursos para você explorar!
ou continue lendo abaixo...
Download App

Baixar o aplicativo

<TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="@string/welcome_title" />

Referenciando no Kotlin:

val title = getString(R.string.welcome_title)

2) Placeholders (formatação com parâmetros)

Use placeholders para inserir valores dinâmicos sem concatenar strings no código (isso facilita tradução e evita erros de ordem de palavras).

Em strings.xml:

<resources>    <string name="greeting_user">Olá, %1$s!</string>    <string name="cart_total">Total: %1$.2f</string>    <string name="items_in_cart">Você tem %1$d itens no carrinho</string></resources>

No Kotlin:

val userName = "Ana"val greeting = getString(R.string.greeting_user, userName)val total = 123.5val totalText = getString(R.string.cart_total, total)val count = 3val countText = getString(R.string.items_in_cart, count)

Boas práticas: use índices (%1$s, %2$d) para permitir que tradutores mudem a ordem dos termos.

3) Plurals (singular/plural corretamente)

Para quantidades, use <plurals> em vez de “if/else” com strings separadas.

Em res/values/strings.xml:

<resources>    <plurals name="notifications_count">        <item quantity="one">%d notificação</item>        <item quantity="other">%d notificações</item>    </plurals></resources>

No Kotlin:

val count = 1val text = resources.getQuantityString(R.plurals.notifications_count, count, count)

Internacionalização (i18n) com pelo menos dois idiomas

1) Criando arquivos por idioma

Você terá um arquivo base em res/values/strings.xml (por exemplo, português) e outro em res/values-en/strings.xml (inglês). O Android escolhe automaticamente conforme o idioma do dispositivo.

Português (Brasil) em res/values-pt-rBR/strings.xml:

<resources>    <string name="welcome_title">Bem-vindo</string>    <string name="greeting_user">Olá, %1$s!</string>    <plurals name="notifications_count">        <item quantity="one">%d notificação</item>        <item quantity="other">%d notificações</item>    </plurals></resources>

Inglês em res/values-en/strings.xml:

<resources>    <string name="welcome_title">Welcome</string>    <string name="greeting_user">Hello, %1$s!</string>    <plurals name="notifications_count">        <item quantity="one">%d notification</item>        <item quantity="other">%d notifications</item>    </plurals></resources>

2) Cuidados comuns em i18n

  • Evite concatenar strings no Kotlin (ex.: "Olá, " + nome), pois a ordem pode mudar em outros idiomas.
  • Evite textos “embutidos” no layout. Use sempre @string/....
  • Para números e moeda, considere formatação local (ex.: NumberFormat) quando necessário; o placeholder sozinho não resolve separadores e símbolos.

Cores: colors.xml e uso correto com temas (Material Theming)

1) Definindo cores em colors.xml

Em res/values/colors.xml:

<resources>    <color name="brand_primary">#6750A4</color>    <color name="brand_secondary">#625B71</color>    <color name="success">#2E7D32</color>    <color name="danger">#C62828</color></resources>

Referenciando no XML (uso direto):

android:textColor="@color/brand_primary"

Referenciando no Kotlin:

val color = getColor(R.color.brand_primary)

Observação: em muitos casos, é melhor não usar a cor “direta”, e sim um atributo do tema (ex.: ?attr/colorPrimary) para que o app se adapte automaticamente ao modo escuro.

2) Preferindo atributos do tema (Material) em vez de cores fixas

Em componentes, prefira:

android:textColor="?attr/colorOnSurface"

Em vez de:

android:textColor="@color/brand_primary"

Isso melhora consistência e facilita dark theme, porque colorOnSurface muda conforme o tema.

Dimensões: dimens.xml para espaçamentos e tamanhos consistentes

1) Criando dimensões padrão

Em res/values/dimens.xml:

<resources>    <dimen name="spacing_xs">4dp</dimen>    <dimen name="spacing_sm">8dp</dimen>    <dimen name="spacing_md">16dp</dimen>    <dimen name="spacing_lg">24dp</dimen>    <dimen name="text_title">20sp</dimen>    <dimen name="text_body">16sp</dimen>    <dimen name="corner_md">12dp</dimen></resources>

No XML:

<TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:padding="@dimen/spacing_md"    android:textSize="@dimen/text_title" />

No Kotlin:

val paddingPx = resources.getDimensionPixelSize(R.dimen.spacing_md)

2) Qualifier para tablets: values-sw600dp

Para ajustar dimensões em telas maiores, crie res/values-sw600dp/dimens.xml com valores diferentes (mesmos nomes).

Exemplo em res/values-sw600dp/dimens.xml:

<resources>    <dimen name="spacing_md">24dp</dimen>    <dimen name="text_title">24sp</dimen></resources>

Sem mudar o layout, o Android aplicará automaticamente as dimensões de tablet quando a menor largura for ≥ 600dp.

Styles e Themes: aplicando Material Theming e evitando repetição

1) Styles para componentes

Styles são “pacotes” de atributos reutilizáveis. Úteis para padronizar TextViews, botões, etc.

Em res/values/styles.xml (ou dentro de themes.xml, dependendo da organização):

<resources>    <style name="TextAppearance.App.Title" parent="TextAppearance.Material3.TitleLarge">        <item name="android:textColor">?attr/colorOnSurface</item>    </style>    <style name="Widget.App.PrimaryButton" parent="Widget.Material3.Button">        <item name="cornerRadius">@dimen/corner_md</item>    </style></resources>

Aplicando no XML:

<TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    style="@style/TextAppearance.App.Title"    android:text="@string/welcome_title" />
<com.google.android.material.button.MaterialButton    android:layout_width="wrap_content"    android:layout_height="wrap_content"    style="@style/Widget.App.PrimaryButton"    android:text="@string/welcome_subtitle" />

2) Tema do app (Material 3) e Material Theming

O tema define cores, tipografia e formas globais. Em projetos com Material 3, é comum usar Theme.Material3.DayNight como base para suportar claro/escuro automaticamente.

Em res/values/themes.xml (tema claro):

<resources>    <style name="Theme.App" parent="Theme.Material3.DayNight.NoActionBar">        <item name="colorPrimary">@color/brand_primary</item>        <item name="colorSecondary">@color/brand_secondary</item>        <item name="colorError">@color/danger</item>    </style></resources>

Em res/values-night/themes.xml (tema escuro):

<resources>    <style name="Theme.App" parent="Theme.Material3.DayNight.NoActionBar">        <item name="colorPrimary">#D0BCFF</item>        <item name="colorSecondary">#CCC2DC</item>        <item name="colorError">#F2B8B5</item>    </style></resources>

Repare que o nome do estilo é o mesmo (Theme.App) nos dois arquivos; o Android escolhe automaticamente a versão values-night quando o modo escuro está ativo.

Aplicando Dark Theme e garantindo contraste adequado

1) Como o modo escuro é aplicado

Se seu app usa um tema DayNight e você define valores em values-night, o Android alterna automaticamente conforme a configuração do sistema (ou conforme você forçar via código).

Para forçar o modo (opcional), no Kotlin (ex.: em uma tela de configurações):

import androidx.appcompat.app.AppCompatDelegateAppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) // escuro// AppCompatDelegate.MODE_NIGHT_NO // claro// AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM // padrão do sistema

2) Contraste: use cores “On*” do Material

Para manter legibilidade, prefira atributos do tema como:

  • ?attr/colorSurface para fundos de superfícies
  • ?attr/colorOnSurface para texto/ícones sobre colorSurface
  • ?attr/colorPrimary e ?attr/colorOnPrimary para elementos primários e conteúdo sobre eles

Exemplo de card com texto que se adapta ao claro/escuro:

<com.google.android.material.card.MaterialCardView    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:layout_margin="@dimen/spacing_md"    app:cardBackgroundColor="?attr/colorSurface">    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:padding="@dimen/spacing_md"        android:text="@string/welcome_subtitle"        android:textColor="?attr/colorOnSurface" /></com.google.android.material.card.MaterialCardView>

Evite texto cinza fixo (ex.: #777777) porque pode ficar ilegível no modo escuro. Se precisar de variações (texto secundário), prefira atributos do Material (quando disponíveis) ou defina cores específicas em values e values-night.

Referenciando recursos no XML e no Kotlin (resumo prático)

TipoXMLKotlin
String@string/welcome_titlegetString(R.string.welcome_title)
String com args(normalmente via binding/atributos)getString(R.string.greeting_user, name)
Plurals(normalmente via binding/adapter)resources.getQuantityString(R.plurals.notifications_count, n, n)
Color (direta)@color/brand_primarygetColor(R.color.brand_primary)
Color (do tema)?attr/colorOnSurfaceMaterialColors.getColor(view, com.google.android.material.R.attr.colorOnSurface)
Dimen@dimen/spacing_mdresources.getDimensionPixelSize(R.dimen.spacing_md)

Exemplo Kotlin para ler uma cor do tema (útil para dark theme):

import android.view.Viewimport com.google.android.material.color.MaterialColorsfun onSurfaceColor(view: View): Int {    return MaterialColors.getColor(view, com.google.android.material.R.attr.colorOnSurface)}

Qualifiers: values-night e values-sw600dp na prática

1) values-night

Use para sobrescrever recursos no modo escuro. Além de themes.xml, você pode ter colors.xml específico para night se fizer sentido.

  • res/values/colors.xml (claro)
  • res/values-night/colors.xml (escuro)

Isso é útil quando você precisa de uma cor utilitária que não vem do tema, mas ainda deve mudar no modo escuro.

2) values-sw600dp

Use para tablets e telas grandes. O caso mais comum é ajustar espaçamentos e tamanhos de texto sem duplicar layouts.

  • res/values/dimens.xml (padrão)
  • res/values-sw600dp/dimens.xml (tablet)

Passo a passo prático: criando uma tela com recursos, i18n e suporte a dark theme

Passo 1: Defina strings com placeholders e plurals

res/values/strings.xml:

<resources>    <string name="profile_title">Perfil</string>    <string name="profile_greeting">Olá, %1$s</string>    <plurals name="profile_points">        <item quantity="one">Você tem %d ponto</item>        <item quantity="other">Você tem %d pontos</item>    </plurals></resources>

res/values-en/strings.xml:

<resources>    <string name="profile_title">Profile</string>    <string name="profile_greeting">Hello, %1$s</string>    <plurals name="profile_points">        <item quantity="one">You have %d point</item>        <item quantity="other">You have %d points</item>    </plurals></resources>

Passo 2: Defina dimensões e (opcionalmente) variações para tablet

res/values/dimens.xml:

<resources>    <dimen name="screen_padding">16dp</dimen>    <dimen name="block_spacing">12dp</dimen></resources>

res/values-sw600dp/dimens.xml:

<resources>    <dimen name="screen_padding">24dp</dimen>    <dimen name="block_spacing">16dp</dimen></resources>

Passo 3: Configure tema claro/escuro

res/values/themes.xml:

<resources>    <style name="Theme.App" parent="Theme.Material3.DayNight.NoActionBar">        <item name="colorPrimary">@color/brand_primary</item>        <item name="colorSecondary">@color/brand_secondary</item>    </style></resources>

res/values-night/themes.xml:

<resources>    <style name="Theme.App" parent="Theme.Material3.DayNight.NoActionBar">        <item name="colorPrimary">#D0BCFF</item>        <item name="colorSecondary">#CCC2DC</item>    </style></resources>

Passo 4: Crie o layout usando recursos e atributos do tema

Exemplo de layout (XML) usando dimens e cores do tema:

<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:padding="@dimen/screen_padding"    android:background="?attr/colorSurface">    <TextView        android:id="@+id/title"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/profile_title"        android:textColor="?attr/colorOnSurface"        android:textAppearance="@style/TextAppearance.Material3.TitleLarge" />    <TextView        android:id="@+id/greeting"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="@dimen/block_spacing"        android:textColor="?attr/colorOnSurface"        android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />    <TextView        android:id="@+id/points"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="@dimen/block_spacing"        android:textColor="?attr/colorOnSurface"        android:textAppearance="@style/TextAppearance.Material3.BodyMedium" /></LinearLayout>

Passo 5: Preencha textos no Kotlin usando placeholders e plurals

val name = "Ana"val points = 2val greetingText = getString(R.string.profile_greeting, name)val pointsText = resources.getQuantityString(R.plurals.profile_points, points, points)findViewById<TextView>(R.id.greeting).text = greetingTextfindViewById<TextView>(R.id.points).text = pointsText

Ao mudar o idioma do dispositivo para inglês, o Android carregará automaticamente as strings de values-en. Ao ativar o modo escuro, carregará o tema de values-night, mantendo contraste via colorSurface/colorOnSurface.

Agora responda o exercício sobre o conteúdo:

Ao criar um layout que funcione bem em modo claro/escuro e seja fácil de manter, qual abordagem é mais adequada para definir cores e textos?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

Centralizar textos em strings e usar atributos do tema para cores evita hardcode, facilita tradução e permite que o Android aplique automaticamente variações como values-night no modo escuro.

Próximo capitúlo

Activity e Fragment em Android com Kotlin: responsabilidades e implementação

Arrow Right Icon
Capa do Ebook gratuito Android para Iniciantes com Kotlin: construindo seu primeiro app moderno
27%

Android para Iniciantes com Kotlin: construindo seu primeiro app moderno

Novo curso

15 páginas

Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.