Android: use uma fonte personalizada em qualquer lugar

O Android não fornece um mecanismo para usar um arquivo de fonte personalizada (TTF, OTF, etc) em todas as áreas do seu aplicativo. Em vez disso, você deve empregar uma estratégia para definir um costume Typefaceem todos os TextViews, EditTexts e Buttons.

Esta postagem cobre uma estratégia que deve atender às suas necessidades de aplicativos comuns.

The View Crawler

Layouts (e sub-layouts) no Android são hierarquias de árvore compostas de ViewGroups como elementos compostos e Views como nós folha. Esta árvore pode ser rastreada visitando visualizações filhas em sua ordem favorita (largura primeiro ou profundidade primeiro). Ao rastejar nesta árvore, pode-se substituir todos os Typefaces em qualquer TextViews, EditTexts e Buttons que forem encontrados.

Aqui está uma implementação recursiva simples de um rastreador de visualização que substituirá o Typefacede qualquer visualização apropriada na hierarquia:

public class FontChangeCrawler
{
private Typeface typeface;

public FontChangeCrawler(Typeface typeface)
{
this.typeface = typeface;
}

public FontChangeCrawler(AssetManager assets, String assetsFontFileName)
{
typeface
= Typeface.createFromAsset(assets, assetsFontFileName);
}

public void replaceFonts(ViewGroup viewTree)
{
View child;
for(int i = 0; i < viewTree.getChildCount(); ++i)
{
child
= viewTree.getChildAt(i);
if(child instanceof ViewGroup)
{
// recursive call
replaceFonts
((ViewGroup)child);
}
else if(child instanceof TextView)
{
// base case
((TextView) child).setTypeface(typeface);
}
}
}
}

Substitua o tipo de letra da atividade inteira

Para substituir a fonte padrão em todas as visualizações do layout de uma atividade, basta usar o FontChangeCrawleracima, da seguinte forma:

@Override
public void setContentView(View view)
{
super.setContentView(view);

FontChangeCrawler fontChanger = new FontChangeCrawler(getAssets(), "font.otf");
fontChanger
.replaceFonts((ViewGroup)this.findViewById(android.R.id.content));
}

Se você não estiver familiarizado com android.R.id.content, é o ID oficial fornecido ao root Viewem um Activitylayout de.

Considere colocar a lógica acima em uma BaseActivityclasse.

Substituir o tipo de letra do Fragment

Você também precisará aplicar o FontChangeCrawlera cada um Fragment. Considere colocar essa lógica em uma BaseFragmentclasse.

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);

FontChangeCrawler fontChanger = new FontChangeCrawler(getAssets(), "font.otf");
fontChanger
.replaceFonts((ViewGroup) this.getView());
}

Adaptadores de manuseio, etc.

Substituir Activityfontes é um longo caminho, mas a maioria de nós também tem uma infinidade de fontes ListView. Os itens da lista em a ListViewsão construídos em um adaptador, não em um Activity. Portanto, você também precisará usar o FontChangeCrawlerem seus adaptadores:

...
if(convertView == null)
{
convertView
= inflater.inflate(R.layout.listitem, null);
fontChanger
.replaceFonts((ViewGroup)convertView);
}
...

O que não foi tratado?

Vou deixar o manuseio do ActionBar como um exercício para o leitor. Além disso, considere como você pode lidar com widgets cujo tipo de letra você não deseja alterar.