Jak zmienić czcionkę w TextView?

Odpowiedzi:

342

Po pierwsze, domyślną wartością nie jest Arial. Domyślnie jest to Droid Sans.

Po drugie, aby zmienić na inną wbudowaną czcionkę, użyj android:typefacew układzie XML lub setTypeface()w Javie.

Po trzecie, w systemie Android nie ma czcionki Helvetica. Wbudowane opcje to Droid Sans ( sans), Droid Sans Mono ( monospace) i Droid Serif ( serif). Chociaż możesz łączyć własne czcionki z aplikacją i używać ich za pośrednictwem setTypeface(), pamiętaj, że pliki czcionek są duże i, w niektórych przypadkach, wymagają umów licencyjnych (np. Helvetica, czcionka Linotype ).

EDYTOWAĆ

Język projektowania Androida opiera się na tradycyjnych narzędziach typograficznych, takich jak skala, przestrzeń, rytm i wyrównanie względem leżącej poniżej siatki. Pomyślne wdrożenie tych narzędzi jest niezbędne, aby pomóc użytkownikom szybko zrozumieć ekran informacji. Aby wesprzeć takie wykorzystanie typografii, Ice Cream Sandwich wprowadził nową rodzinę typów o nazwie Roboto, stworzoną specjalnie pod kątem wymagań interfejsu użytkownika i ekranów o wysokiej rozdzielczości.

Obecna struktura TextView oferuje Roboto w cienkich, lekkich, regularnych i odważnych wzorach, a także kursywą dla każdej wagi. Ramy oferują również wariant Roboto Condensed w odważnikach regularnych i odważnych, a także kursywą dla każdej masy.

Po ICS, Android zawiera styl czcionek Roboto, Czytaj więcej Roboto

EDYCJA 2

Wraz z pojawieniem się biblioteki pomocy technicznej 26 system Android domyślnie obsługuje niestandardowe czcionki. Możesz wstawiać nowe czcionki w res / fonts, które można ustawić na TextViews indywidualnie, zarówno w formacie XML, jak i programowo. Domyślną czcionką dla całej aplikacji można także zmienić poprzez określenie to styles.xml Dokumentacja dewelopera android ma jasnych wskazówek na ten temat tutaj

CommonsWare
źródło
6
Nie możesz ustawić czcionek w XML? Czemu?
Jonny
5
@Jonny Naprawdę możesz. Tworzysz klasę, która rozszerza TextView i wywołuje setTypeface z konstruktora.
Mark Phillip
jak to zrobić w układzie XML?
M. Usman Khan
2
@usman: Potrzebujesz biblioteki innej firmy, takiej jak Calligraphy: github.com/chrisjenx/Calligraphy
CommonsWare
Ustawienie kroju pisma przy użyciu kodu Java jest trudne ze względu na wiele wierszy. Utworzyłem bibliotekę, aby ustawić niestandardowe czcionki. Wykorzystanie biblioteki można znaleźć w tej odpowiedzi stackoverflow.com/a/42001474/4446392
Chathura Jayanath
254

Najpierw pobierz .ttfplik potrzebnej czcionki ( arial.ttf). Umieść go w assets folderze. (Wewnątrz folderu zasobów utwórz nowy folder o nazwie czcionki i umieść go w nim.) Użyj następującego kodu, aby zastosować czcionkę do TextView:

Typeface type = Typeface.createFromAsset(getAssets(),"fonts/arial.ttf"); 
textView.setTypeface(type);
HjK
źródło
Drogi Mayur, masz jakieś zalecenia, skąd wziąć te pliki .ttf?
samotnik
3
Drogi @lonelearner, możesz pobrać darmowe pliki czcionek (.ttf) ze 1001freefonts.com lub po prostu google „Darmowe czcionki”
ymerdrengene
10
Dla tych, którzy korzystają z Android Studio i nie mogą znaleźć folderu „zasoby”, zobacz to pytanie . Krótka odpowiedź: src/main/assets/fonts/.
adamdport,
51
Typeface tf = Typeface.createFromAsset(getAssets(),
        "fonts/DroidSansFallback.ttf");
TextView tv = (TextView) findViewById(R.id.CustomFontText);
tv.setTypeface(tf);
Android Girl
źródło
33

