Como definir a família de fontes padrão para todo o aplicativo Android

282

Estou usando a fonte de luz Roboto no meu aplicativo. Para definir a fonte, eu devo adicionar a android:fontFamily="sans-serif-light"todas as visualizações. Existe alguma maneira de declarar a fonte Roboto como família de fontes padrão para o aplicativo inteiro? Eu tentei assim, mas não parecia funcionar.

<style name="AppBaseTheme" parent="android:Theme.Light"></style>

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>
tomrozb
fonte
2
Isso pode ajudá-lo: stackoverflow.com/a/16883281/1329733
Jacob R
2
Agora você pode especificar fontes personalizadas diretamente do XML no android studio 3.0 developer.android.com/guide/topics/ui/look-and-feel/…
Sete

Respostas:

289

A resposta é sim.

Global Roboto light para TextViewe Buttonclasses:

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="android:buttonStyle">@style/RobotoButtonStyle</item>
</style>

<style name="RobotoTextViewStyle" parent="android:Widget.TextView">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

<style name="RobotoButtonStyle" parent="android:Widget.Holo.Button">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

Basta selecionar o estilo desejado na lista themes.xml e depois criar seu estilo personalizado com base no original. No final, aplique o estilo como tema do aplicativo.

<application
    android:theme="@style/AppTheme" >
</application>

Ele funcionará apenas com fontes internas como o Roboto, mas essa foi a questão. Para fontes personalizadas (carregadas de ativos, por exemplo), esse método não funciona.

EDIT 13/08/15

Se você estiver usando temas do AppCompat, lembre-se de remover o android:prefixo. Por exemplo:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="buttonStyle">@style/RobotoButtonStyle</item>
</style>

Observe que o prefixo buttonStylenão contém android:, mas textViewStyledeve conter.

tomrozb
fonte
4
De onde você tirou o sans-serif-lightvalor? Existe uma lista de valores válidos para fontFamilyalgum lugar? Estive pesquisando os documentos, os arquivos de tema e estilo na fonte do Android e não consigo encontrar nada.
30513 Christopher Christopher
34
isso é possível apenas para o nível 16 da API. o nome "android: fontFamily" existe apenas no nível 16 ou superior. existe uma maneira de fazer isso também para a API 14, por exemplo?
Lorenzo Barbagli
3
@LorenzoBarbagli, você pode verificar caligrafia
Brais Gabin
10
Bem, o que faço se tiver uma fonte personalizada?
Rohit Tigga
2
sim, também quero adicionar uma fonte personalizada a todo o aplicativo. Como eu posso fazer isso ?. Preciso substituir o TextView e substituir todo o TextView, conforme sugerido na primeira resposta #
John
144

Com o lançamento do Android Oreo, você pode usar a biblioteca de suporte para atingir esse objetivo.

  1. Faça check-in no seu aplicativo build.gradle se você tiver a biblioteca de suporte > = 26.0.0
  2. Adicione a pasta " fonte " à sua pasta de recursos e adicione suas fontes lá
  3. Faça referência à sua família de fontes padrão no estilo principal do seu aplicativo:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
       <item name="android:fontFamily">@font/your_font</item>
       <item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 if theme other than AppCompat -->
    </style>

Verifique https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html para obter informações mais detalhadas.

João Magalhães
fonte
9
Ao segmentar a API 26+, esse deve ser o método aceito. Ao usar a Biblioteca de suporte , remova o android:prefixo
webo80
2
se você usar apenas a versão não corrigida, tudo bem. A prefixada apenas será ignorado na API <26
webo80
2
Isso não define a fonte em todos os lugares ... por exemplo, se você tem estilos derivados Base.TextAppearance.AppCompat, não é usado lá.
Ixx
3
@ Ixx, como substituir esses estilos também?
Primož Kralj
2
Lembre-se de usar também AppCompatTextView ao direcionar api <26
Codelicious
37

Para alterar a fonte do seu aplicativo, siga as seguintes etapas:

  1. resDiretório interno crie um novo diretório e chame-ofont .
  2. Insira sua fonte .ttf / .otf dentro da pasta de fontes. Verifique se o nome da fonte está em letras minúsculas e apenas sublinhado.
  3. Dentro res-> values-> styles.xmldentro <resources>-> <style>adicione sua fonte <item name="android:fontFamily">@font/font_name</item>.

insira a descrição da imagem aqui

