Android: deseja definir fontes personalizadas para todo o aplicativo, não para o tempo de execução

100

É possível definir qualquer fonte personalizada em todos os controles do aplicativo? E não necessariamente em tempo de execução? (ou seja, de xml se possível ou apenas uma vez para todo o aplicativo no arquivo JAVA)

Posso definir a fonte para um controle a partir deste código.

public static void setFont(TextView textView) {
    Typeface tf = Typeface.createFromAsset(textView.getContext()
            .getAssets(), "fonts/BPreplay.otf");

    textView.setTypeface(tf);

}

E o problema com esse código é que ele deve ser chamado para todos os controles. E eu quero chamar isso ou qualquer método semelhante uma vez, ou se possível definir a propriedade em xml. É possível?

Prasham
fonte
6
Pode ser que você possa escrever um controle personalizado estendendo o TextView e definir a fonte no construtor pode ser uma opção. Então, você pode usar este controle em todo o aplicativo no lugar do seu textview. também para economizar memória, você pode evitar o carregamento de recursos usando um tipo de fonte estática.
Varun
@Varun: bem, essa ideia pode economizar meu tempo, mas eu tenho que definir todos os controles, e escrever um controle personalizado para cada um será um caminho mais longo do que definir um tempo de execução de fonte, o que você acha? (No entanto, +1 para escrever o controle personalizado)
Prasham
Você pode querer escrever apenas um controle personalizado estendendo o textView e a única modificação será a configuração do tipo de letra. Ao usar o controle cusotm em seus arquivos de layout, você não precisa fazer isso manualmente todas as vezes para cada visualização de texto e ainda pode ter certeza de que está usando a fonte que deseja.
Varun
Que tal escrever um costume em VIEWvez de escrever um custom text viewe um custom button viewseparadamente? Meu requisito é para todos os controles, e a visualização de texto foi apenas um exemplo. Desculpe, esqueci de mencionar isso .. :-(
Prasham
1
Dê uma olhada na questão satckoverflow stackoverflow.com/questions/2711858/… isso ajuda você.
Ashwini

Respostas:

123

EDIT : Já faz um tempo e gostaria de acrescentar o que acho que é a melhor maneira de fazer isso, nada menos que por meio de XML!

Então, primeiro, você vai querer fazer uma nova classe que substitui qualquer View que você deseja personalizar. (por exemplo, deseja um botão com uma fonte personalizada? Estender Button). Vamos dar um exemplo:

public class CustomButton extends Button {
    private final static int ROBOTO = 0;
    private final static int ROBOTO_CONDENSED = 1;

    public CustomButton(Context context) {
        super(context);
    }

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        parseAttributes(context, attrs); //I'll explain this method later
    }

    public CustomButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        parseAttributes(context, attrs);
    }
}

Agora, se você não tiver um, adicione um documento XML em res/values/attrs.xmle adicione:

<resources>
    <!-- Define the values for the attribute -->
    <attr name="typeface" format="enum">
        <enum name="roboto" value="0"/>
        <enum name="robotoCondensed" value="1"/>
    </attr>

    <!-- Tell Android that the class "CustomButton" can be styled, 
         and which attributes it supports -->
    <declare-styleable name="CustomButton">
        <attr name="typeface"/>
    </declare-styleable>
</resources>

Ok, então com isso fora do caminho, vamos voltar ao parseAttributes()método anterior:

private void parseAttributes(Context context, AttributeSet attrs) {
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.CustomButton);

    //The value 0 is a default, but shouldn't ever be used since the attr is an enum
    int typeface = values.getInt(R.styleable.CustomButton_typeface, 0);

    switch(typeface) {
        case ROBOTO: default:
            //You can instantiate your typeface anywhere, I would suggest as a 
            //singleton somewhere to avoid unnecessary copies
            setTypeface(roboto); 
            break;
        case ROBOTO_CONDENSED:
            setTypeface(robotoCondensed);
            break;
    }

    values.recycle();
}

Agora você está pronto. Você pode adicionar mais atributos para qualquer coisa (você pode adicionar outro para typefaceStyle - negrito, itálico, etc.), mas agora vamos ver como usá-lo:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.yourpackage.name"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.yourpackage.name.CustomButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me!"
        custom:typeface="roboto" />