Możesz stworzyć klasę statyczną, która będzie zawierać wszystkie czcionki. W ten sposób nie będziesz tworzyć czcionki wiele razy, co może mieć negatywny wpływ na wydajność . Upewnij się tylko, że utworzysz podfolder o nazwie „ czcionki ” w folderze „ zasoby ”.

Zrób coś takiego:

public class CustomFontsLoader {

public static final int FONT_NAME_1 =   0;
public static final int FONT_NAME_2 =   1;
public static final int FONT_NAME_3 =   2;

private static final int NUM_OF_CUSTOM_FONTS = 3;

private static boolean fontsLoaded = false;

private static Typeface[] fonts = new Typeface[3];

private static String[] fontPath = {
    "fonts/FONT_NAME_1.ttf",
    "fonts/FONT_NAME_2.ttf",
    "fonts/FONT_NAME_3.ttf"
};


/**
 * Returns a loaded custom font based on it's identifier. 
 * 
 * @param context - the current context
 * @param fontIdentifier = the identifier of the requested font
 * 
 * @return Typeface object of the requested font.
 */
public static Typeface getTypeface(Context context, int fontIdentifier) {
    if (!fontsLoaded) {
        loadFonts(context);
    }
    return fonts[fontIdentifier];
}


private static void loadFonts(Context context) {
    for (int i = 0; i < NUM_OF_CUSTOM_FONTS; i++) {
        fonts[i] = Typeface.createFromAsset(context.getAssets(), fontPath[i]);
    }
    fontsLoaded = true;

}
}

W ten sposób możesz pobrać czcionkę z dowolnego miejsca w aplikacji.

Daniel L.
źródło
1
Super koleś! To jest piękno OOP. Świetna robota! :)
Joshua Michael Wagoner
Jak korzystać z tej klasy?
Jack
Musisz umieścić ten kod w swoim projekcie, dostosować go do czcionek, a następnie użyć metody statycznej getTypeface (..) z dowolnego miejsca w aplikacji.
Daniel L.,
Użyłem podobnego rozwiązania, ale dodałem buforowanie w celu zwiększenia wydajności ... czy w każdym razie napotkałeś sytuację, w której czcionka działa na niektórych telefonach, a na innych nie?
RJFares
20

Najlepsza praktyka w historii

TextViewPlus.java:

public class TextViewPlus extends TextView {
    private static final String TAG = "TextView";

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

    public TextViewPlus(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setCustomFont(context, attrs);
    }

    private void setCustomFont(Context ctx, AttributeSet attrs) {
        TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
        String customFont = a.getString(R.styleable.TextViewPlus_customFont);
        setCustomFont(ctx, customFont);
        a.recycle();
    }

    public boolean setCustomFont(Context ctx, String asset) {
        Typeface typeface = null;
        try {
            typeface = Typeface.createFromAsset(ctx.getAssets(), asset);
        } catch (Exception e) {
            Log.e(TAG, "Unable to load typeface: "+e.getMessage());
            return false;
        }

        setTypeface(typeface);
        return true;
    }
}

attrs.xml: (Gdzie umieścić res / wartości )

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TextViewPlus">
        <attr name="customFont" format="string"/>
    </declare-styleable>
</resources>

Jak używać:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:foo="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <com.mypackage.TextViewPlus
        android:id="@+id/textViewPlus1"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:text="@string/showingOffTheNewTypeface"
        foo:customFont="my_font_name_regular.otf">
    </com.mypackage.TextViewPlus>
</LinearLayout>

Mam nadzieję, że to ci pomoże.

Hiren Patel
źródło
1
Dlaczego podklasowanie TextView jest najlepszą praktyką?
Stealth Rabbi
@Stealth Rabbi, tutaj możemy przekazać niestandardową czcionkę tylko przez xml, nie trzeba pisać specjalnego kodu Java dla każdego widoku tekstu.
Hiren Patel
Jest na to biblioteka. Wystarczy dodać czcionkę w folderze zasobów i zadeklarować ją w formacie XML. github.com/febaisi/CustomTextView
febaisi
Twoja biblioteka wygląda dobrze, ale jedynym problemem jest to, że jest dla Androida 21+
loloof64
@febaisi, jak widziałem w twoim przykładzie lib raw.githubusercontent.com/febaisi/CustomTextView/master/wiki/…
Mr.Q
17