Agora todo o texto do seu aplicativo deve estar na fonte que você adicionar.

cara
fonte
8
ao usar fontes personalizadas, como posso adicionar fontes em negrito junto com fontes comuns?
Rajbir Shienh 31/03/19
Isso funciona apenas com o nível 26 da API e acima. E a API 21 e abaixo?
zulkarnain shah 04/04
34

LEIA ATUALIZAÇÕES ABAIXO

Eu tive o mesmo problema com a incorporação de uma nova fonte e finalmente consegui trabalhar com a extensão do TextView e definir o tipo de letra dentro.

public class YourTextView extends TextView {

    public YourTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public YourTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public YourTextView(Context context) {
        super(context);
        init();
    }

    private void init() {
        Typeface tf = Typeface.createFromAsset(context.getAssets(),
            "fonts/helveticaneue.ttf");
        setTypeface(tf);
    }
}

Você precisa alterar os elementos do TextView posteriormente para de em todos os elementos. E se você usar o UI-Creator no Eclipse, às vezes ele não mostra os TextViews corretamente. Foi a única coisa que funcionou para mim ...

ATUALIZAR

Atualmente, estou usando a reflexão para alterar os tipos de letra em todo o aplicativo sem estender TextViews. Confira esta postagem do SO

ATUALIZAÇÃO 2

A partir do nível 26 da API e disponível na 'biblioteca de suporte', você pode usar

android:fontFamily="@font/embeddedfont"

Mais informações: Fontes em XML

longi
fonte
25
Esta não é a solução. Estou usando muitas visualizações diferentes, não apenas o TextView. Quero definir a fonte uma vez e esquecê-la. Além disso, seu código cria um novo objeto para cada TextView. Pelo menos, declare o campo como estático para carregar a fonte dos ativos uma vez.
Tomrozb
2
... bem, há um localizar e substituir função, que funciona muito bem neste caso
longi
1
Isso não vai funcionar. Você não pode chamar getContext()quando a variável é estática. Você deve implementá-lo da maneira singleton, caso contrário, o código atual nem será compilado.
Tom15215:
1
eu reverti o último commit.
longi
1
@trozroz: D Acabei de perceber que as últimas mudanças rápidas que fiz foram por causa de seus comentários! como você tem pontos suficientes, você pode otimizar o exemplo de código. caso contrário ainda vamos falar sobre o assunto dentro de alguns anos, quando ninguém se preocupa com smartphones mais;)
longi
8

Adicione esta linha de código em seu res / value / styles.xml

<item name="android:fontFamily">@font/circular_medium</item>

todo o estilo será assim

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:fontFamily">@font/circular_medium</item>
</style>

altere "circular_medium" para o seu próprio nome de fonte.

nirazverma
fonte
6

Para não falar de desempenho, para fontes personalizadas, você pode ter um método recursivo em loop através de todas as visualizações e definir o tipo de letra, se for um TextView:

public class Font {
    public static void setAllTextView(ViewGroup parent) {
        for (int i = parent.getChildCount() - 1; i >= 0; i--) {
            final View child = parent.getChildAt(i);
            if (child instanceof ViewGroup) {
                setAllTextView((ViewGroup) child);
            } else if (child instanceof TextView) {
                ((TextView) child).setTypeface(getFont());
            }
        }
    }

    public static Typeface getFont() {
        return Typeface.createFromAsset(YourApplicationContext.getInstance().getAssets(), "fonts/whateverfont.ttf");
    }
}

Em toda a sua atividade, passe o ViewGroup atual para ele após setContentView e pronto:

ViewGroup group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
Font.setAllTextView(group);

Para fragmento, você pode fazer algo semelhante.

Allen Chan
fonte
1
Parece ótimo, mas me pergunto como fazê-lo funcionar no conteúdo do recyclerView?
Srujan Barai
Eu apenas tentei isso. muito pesado para renderizar. Desacelerando recyclerViewcomo o inferno.
Srujan Barai
Totalmente não recomendado para qualquer exibição de lista, esse truque é apenas para economizar tempo para codificar a exibição estática.
Allen Chan
5

Outra maneira de fazer isso para todo o aplicativo é usar a reflexão com base nesta resposta