</LinearLayout>

A xmlns:customlinha pode realmente ser qualquer coisa, mas a convenção é o que é mostrado acima. O que importa é que ele seja único e é por isso que o nome do pacote é usado. Agora você apenas usa o custom:prefixo para seus atributos e o android:prefixo para atributos do Android.

Uma última coisa: se você quiser usar isso em um estilo ( res/values/styles.xml), você deve não adicionar a xmlns:customlinha. Basta fazer referência ao nome do atributo sem prefixo:

<style name="MyStyle>
    <item name="typeface">roboto</item>
</style>

                               (PREVIOUS ANSWER)

Usando uma fonte personalizada no Android

Isso deve ajudar. Basicamente, não há como fazer isso em XML e, até onde sei, não há maneira mais fácil de fazer isso em código. Você sempre pode ter um método setLayoutFont () que cria o tipo de letra uma vez e, em seguida, executa setTypeface () para cada um. Você apenas teria que atualizá-lo cada vez que adicionar um novo item a um layout. Algo como abaixo:

public void setLayoutFont() {
    Typeface tf = Typeface.createFromAsset(
        getBaseContext().getAssets(), "fonts/BPreplay.otf");
    TextView tv1 = (TextView)findViewById(R.id.tv1);
    tv1.setTypeface(tf);

    TextView tv2 = (TextView)findViewById(R.id.tv2);
    tv2.setTypeface(tf);

    TextView tv3 = (TextView)findViewById(R.id.tv3);
    tv3.setTypeface(tf);
}

EDIT : Então, acabei de implementar algo como isso sozinho, e como acabei fazendo isso foi criar uma função como esta:

public static void setLayoutFont(Typeface tf, TextView...params) {
    for (TextView tv : params) {
        tv.setTypeface(tf);
    }
}

Depois, basta usar este método de onCreate () e passar todos os TextViews que deseja atualizar:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
//find views by id...
setLayoutFont(tf, tv1, tv2, tv3, tv4, tv5);

EDITAR 05/09/12:

Então, como isso ainda está recebendo visualizações e votos, gostaria de adicionar um método muito melhor e mais completo:

Typeface mFont = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
ViewGroup root = (ViewGroup)findViewById(R.id.myrootlayout);
setFont(root, mFont);

/*
 * Sets the font on all TextViews in the ViewGroup. Searches
 * recursively for all inner ViewGroups as well. Just add a
 * check for any other views you want to set as well (EditText,
 * etc.)
 */
public void setFont(ViewGroup group, Typeface font) {
    int count = group.getChildCount();
    View v;
    for(int i = 0; i < count; i++) {
        v = group.getChildAt(i);
        if(v instanceof TextView || v instanceof Button /*etc.*/)
            ((TextView)v).setTypeface(font);
        else if(v instanceof ViewGroup)
            setFont((ViewGroup)v, font);
    }
}

Se você passar a raiz do seu layout, ele verificará recursivamente por TextViewou Buttonvisualizações (ou quaisquer outras que você adicionar a essa instrução if) dentro desse layout e definirá a fonte sem que você precise especificá-los por ID. Isso, claro, pressupõe que você deseja definir a fonte para cada visualização.

Kevin Coppock
fonte
1
Não vejo nenhuma diferença em seu código e meu código, exceto que eu uso o método como método de fábrica para todo o aplicativo e seu código parece ter sido escrito para uma atividade. PS é realmente estranho adicionar mais um objeto para um textView somente leitura apenas para alterar a fonte. Off Topic: O Android deve realmente introduzir um mecanismo para buscar uma fonte da pasta assests e ser incluída no R para que possa ser alterado no tempo de design)
Prasham
1
Eu acho que, realisticamente, não há nenhuma grande diferença, exceto que você não estaria criando o Typeface repetidamente. A ideia de Varun de usar apenas uma fonte estática faria a mesma coisa.
Kevin Coppock
1
A linha final do seu código de exemplo deve ser setLayoutFont (tf, tv1, tv2, tv3, tv4, tv5); em vez de setTypeface (tf, tv1, tv2, tv3, tv4, tv5) ;?
Kyle Clegg
1
Não deve você recycleo TypedArray values?
CorayThan
1
Se estiver usando Gradle, o namespace personalizado deve serxmlns:custom="http://schemas.android.com/apk/res-auto"
Jabari
93

