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.xmleres/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:
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
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 sistema2) Contraste: use cores “On*” do Material
Para manter legibilidade, prefira atributos do tema como:
?attr/colorSurfacepara fundos de superfícies?attr/colorOnSurfacepara texto/ícones sobrecolorSurface?attr/colorPrimarye?attr/colorOnPrimarypara 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)
| Tipo | XML | Kotlin |
|---|---|---|
| String | @string/welcome_title | getString(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_primary | getColor(R.color.brand_primary) |
| Color (do tema) | ?attr/colorOnSurface | MaterialColors.getColor(view, com.google.android.material.R.attr.colorOnSurface) |
| Dimen | @dimen/spacing_md | resources.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 = pointsTextAo 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.