public class TypefaceUtil {
    /**
     * Using reflection to override default typefaces
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE
     * OVERRIDDEN
     *
     * @param typefaces map of fonts to replace
     */
    public static void overrideFonts(Map<String, Typeface> typefaces) {
        try {
            final Field field = Typeface.class.getDeclaredField("sSystemFontMap");
            field.setAccessible(true);
            Map<String, Typeface> oldFonts = (Map<String, Typeface>) field.get(null);
            if (oldFonts != null) {
                oldFonts.putAll(typefaces);
            } else {
                oldFonts = typefaces;
            }
            field.set(null, oldFonts);
            field.setAccessible(false);
        } catch (Exception e) {
            Log.e("TypefaceUtil", "Can not set custom fonts");
        }
    }

    public static Typeface getTypeface(int fontType, Context context) {
        // here you can load the Typeface from asset or use default ones
        switch (fontType) {
            case BOLD:
                return Typeface.create(SANS_SERIF, Typeface.BOLD);
            case ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.ITALIC);
            case BOLD_ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.BOLD_ITALIC);
            case LIGHT:
                return Typeface.create(SANS_SERIF_LIGHT, Typeface.NORMAL);
            case CONDENSED:
                return Typeface.create(SANS_SERIF_CONDENSED, Typeface.NORMAL);
            case THIN:
                return Typeface.create(SANS_SERIF_MEDIUM, Typeface.NORMAL);
            case MEDIUM:
                return Typeface.create(SANS_SERIF_THIN, Typeface.NORMAL);
            case REGULAR:
            default:
                return Typeface.create(SANS_SERIF, Typeface.NORMAL);
        }
    }
}

sempre que quiser substituir as fontes, basta chamar o método e fornecer um mapa de tipos de letra da seguinte maneira:

Typeface regular = TypefaceUtil.getTypeface(REGULAR, context);
Typeface light = TypefaceUtil.getTypeface(REGULAR, context);
Typeface condensed = TypefaceUtil.getTypeface(CONDENSED, context);
Typeface thin = TypefaceUtil.getTypeface(THIN, context);
Typeface medium = TypefaceUtil.getTypeface(MEDIUM, context);
Map<String, Typeface> fonts = new HashMap<>();
fonts.put("sans-serif", regular);
fonts.put("sans-serif-light", light);
fonts.put("sans-serif-condensed", condensed);
fonts.put("sans-serif-thin", thin);
fonts.put("sans-serif-medium", medium);
TypefaceUtil.overrideFonts(fonts);

para ver exemplo completo

Isso funciona apenas para o Android SDK 21 e superior para versões anteriores. Verifique o exemplo completo

Ismail Almetwally
fonte
5

Basta usar esta lib compile-a no seu arquivo de notas

complie'me.anwarshahriar:calligrapher:1.0'

e use-o no método onCreate na atividade principal

Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "yourCustomFontHere.ttf", true);

Esta é a maneira mais rápida e elegante de fazer isso.

Mohamed Ayed
fonte
2

Este é o trabalho para o meu projeto, fonte https://gist.github.com/artem-zinnatullin/7749076

Crie um diretório de fontes dentro da Pasta de ativos e, em seguida, copie sua fonte personalizada para o diretório de fontes, por exemplo, estou usando trebuchet.ttf;

Crie uma classe TypefaceUtil.java;

import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;

import java.lang.reflect.Field;
public class TypefaceUtil {

    public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
        try {
            final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

            final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
            defaultFontTypefaceField.setAccessible(true);
            defaultFontTypefaceField.set(null, customFontTypeface);
        } catch (Exception e) {

        }
    }
}

Editar tema em styles.xml adicione abaixo

<item name="android:typeface">serif</item>

Exemplo em Meus styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:typeface">serif</item><!-- Add here -->
    </style>


    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowFullscreen">true</item>
    </style>
</resources>

Por fim, em Activity or Fragment onCreate, chame TypefaceUtil.java

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
    }
Irvan Dwi Pangga
fonte
0

O Android não oferece muito suporte para a aplicação de fontes em todo o aplicativo (consulte esta edição ). Você tem 4 opções para definir a fonte para todo o aplicativo:

  • Opção1: aplicar reflexão para alterar a fonte do sistema
  • Opção2: criar e subclassificar as classes de exibição personalizadas para cada exibição que precisa de uma fonte personalizada
  • Opção 3: implementar um rastreador de exibição que atravessa a hierarquia de exibição da tela atual
  • Opção4: use uma biblioteca de terceiros.

Detalhes dessas opções podem ser encontradas aqui .

Phileo99
fonte
0