Existe uma maneira bastante fácil de fazer isso via XML. Você só precisa criar seu próprio widget que estenda TextView.

Primeiro, crie um arquivo em res / values ​​/ attrs.xml com o seguinte conteúdo:

<resources>
    <declare-styleable name="TypefacedTextView">
        <attr name="typeface" format="string" />
    </declare-styleable>
</resources>

Depois disso, crie seu widget personalizado:

package your.package.widget;

public class TypefacedTextView extends TextView {

    public TypefacedTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        //Typeface.createFromAsset doesn't work in the layout editor. Skipping...
        if (isInEditMode()) {
            return;
        }

        TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.TypefacedTextView);
        String fontName = styledAttrs.getString(R.styleable.TypefacedTextView_typeface);
        styledAttrs.recycle();

        if (fontName != null) {
            Typeface typeface = Typeface.createFromAsset(context.getAssets(), fontName);
            setTypeface(typeface);
        }
    }

}

Como você pode ver, o código acima lerá uma fonte dentro de ativos / pasta. Para este exemplo, estou assumindo que existe um arquivo chamado "custom.ttf" na pasta de ativos. Por fim, use o widget nos XMLs:

<your.package.widget.TypefacedTextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:your_namespace="http://schemas.android.com/apk/res/your.package"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Custom fonts in XML are easy"
    android:textColor="#FFF"
    android:textSize="14dip"
    your_namespace:typeface="custom.ttf" />

Nota: você não poderá ver sua fonte customizada no editor de layout do Eclipse. É por isso que coloquei o isInEditMode()cheque. Mas se você executar seu aplicativo, a fonte personalizada funcionará perfeitamente.

Espero que ajude!

leocadiotina
fonte
Não tentei fazer isso, mas criei um controle personalizado estendendo a TextViewclasse; configurei typefacenele e usei o controle personalizado no layout como fazemos normalmente e funcionou para mim ... Era simples, porém, que o acima ...
Mahendra Liya
1
Eu fiz exatamente o que você disse. A única diferença é que tornei esse componente reutilizável, pois a questão é como fazer isso via XML. De fato, há uma maneira de fazer isso via XML e essa é a maneira de se fazer :)
leocadiotina
Código muito fácil de integrar. Funciona para mim. Obrigado.
Durai
1
Esta deve ser a resposta aceita. Muito bem escrito. Obrigado!
Reaz Murshed
1
Incrível, @DominikSuszczewicz! Você pode compartilhar o código para que eu possa atualizar a resposta?
leocadiotina 01 de
15

Exemplo de TextView com tipo de letra roboto:

attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

<declare-styleable name="RobotoTextView">
    <attr name="typeface"/>
</declare-styleable>

<attr name="typeface" format="enum">
    <enum name="roboto_thin" value="0"/>
    <enum name="roboto_thin_italic" value="1"/>
    <enum name="roboto_light" value="2"/>
    <enum name="roboto_light_italic" value="3"/>
    <enum name="roboto_regular" value="4"/>
    <enum name="roboto_italic" value="5"/>
    <enum name="roboto_medium" value="6"/>
    <enum name="roboto_medium_italic" value="7"/>
    <enum name="roboto_bold" value="8"/>
    <enum name="roboto_bold_italic" value="9"/>
    <enum name="roboto_black" value="10"/>
    <enum name="roboto_black_italic" value="11"/>
    <enum name="roboto_condensed" value="12"/>
    <enum name="roboto_condensed_italic" value="13"/>
    <enum name="roboto_condensed_bold" value="14"/>
    <enum name="roboto_condensed_bold_italic" value="15"/>
</attr>

</resources>

RobotoTextView.java:

public class RobotoTextView extends TextView {

/*
 * Permissible values ​​for the "typeface" attribute.
 */
private final static int ROBOTO_THIN = 0;
private final static int ROBOTO_THIN_ITALIC = 1;
private final static int ROBOTO_LIGHT = 2;
private final static int ROBOTO_LIGHT_ITALIC = 3;
private final static int ROBOTO_REGULAR = 4;
private final static int ROBOTO_ITALIC = 5;
private final static int ROBOTO_MEDIUM = 6;
private final static int ROBOTO_MEDIUM_ITALIC = 7;
private final static int ROBOTO_BOLD = 8;
private final static int ROBOTO_BOLD_ITALIC = 9;
private final static int ROBOTO_BLACK = 10;
private final static int ROBOTO_BLACK_ITALIC = 11;
private final static int ROBOTO_CONDENSED = 12;
private final static int ROBOTO_CONDENSED_ITALIC = 13;
private final static int ROBOTO_CONDENSED_BOLD = 14;
private final static int ROBOTO_CONDENSED_BOLD_ITALIC = 15;
/**
 * List of created typefaces for later reused.
 */
private final static SparseArray<Typeface> mTypefaces = new SparseArray<Typeface>(16);

/**
 * Simple constructor to use when creating a view from code.
 *
 * @param context The Context the view is running in, through which it can
 *                access the current theme, resources, etc.
 */
public RobotoTextView(Context context) {
    super(context);
}

/**
 * Constructor that is called when inflating a view from XML. This is called
 * when a view is being constructed from an XML file, supplying attributes
 * that were specified in the XML file. This version uses a default style of
 * 0, so the only attribute values applied are those in the Context's Theme
 * and the given AttributeSet.
 * <p/>
 * <p/>
 * The method onFinishInflate() will be called after all children have been
 * added.
 *
 * @param context The Context the view is running in, through which it can
 *                access the current theme, resources, etc.
 * @param attrs   The attributes of the XML tag that is inflating the view.
 * @see #RobotoTextView(Context, AttributeSet, int)
 */
public RobotoTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    parseAttributes(context, attrs);
}

/**
 * Perform inflation from XML and apply a class-specific base style. This
 * constructor of View allows subclasses to use their own base style when
 * they are inflating.
 *
 * @param context  The Context the view is running in, through which it can
 *                 access the current theme, resources, etc.
 * @param attrs    The attributes of the XML tag that is inflating the view.
 * @param defStyle The default style to apply to this view. If 0, no style
 *                 will be applied (beyond what is included in the theme). This may
 *                 either be an attribute resource, whose value will be retrieved
 *                 from the current theme, or an explicit style resource.
 * @see #RobotoTextView(Context, AttributeSet)
 */
public RobotoTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    parseAttributes(context, attrs);
}

/**
 * Parse the attributes.
 *
 * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
 * @param attrs   The attributes of the XML tag that is inflating the view.
 */
private void parseAttributes(Context context, AttributeSet attrs) {
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.RobotoTextView);

    int typefaceValue = values.getInt(R.styleable.RobotoTextView_typeface, 0);
    values.recycle();

    setTypeface(obtaintTypeface(context, typefaceValue));
}

/**
 * Obtain typeface.
 *
 * @param context       The Context the view is running in, through which it can
 *                      access the current theme, resources, etc.
 * @param typefaceValue values ​​for the "typeface" attribute
 * @return Roboto {@link Typeface}
 * @throws IllegalArgumentException if unknown `typeface` attribute value.
 */
private Typeface obtaintTypeface(Context context, int typefaceValue) throws IllegalArgumentException {
    Typeface typeface = mTypefaces.get(typefaceValue);
    if (typeface == null) {
        typeface = createTypeface(context, typefaceValue);
        mTypefaces.put(typefaceValue, typeface);
    }
    return typeface;
}

/**
 * Create typeface from assets.
 *
 * @param context       The Context the view is running in, through which it can
 *                      access the current theme, resources, etc.
 * @param typefaceValue values ​​for the "typeface" attribute
 * @return Roboto {@link Typeface}
 * @throws IllegalArgumentException if unknown `typeface` attribute value.
 */