Odpowiedzi powyżej są poprawne. Upewnij się, że utworzysz podfolder o nazwie „czcionki” w folderze „zasoby”, jeśli używasz tego fragmentu kodu.

VJ Vélan Solutions
źródło
1
Twój komentarz jest zbędny. Powyższe wyjaśnienie mówi dokładnie to, co powiedziałeś, a nawet więcej ...
Joshua Michael Wagoner
14

Kolejny sposób na konsolidację tworzenia czcionek ...

public class Font {
  public static final Font  PROXIMA_NOVA    = new Font("ProximaNovaRegular.otf");
  public static final Font  FRANKLIN_GOTHIC = new Font("FranklinGothicURWBoo.ttf");
  private final String      assetName;
  private volatile Typeface typeface;

  private Font(String assetName) {
    this.assetName = assetName;
  }

  public void apply(Context context, TextView textView) {
    if (typeface == null) {
      synchronized (this) {
        if (typeface == null) {
          typeface = Typeface.createFromAsset(context.getAssets(), assetName);
        }
      }
    }
    textView.setTypeface(typeface);
  }
}

A następnie użyć w swojej działalności ...

myTextView = (TextView) findViewById(R.id.myTextView);
Font.PROXIMA_NOVA.apply(this, myTextView);

Pamiętaj, ten podwójnie sprawdzony idiom blokujący z polem lotnym działa poprawnie tylko z modelem pamięci używanym w Javie 1.5+.

Chris Aitchison
źródło
Dlaczego ta odpowiedź ma tylko 1 głos w górę, a ta powyżej ma 15? Co sprawia, że ​​ten drugi jest lepszy? Wydaje mi się, że ten jest bardziej prosty przy użyciu zasady singletonu ...?
Koen Demonie
Właśnie zobaczyłem, że masz publicznego konstruktora, ustawię go jako prywatny, ponieważ nie potrzebujesz do niego dostępu. W każdym razie używasz wewnętrznych zmiennych czcionek ...
Koen Demonie
Absolutnie powinien być prywatny konstruktor. Dobrze zauważony :) Będzie edytować!
Chris Aitchison
12

Najlepszą praktyką jest korzystanie z Biblioteki obsługi systemu Android w wersji 26.0.0 lub nowszej.

KROK 1: dodaj plik czcionki

  1. W folderze res utwórz nowy słownik zasobów czcionek
  2. Dodaj plik czcionek ( .ttf , .orf )

Na przykład, gdy plik czcionek będzie helvetica_neue.ttf, który wygeneruje R.font.helvetica_neue

KROK 2: utwórz rodzinę czcionek

  1. W folderze czcionek dodaj nowy plik zasobów
  2. Załącz każdy plik czcionki, styl i atrybut wagi w elemencie.

Na przykład:

<?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/helvetica_neue" />
</font-family>

KROK 3: użyj go

W układach XML:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fontFamily="@font/my_font"/>

Lub dodaj czcionki do stylu:

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

Aby uzyskać więcej przykładów, możesz postępować zgodnie z dokumentacją:

Praca z czcionkami

Marek Rzeźniczek
źródło
7

Jest trochę stary, ale nieco poprawiłem klasę CustomFontLoader i chciałem się nim podzielić, aby był pomocny. Po prostu utwórz nową klasę za pomocą tego kodu.

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

public enum FontLoader {

ARIAL("arial"),
TIMES("times"),
VERDANA("verdana"),
TREBUCHET("trbuchet"),
GEORGIA("georgia"),
GENEVA("geneva"),
SANS("sans"),
COURIER("courier"),
TAHOMA("tahoma"),
LUCIDA("lucida");   


private final String name;
private Typeface typeFace;


private FontLoader(final String name) {
    this.name = name;

    typeFace=null;  
}

public static Typeface getTypeFace(Context context,String name){
    try {
        FontLoader item=FontLoader.valueOf(name.toUpperCase(Locale.getDefault()));
        if(item.typeFace==null){                
            item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");                 
        }           
        return item.typeFace;
    } catch (Exception e) {         
        return null;
    }                   
}
public static Typeface getTypeFace(Context context,int id){
    FontLoader myArray[]= FontLoader.values();
    if(!(id<myArray.length)){           
        return null;
    } 
    try {
        if(myArray[id].typeFace==null){     
            myArray[id].typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+myArray[id].name+".ttf");                       
        }       
        return myArray[id].typeFace;    
    }catch (Exception e) {          
        return null;
    }   

}