Eu sei que esta pergunta é bastante antiga, mas eu encontrei uma boa solução. Basicamente, você passa um layout de contêiner para esta função, e ela aplicará a fonte a todas as visualizações suportadas e circulará recursivamente nos layouts filhos:

public static void setFont(ViewGroup layout)
{
    final int childcount = layout.getChildCount();
    for (int i = 0; i < childcount; i++)
    {
        // Get the view
        View v = layout.getChildAt(i);

        // Apply the font to a possible TextView
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Apply the font to a possible EditText
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Recursively cicle into a possible child layout
        try {
            ViewGroup vg = (ViewGroup) v;
            Utility.setFont(vg);
            continue;
        }
        catch (Exception e) { }
    }
}
FonzTech
fonte
0

meramente conjunto fonte de aplicativo para normal, sans, serifoumonospace (não uma fonte personalizada!), você pode fazer isso.

defina um tema e defina o android:typefaceatributo para o tipo de letra que você deseja usar styles.xml:

<resources>

    <!-- custom normal activity theme -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!-- other elements -->
        <item name="android:typeface">monospace</item>
    </style>

</resources>

aplique o tema a todo o aplicativo no AndroidManifest.xmlarquivo:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application
        android:theme="@style/AppTheme" >
    </application>
</manifest>

referência android

Eric
fonte
Tem certeza que funciona? De acordo com o documento do Android: "Deve ser um dos seguintes valores constantes: normal, sans, serif, monospace".
Tomrozb
1
Ah, entendi ... você está certo ... eu não entendi a pergunta, afinal: x Eu só queria que meu aplicativo inteiro usasse uma fonte monoespaçada (não personalizada) e eu o vi funcionando, então publiquei isso aqui ... eu acho que minha resposta ainda pode ser útil para quem quer fazer algo parecido .... então eu vou editá-lo e deixá-lo aqui ... eu estou bem, é isso acumula votos negativos. obrigado por apontar isso
Eric
Hey @Dave Cruise, funciona apenas para monoespaços? Eu só testei para monoespaço ... e nada mais ... então não tenho certeza ... mas de acordo com a documentação, ele deve funcionar para "normal", "sans" e "serif" também .. .i acho que o tipo de letra é mais geral que a fonte, portanto, não podemos usá-lo para definir a fonte do aplicativo como uma fonte específica, como "consolas" ou algo assim.
Eric
@ Eric sim. Eu também não tenho ideia. o monoespaço funciona como um encanto, mas sem sorte para o normal, sans ou serif.
Dave Cruise
0

Experimente esta biblioteca, leve e fácil de implementar

https://github.com/sunnag7/FontStyler

<com.sunnag.fontstyler.FontStylerView
              android:textStyle="bold"
              android:text="@string/about_us"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingTop="8dp"
              app:fontName="Lato-Bold"
              android:textSize="18sp"
              android:id="@+id/textView64" />
Sanny Nagveker
fonte
-7

A resposta é não, você não pode. Consulte É possível definir uma fonte personalizada para todo o aplicativo? Para maiores informações.

Existem soluções alternativas, mas nada nas linhas de "uma única linha de código aqui e todas as minhas fontes serão esta em vez daquela ".

(Eu meio que agradeço ao Google - e à Apple - por isso). As fontes personalizadas têm um lugar, mas torná-las fáceis de substituir por todo o aplicativo teriam criado um mundo inteiro de aplicativos do Comic Sans )

Martin Marconcini
fonte
41
Não concordo totalmente com o seu comentário. Definir uma fonte globalmente deve ser trivial, não algo que exija os tipos de soluções alternativas necessárias. Cabe aos desenvolvedores / designers do mundo evitar os aplicativos "Comic Sans", não o Google / Apple para impor isso.
precisa saber é o seguinte
4
Consistência> Design sofisticado.
Martin Marconcini
14
No entanto, consistência <funcionalidade. Desenvolvemos aplicativos que exibem hebraico bíblico. Todas as fontes de estoque encontradas nos dispositivos Android (incluindo as mais recentes fontes L do Android) fazem um péssimo trabalho de renderização de marcas de cantilação (e executam um trabalho medíocre nas marcas de vogal, apesar de estarem melhorando). É absolutamente necessário usar uma fonte personalizada em todo o aplicativo e tivemos que escrever muito código simplesmente para obter todas as visualizações necessárias.
Ted Hopp