private Typeface createTypeface(Context context, int typefaceValue) throws IllegalArgumentException {
    Typeface typeface;
    switch (typefaceValue) {
        case ROBOTO_THIN:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Thin.ttf");
            break;
        case ROBOTO_THIN_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-ThinItalic.ttf");
            break;
        case ROBOTO_LIGHT:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Light.ttf");
            break;
        case ROBOTO_LIGHT_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-LightItalic.ttf");
            break;
        case ROBOTO_REGULAR:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Regular.ttf");
            break;
        case ROBOTO_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Italic.ttf");
            break;
        case ROBOTO_MEDIUM:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Medium.ttf");
            break;
        case ROBOTO_MEDIUM_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-MediumItalic.ttf");
            break;
        case ROBOTO_BOLD:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");
            break;
        case ROBOTO_BOLD_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldItalic.ttf");
            break;
        case ROBOTO_BLACK:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Black.ttf");
            break;
        case ROBOTO_BLACK_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BlackItalic.ttf");
            break;
        case ROBOTO_CONDENSED:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Condensed.ttf");
            break;
        case ROBOTO_CONDENSED_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-CondensedItalic.ttf");
            break;
        case ROBOTO_CONDENSED_BOLD:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensed.ttf");
            break;
        case ROBOTO_CONDENSED_BOLD_ITALIC:
            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensedItalic.ttf");
            break;
        default:
            throw new IllegalArgumentException("Unknown `typeface` attribute value " + typefaceValue);
    }
    return typeface;
}

}

Exemplo de uso:

<your.package.widget.RobotoTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:typeface="roboto_thin"
                android:textSize="22sp"
                android:text="Roboto Thin"/>

Recursos: fontes Roboto e Noto

e.shishkin
fonte
existe uma maneira de usar essa solução, porém, sem corrigir os ids das fontes na classe java? talvez leia esses campos finais de enum attrs .. private final static int ROBOTO_THIN = 0; privado final estático int ROBOTO_THIN_ITALIC = 1; estático final privado int ROBOTO_LIGHT = 2; ...
Arthur Melo
3

É tarde demais, mas ajuda o outro,
eu criei CustomTextView que tem um atributo chamado typeFace e trata do problema de vazamento de memória com carregamento de fonte sem cache

Em primeiro lugar, a Fontsclasse que carrega as fontes dos ativos apenas uma vez

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

import java.util.Hashtable;

/**
 * Created by tonyhaddad on 7/19/15.
 */
public class Fonts {
    private Context context;

    public Fonts(Context context) {
        this.context = context;
    }
    private static Hashtable<String, Typeface> sTypeFaces = new Hashtable<String, Typeface>(
            4);
    public static Typeface getTypeFace(Context context, String fileName) {
        Typeface tempTypeface = sTypeFaces.get(fileName);

        if (tempTypeface == null) {
            String fontPath=null;
            if(fileName=="metabold")
                fontPath ="fonts/Meta-Bold.ttf";

            else if(fileName=="metanormal")
                fontPath="fonts/Meta-Normal.ttf";
            else if(fileName=="gsligh")
                fontPath="fonts/gesslight.ttf";
            else if(fileName=="bold")
                fontPath="fonts/Lato-Bold.ttf";
            else if(fileName=="rcr")
                fontPath="fonts/RobotoCondensed-Regular.ttf";

            else if(fileName=="mpr")
                fontPath="fonts/MyriadPro-Regular.otf";
            else if(fileName=="rr")
                fontPath="fonts/Roboto-Regular.ttf";

            tempTypeface = Typeface.createFromAsset(context.getAssets(), fontPath);
            sTypeFaces.put(fileName, tempTypeface);
        }

        return tempTypeface;
    }
}

então você precisa adicionar um atributo personalizado no attrs.xml adicionar este

<declare-styleable name="CustomFontTextView">
        <attr name="typeFace" format="string" />

    </declare-styleable>

então aula personalizada

 package package_name;

/**
 * Created by tonyhaddad on 8/26/15.
 */

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;

import package_name.R;

public class CustomFontTextView extends TextView {

    String typeFace;


    public CustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }

    public CustomFontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }

        init();
    }

    public CustomFontTextView(Context context) {
        super(context);



        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }


    private void init() {

    }

    public String getTypeFace() {
        return typeFace;
    }

    public void setTypeFace(String typeFace) {
        this.typeFace = typeFace;
        invalidate();
        requestLayout();
    }
}