public static Typeface getTypeFaceByName(Context context,String name){      
    for(FontLoader item: FontLoader.values()){              
        if(name.equalsIgnoreCase(item.name)){
            if(item.typeFace==null){
                try{
                    item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");     
                }catch (Exception e) {          
                    return null;
                }   
            }
            return item.typeFace;
        }               
    }
    return null;
}   

public static void loadAllFonts(Context context){       
    for(FontLoader item: FontLoader.values()){              
        if(item.typeFace==null){
            try{
                item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");     
            }catch (Exception e) {
                item.typeFace=null;
            }   
        }                
    }       
}   
}

Następnie po prostu użyj tego kodu na swoim widoku tekstu:

 Typeface typeFace=FontLoader.getTypeFace(context,"arial");  
 if(typeFace!=null) myTextView.setTypeface(typeFace);
Alan
źródło
5

W końcu znalazłem bardzo łatwe rozwiązanie tego problemu.

  1. korzystaj z tych bibliotek pomocy technicznej na poziomie aplikacji ,

    compile 'com.android.support:appcompat-v7:26.0.2'
    compile 'com.android.support:support-v4:26.0.2'
  2. następnie utwórz katalog o nazwie „font” w folderze res

  3. umieść pliki czcionek (ttf) w tym katalogu czcionek, pamiętaj o konwencjach nazewnictwa [nazwa nie powinna zawierać żadnych znaków specjalnych, wielkich liter ani spacji ani tabulatorów]
  4. Następnie odwołaj się do tej czcionki z xml w ten sposób

            <Button
            android:id="@+id/btn_choose_employee"
            android:layout_width="140dp"
            android:layout_height="40dp"
            android:layout_centerInParent="true"
            android:background="@drawable/rounded_red_btn"
            android:onClick="btnEmployeeClickedAction"
            android:text="@string/searching_jobs"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:fontFamily="@font/times_new_roman_test"
            />

W tym przykładzie times_new_roman_test jest plikiem ttf czcionki z tego katalogu czcionek

Shamsul Arefin Sajib
źródło
4
import java.lang.ref.WeakReference;
import java.util.HashMap;

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

public class FontsManager {

    private static FontsManager instance;

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

    private static Context context;

    private FontsManager(final Context ctx) {
        if (context == null) {
            context = ctx;
        }
    }

    public static FontsManager getInstance(final Context appContext) {
        if (instance == null) {
            instance = new FontsManager(appContext);
        }
        return instance;
    }

    public static FontsManager getInstance() {
        if (instance == null) {
            throw new RuntimeException(
                    "Call getInstance(Context context) at least once to init the singleton properly");
        }
        return instance;
    }

    public Typeface getFont(final String assetName) {
        final WeakReference<Typeface> tfReference = typefaces.get(assetName);
        if (tfReference == null || tfReference.get() == null) {
            final Typeface tf = Typeface.createFromAsset(context.getResources().getAssets(),
                    assetName);
            typefaces.put(assetName, new WeakReference<Typeface>(tf));
            return tf;
        }
        return tfReference.get();
    }

}

W ten sposób możesz utworzyć widok, który dziedziczy z TextView i wywołuje setTypeface na swoim konstruktorze.

Charlie-Blake
źródło
1
Witaj, dlaczego używamy WeakReference do przechowywania obiektu TypeFace?
Leniwy,
3

Gdy twoja czcionka jest przechowywana w środku, res/asset/fonts/Helvetica.ttfużyj:

Typeface tf = Typeface.createFromAsset(getAssets(),"fonts/Helvetica.ttf"); 
txt.setTypeface(tf);

Lub, jeśli plik czcionek jest przechowywany w środku, res/font/helvetica.ttfużyj:

Typeface tf = ResourcesCompat.getFont(this,R.font.helvetica);
txt.setTypeface(tf);
Pankaj Lilan
źródło
2
Dzięki, szukaliśmy części, w której miałeś ją w folderze res!
Mikkel Larsen,
2

pobierz czcionkę z zasobu i ustaw na wszystkie dzieci

public static void overrideFonts(final Context context, final View v) {
    try {
        if (v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++) {
                View child = vg.getChildAt(i);
                overrideFonts(context, child);
         }
        } else if (v instanceof TextView ) {
            ((TextView) v).setTypeface(Typeface.createFromAsset(context.getAssets(),"DroidNaskh.ttf"));// "BKOODB.TTF"));
        }
    } catch (Exception e) {
 }
 } 
Manian Rezaee
źródło
2
  1. dodaj klasę FontTextView.java:


public class FontTextView extends TextView {
    String fonts[] = {"HelveticaNeue.ttf", "HelveticaNeueLight.ttf", "motschcc.ttf", "symbol.ttf"};

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

    public FontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (!isInEditMode()) {
            init(attrs);
        }

    }

    public FontTextView(Context context) {
        super(context);
        if (!isInEditMode()) {
            init(null);
        }
    }

    private void init(AttributeSet attrs) {
        if (attrs != null) {
            TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.FontTextView);
            if (a.getString(R.styleable.FontTextView_font_type) != null) {
                String fontName = fonts[Integer.valueOf(a.getString(R.styleable.FontTextView_font_type))];

                if (fontName != null) {
                    Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/" + fontName);
                    setTypeface(myTypeface);
                }
                a.recycle();
            }
        }
    }
}


  1. dodaj do biblioteki czcionek zasobów
    wprowadź opis zdjęcia tutaj


  1. dodaj do attrs.xml, Liczby powinny być w kolejności w klasie tablicowej.

    <declare-styleable name="FontTextView">
    <attr name="font_type" format="enum">
        <enum name="HelveticaNeue" value="0"/>
        <enum name="HelveticaNeueLight" value="1"/>
        <enum name="motschcc" value="2"/>
        <enum name="symbol" value="3"/>
    </attr>


  1. Wybierz czcionkę z listy
    wprowadź opis zdjęcia tutaj
David
źródło
Czy potrzebujesz utworzyć instancję tej klasy w MainActivity? Ponieważ to nic dla mnie nie zmienia.
Tobias Mayr
1

Android wykorzystuje czcionkę Roboto, która jest naprawdę ładnie wyglądająca, z kilkoma różnymi grubościami (zwykła, lekka, cienka, zagęszczona), które świetnie wyglądają na ekranach o wysokiej gęstości.

Sprawdź poniższy link, aby sprawdzić czcionki Roboto:

Jak korzystać z Roboto w układzie XML

Wracając do pytania, jeśli chcesz zmienić czcionkę dla wszystkich TextView / Button w swojej aplikacji , spróbuj dodać poniższy kod do pliku styles.xml, aby użyć czcionki Roboto-light :

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    ......
    <item name="android:buttonStyle">@style/MyButton</item>
    <item name="android:textViewStyle">@style/MyTextView</item>
</style>

<style name="MyButton" parent="@style/Widget.AppCompat.Button">
    <item name="android:textAllCaps">false</item>
    <item name="android:fontFamily">sans-serif-light</item>
</style>

<style name="MyTextView" parent="@style/TextAppearance.AppCompat">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

I nie zapomnij użyć „AppTheme” w pliku AndroidManifest.xml

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    ......
</application>
Kupiec
źródło
0

Może coś nieco prostszego:

public class Fonts {
  public static HashSet<String,Typeface> fonts = new HashSet<>();

  public static Typeface get(Context context, String file) {
    if (! fonts.contains(file)) {
      synchronized (this) {
        Typeface typeface = Typeface.createFromAsset(context.getAssets(), name);
        fonts.put(name, typeface);
      }
    }
    return fonts.get(file);
  }
}

// Usage
Typeface myFont = Fonts.get("arial.ttf");

(Uwaga: ten kod nie został przetestowany, ale ogólnie to podejście powinno działać dobrze).

przeł
źródło