e, finalmente, adicione a visualização de texto

  <package_name.CustomFontTextView
            xmlns:custom="http://schemas.android.com/apk/res-auto/package_name"
            android:id="@+id/txt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="41dp"
            android:gravity="center_vertical"
            android:text="text"
            android:textColor="#000"
            android:textSize="23sp"
            custom:typeFace="metanormal"/>

e você pode alterar a fonte programaticamente com o método setTypeFace
também poderá mover o espaço de nomes personalizado para o seu layout principal se quiser usar mais do que um nesta janela

Happy Coding :)

Antwan
fonte
resposta simples e direta.
eyadMhanna de
2

O método a seguir, chamado em onCreate () e aprovado no ViewGroup mais externo, funcionará para tudo, exceto para texto criado dinamicamente (ou seja, listas dinâmicas, alertas, etc.). Uma maneira fácil de obter o ViewGroup mais externo é usar getRootView em qualquer uma de suas visualizações.

public void onCreate(Bundle savedInstanceState){
    //onCreate code...
    EditText text = (EditText) findViewById(R.id.editText1);
    setTypeFaceForViewGroup((ViewGroup) text.getRootView());
}

private void setTypeFaceForViewGroup(ViewGroup vg){

    for (int i = 0; i < vg.getChildCount(); i++) {

            if (vg.getChildAt(i) instanceof ViewGroup)
                setTypeFaceForViewGroup((ViewGroup) vg.getChildAt(i));

            else if (vg.getChildAt(i) instanceof TextView)
                ((TextView) vg.getChildAt(i)).setTypeface(Typeface.createFromAsset(getAssets(), "fonts/Your_Font.ttf"));

    }

}

Isso deve funcionar para conteúdo dinâmico também, você apenas terá que chamá-lo, passando tudo o que você criou, logo depois de criá-lo (embora eu não testei isso).

Para economizar memória, você provavelmente desejará tornar o tipo de letra uma variável estática, em vez de criar um novo cada vez que o loop for executado como fiz aqui.

Chris
fonte
Eu não recomendo esta solução, porque você está criando uma nova instância da mesma fonte para cada elemento ao qual deseja aplicá-la. Isso pode causar problemas de memória.
flawyte
Isso está coberto em minha nota no final.
Chris
2

Se você está procurando uma solução programática mais geral, criei uma classe estática que pode ser usada para definir o Typeface de uma visualização inteira (Activity UI). Observe que estou trabalhando com Mono (C #), mas você pode implementá-lo facilmente usando Java.

Você pode passar a essa classe um layout ou uma visualização específica que deseja personalizar. Se você quiser ser supereficiente, poderá implementá-lo usando o padrão Singleton.

public static class AndroidTypefaceUtility 
{
    static AndroidTypefaceUtility()
    {
    }
    //Refer to the code block beneath this one, to see how to create a typeface.
    public static void SetTypefaceOfView(View view, Typeface customTypeface)
    {
    if (customTypeface != null && view != null)
    {
            try
            {
                if (view is TextView)
                    (view as TextView).Typeface = customTypeface;
                else if (view is Button)
                    (view as Button).Typeface = customTypeface;
                else if (view is EditText)
                    (view as EditText).Typeface = customTypeface;
                else if (view is ViewGroup)
                    SetTypefaceOfViewGroup((view as ViewGroup), customTypeface);
                else
                    Console.Error.WriteLine("AndroidTypefaceUtility: {0} is type of {1} and does not have a typeface property", view.Id, typeof(View));
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine("AndroidTypefaceUtility threw:\n{0}\n{1}", ex.GetType(), ex.StackTrace);
                    throw ex;
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / view parameter should not be null");
            }
        }

        public static void SetTypefaceOfViewGroup(ViewGroup layout, Typeface customTypeface)
        {
            if (customTypeface != null && layout != null)
            {
                for (int i = 0; i < layout.ChildCount; i++)
                {
                    SetTypefaceOfView(layout.GetChildAt(i), customTypeface);
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / layout parameter should not be null");
            }
        }

    }

Em sua atividade, você precisará criar um objeto Typeface. Eu crio o meu no OnCreate () usando um arquivo .ttf colocado em meu diretório Resources / Assets /. Certifique-se de que o arquivo esteja marcado como um Ativo Android em suas propriedades.

protected override void OnCreate(Bundle bundle)
{               
    ...
    LinearLayout rootLayout = (LinearLayout)FindViewById<LinearLayout>(Resource.Id.signInView_LinearLayout);
    Typeface allerTypeface = Typeface.CreateFromAsset(base.Assets,"Aller_Rg.ttf");
    AndroidTypefaceUtility.SetTypefaceOfViewGroup(rootLayout, allerTypeface);
}
JCKortlang
fonte
2

Infelizmente, o Android não oferece a maneira rápida, fácil e limpa que você procura para alterar a fonte de todo o seu aplicativo. Mas recentemente eu investiguei este assunto e criei algumas ferramentas que permitem que você altere a fonte sem qualquer codificação (você pode fazer tudo através de xml, estilos e até mesmo aparências de texto). Eles são baseados em soluções semelhantes, como você vê nas outras respostas aqui, mas permitem muito mais flexibilidade. Você pode ler tudo sobre isso neste blog e ver o projeto github aqui .

Aqui está um exemplo de como aplicar essas ferramentas. Coloque todos os seus arquivos de fonte em assets/fonts/. Em seguida, declare essas fontes em um arquivo xml (por exemplo res/xml/fonts.xml) e carregue esse arquivo no início de seu aplicativo com TypefaceManager.initialize(this, R.xml.fonts);(por exemplo, no onCreate de sua classe Application). O arquivo xml tem a seguinte aparência:

<?xml version="1.0" encoding="utf-8"?>
<familyset>

    <!-- Some Font. Can be referenced with 'someFont' or 'aspergit' -->
    <family>
        <nameset>
            <name>aspergit</name>
            <name>someFont</name>
        </nameset>
        <fileset>
            <file>Aspergit.ttf</file>
            <file>Aspergit Bold.ttf</file>
            <file>Aspergit Italic.ttf</file>
            <file>Aspergit Bold Italic.ttf</file>
        </fileset>
    </family>

    <!-- Another Font. Can be referenced with 'anotherFont' or 'bodoni' -->
    <family>
        <nameset>
            <name>bodoni</name>
            <name>anotherFont</name>
        </nameset>
        <fileset>
            <file>BodoniFLF-Roman.ttf</file>
            <file>BodoniFLF-Bold.ttf</file>
        </fileset>
    </family>

</familyset>

Agora você pode usar essas fontes em seu estilo ou xml (desde que use as ferramentas que mencionei acima), usando o elemento de interface do usuário personalizado com.innovattic.font.FontTextViewem seu layout xml. Abaixo, você pode ver como pode aplicar uma fonte a todos os textos em todo o seu aplicativo, apenas editando res/values/styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

    <!-- Application theme -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
        <item name="android:textViewStyle">@style/MyTextViewStyle</item>
    </style>

    <!-- Style to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextViewStyle" parent="@android:style/Widget.Holo.Light.TextView">
        <item name="android:textAppearance">@style/MyTextAppearance</item>
    </style>

    <!-- Text appearance to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextAppearance" parent="@android:style/TextAppearance.Holo">
        <!-- Alternatively, reference this font with the name "aspergit" -->
        <!-- Note that only our own TextView's will use the font attribute -->
        <item name="flFont">someFont</item>
        <item name="android:textStyle">bold|italic</item>
    </style>

    <!-- Alternative style, maybe for some other widget -->
    <style name="StylishFont">
        <item name="flFont">anotherFont</item>
        <item name="android:textStyle">normal</item>
    </style>

</resources>

Com o acompanhamento res/layout/layout.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- This text view is styled with the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This uses my font in bold italic style" />

    <!-- This text view is styled here and overrides the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:flFont="anotherFont"
        android:textStyle="normal"
        android:text="This uses another font in normal style" />

    <!-- This text view is styled with a style and overrides the app theme -->
    <com.innovattic.font.FontTextView
        style="@style/StylishFont"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This also uses another font in normal style" />

</LinearLayout>

Não se esqueça de aplicar o tema em seu manifesto Android.

Jelle Fresen
fonte
2

Eu gostaria de adicionar uma observação à ótima solução de leocadiotine. É perfeito, mas ao usar este TextView Customizado muitas vezes desacelera a aplicação, pois ele tem que acessar os ativos toda vez que um TextView é criado. Sugiro usar algo como View Holder patternno Adapters, escrevi um exemplo:

public class Fonts {

    private static final Map<String, Typeface> typefaces = new HashMap<String, Typeface>();

    public static Typeface getTypeface(Context ctx, String fontName) {
        Typeface typeface = typefaces.get(fontName);
        if (typeface == null) {
            typeface = Typeface.createFromAsset(ctx.getAssets(), fontName);
            typefaces.put(fontName, typeface);
        }
        return typeface;
    } 
}

Dessa forma, o aplicativo acessa os ativos apenas uma vez por ativo e os mantém na memória para necessidades futuras.

Emaboursa
fonte
0

Não sei se isso muda todo o aplicativo, mas consegui mudar alguns componentes que não poderiam ser alterados ao fazer isto:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Lucida Sans Unicode.ttf");
Typeface.class.getField("DEFAULT").setAccessible(true);
Typeface.class.getField("DEFAULT_BOLD").setAccessible(true);
Typeface.class.getField("DEFAULT").set(null, tf);
Typeface.class.getField("DEFAULT_BOLD").set(null, tf);
Richard
fonte
@richard, quero definir a fonte personalizada de acordo com a localidade. Por exemplo, desejo definir o Arial TTF sempre que usarmos a localidade em inglês e definir o TTF gótico quando usar o coreano loacale
Dwivedi Ji
0

Encontrei informações passo a passo neste link: https://github.com/jaydipumaretiya/CustomTypeface/

Há muitas maneiras de usar o tipo de letra corretamente no android, você tem que colocar o arquivo de tipo de letra na pasta de ativos em seu principal diretamente e pode usá-lo em tempo de execução.

Outra maneira mais simples é usar a biblioteca padrão para definir o tipo de letra em seu arquivo xml. Eu prefiro esta biblioteca de fonte personalizada para definir a fonte para TextView, EditText, Button, CheckBox, RadioButton e AutoCompleteTextView e outros wedget no Android.

Mehul Rakholiya
fonte
O link do github não está funcionando.
Thomas
0

O Android 8.0 (API de nível 26) apresenta um novo recurso, Fonts in XML. Você pode criar um arquivo fontfamily e configurá-lo em styles.xml.

Para adicionar fontes como recursos, execute as seguintes etapas no Android Studio:

1. Clique com o botão direito na pasta res e vá para Novo> diretório de recursos do Android. A janela Novo diretório de recursos é exibida.

2. Na lista Tipo de recurso, selecione a fonte e clique em OK. Observação: o nome do diretório de recursos deve ser fonte.

3.Adicione seus arquivos de fontes na pasta de fontes.

Para criar uma família de fontes, execute as seguintes etapas:

1. Clique com o botão direito na pasta de fontes e vá para Novo> Arquivo de recursos de fonte. A janela Novo arquivo de recurso é exibida.

2.Insira o nome do arquivo e clique em OK. O novo recurso de fonte XML é aberto no editor.

3. Inclua cada arquivo de fonte, estilo e atributo de peso no elemento. O seguinte XML ilustra a adição de atributos relacionados à fonte no XML do recurso de fonte:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
    <font
        android:fontStyle="normal"
        android:fontWeight="400"
        android:font="@font/lobster_regular" />
    <font
        android:fontStyle="italic"
        android:fontWeight="400"
        android:font="@font/lobster_italic" />
</font-family>

Adicionando fontes ao estilo

Abra o styles.xml e defina o atributo fontFamily para o arquivo de fonte que deseja acessar.

 <style name="customfontstyle" parent="@android:style/TextAppearance.Small">
    <item name="android:fontFamily">@font/lobster</item>
</style>

Fonte: Fontes em XML

Desenvolvedor Android
fonte