Cara mengatur keluarga font default untuk seluruh aplikasi Android

282

Saya menggunakan font ringan Roboto di aplikasi saya. Untuk mengatur font saya harus menambahkan android:fontFamily="sans-serif-light"ke setiap tampilan. Apakah ada cara untuk mendeklarasikan font Roboto sebagai keluarga font default untuk seluruh aplikasi? Saya sudah mencoba seperti ini tetapi sepertinya tidak berhasil.

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

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>
Tomrozb
sumber
2
Ini mungkin membantu Anda: stackoverflow.com/a/16883281/1329733
Jacob R
2
Anda sekarang dapat menentukan font khusus langsung dari XML di android studio 3.0 developer.android.com/guide/topics/ui/look-and-feel/…
Seven

Jawaban:

289

Jawabannya iya.

Global Roboto light untuk TextViewdan Buttonkelas:

<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>

Cukup pilih gaya yang Anda inginkan dari daftar themes.xml , lalu buat gaya kustom Anda berdasarkan yang asli. Pada akhirnya, terapkan gaya sebagai tema aplikasi.

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

Ini hanya akan berfungsi dengan font bawaan seperti Roboto, tapi itu pertanyaannya. Untuk font khusus (misalnya, diambil dari aset) metode ini tidak akan berfungsi.

EDIT 08/13/15

Jika Anda menggunakan tema AppCompat, ingatlah untuk menghapus android:awalan. Sebagai contoh:

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

Perhatikan buttonStyletidak mengandung android:awalan, tetapi textViewStyleharus memuatnya.

Tomrozb
sumber
4
Dari mana Anda mendapatkan sans-serif-lightnilainya? Apakah ada daftar nilai yang valid untuk fontFamilysuatu tempat? Saya telah melihat-lihat dokumen, serta file tema dan gaya di sumber Android dan tidak dapat menemukan apa pun.
Christopher Perry
34
ini hanya mungkin untuk API level 16 .. nama "android: fontFamily" hanya ada di level 16 atau di atas .. apakah ada cara untuk melakukannya juga untuk API 14 misalnya?
Lorenzo Barbagli
3
@LorenzoBarbagli, Anda dapat memeriksa Kaligrafi
Brais Gabin
10
Nah apa yang harus saya lakukan jika saya memiliki font khusus?
Rohit Tigga
2
ya ,, Saya juga ingin menambahkan font khusus ke seluruh aplikasi. Bagaimana saya bisa melakukan itu? Apakah saya perlu mengganti TextView dan mengganti semua TextView seperti yang disarankan dalam jawaban pertama
John
145

Dengan rilis Android Oreo Anda dapat menggunakan perpustakaan dukungan untuk mencapai tujuan ini.

  1. Periksa build.gradle aplikasi Anda jika Anda memiliki perpustakaan dukungan > = 26.0.0
  2. Tambahkan " font " folder ke folder sumber daya Anda dan tambahkan font Anda di sana
  3. Referensi keluarga font default Anda dalam gaya utama aplikasi Anda:

    <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>

Periksa https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html untuk informasi lebih lanjut.

João Magalhães
sumber
9
Saat menargetkan API 26+, ini harus menjadi metode yang diterima. Saat menggunakan Perpustakaan Dukungan , hapus saja android:awalan
webo80
2
jika Anda hanya menggunakan versi yang tidak diperbaiki, tidak apa-apa. Yang diawali hanya akan diabaikan di API <26
webo80
2
Ini tidak mengatur font di mana-mana ... misalnya jika Anda memiliki gaya yang berasal dari Base.TextAppearance.AppCompat, itu tidak digunakan di sana.
Ixx
3
@Ixx, bagaimana cara mengganti gaya-gaya itu juga?
Primož Kralj
2
Ingatlah untuk juga menggunakan AppCompatTextView ketika menargetkan api <26
Codelicious
37

Untuk mengubah font aplikasi Anda ikuti langkah-langkah berikut:

  1. resDirektori di dalam membuat direktori baru dan menyebutnya font.
  2. Masukkan font .ttf / .otf Anda di dalam folder font, Pastikan nama font huruf kecil dan garis bawah saja.
  3. Di dalam res-> values-> styles.xmldi dalam <resources>-> <style>tambahkan font Anda <item name="android:fontFamily">@font/font_name</item>.

masukkan deskripsi gambar di sini

Sekarang semua teks aplikasi Anda harus dalam sumber yang Anda tambahkan.

orang
sumber
8
saat menggunakan font khusus, bagaimana cara menambahkan huruf tebal bersama font biasa?
Rajbir Shienh
Itu hanya berfungsi dengan API level 26 dan di atasnya, bagaimana dengan API 21 dan di bawah?
zulkarnain shah
34

BACA PEMBARUAN DI BAWAH INI

Saya memiliki masalah yang sama dengan menanamkan font baru dan akhirnya berhasil bekerja dengan memperluas TextView dan mengatur typefont di dalamnya.

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);
    }
}

Anda harus mengubah Elemen TextView nanti menjadi dari ke dalam setiap elemen. Dan jika Anda menggunakan UI-Creator di Eclipse, kadang-kadang dia tidak menunjukkan TextViews dengan benar. Adalah satu-satunya yang bekerja untuk saya ...

MEMPERBARUI

Saat ini saya menggunakan refleksi untuk mengubah tipografi di seluruh aplikasi tanpa memperluas TextViews. Lihatlah pos SO ini

PEMBARUAN 2

Dimulai dengan API Level 26 dan tersedia di 'perpustakaan dukungan' yang dapat Anda gunakan

android:fontFamily="@font/embeddedfont"

Informasi lebih lanjut: Font dalam XML

longi
sumber
25
Ini bukan solusinya. Saya menggunakan banyak tampilan berbeda, tidak hanya TextView. Saya ingin mengatur font sekali dan melupakannya. Selain itu, kode Anda membuat objek baru untuk setiap TextView. Setidaknya nyatakan bidang sebagai statis untuk memuat font dari aset satu kali.
tomrozb
2
... well, ada fungsi temukan dan ganti, yang berfungsi sangat baik dalam kasus ini
longi
1
Ini tidak akan berhasil. Anda tidak dapat menelepon getContext()saat variabelnya statis. Anda harus mengimplementasikannya dengan cara singleton, jika tidak, kode saat ini bahkan tidak dapat dikompilasi.
tomrozb
1
saya mengembalikan komit terakhir.
longi
1
@ Tomrozb: D Saya baru menyadari, bahwa perubahan cepat terakhir yang saya lakukan, adalah karena komentar Anda! karena Anda memiliki cukup poin, Anda dapat mengoptimalkan sendiri contoh kode. kalau tidak, kita masih akan berbicara tentang topik dalam beberapa tahun, ketika tidak ada lagi yang peduli dengan smartphone;)
longi
8

Tambahkan baris kode ini di res / value / styles.xml Anda

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

seluruh gaya akan terlihat seperti itu

<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>

ubah "circular_medium" menjadi nama font Anda sendiri ..

nirazverma
sumber
6

Tidak berbicara tentang kinerja, untuk font khusus Anda dapat memiliki loop metode rekursif melalui semua tampilan dan mengatur jenis huruf jika itu adalah 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");
    }
}

Di semua aktivitas Anda, sampaikan ViewGroup saat ini setelah setContentView dan selesai:

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

Untuk fragmen Anda dapat melakukan hal serupa.

Allen Chan
sumber
1
Kedengarannya hebat tetapi bertanya-tanya bagaimana cara membuatnya bekerja di konten recyclerView?
Srujan Barai
Saya baru saja mencoba ini. terlalu berat untuk diurai. Melambat recyclerViewseperti neraka.
Srujan Barai
Sama sekali tidak direkomendasikan untuk tampilan daftar apa pun, trik ini hanya untuk menghemat waktu untuk mengkodekan tampilan statis.
Allen Chan
5

Cara lain untuk melakukan ini untuk seluruh aplikasi adalah menggunakan refleksi berdasarkan jawaban ini

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);
        }
    }
}

maka setiap kali Anda ingin mengganti font, Anda bisa memanggil metode dan memberikannya peta tipografi sebagai berikut:

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);

untuk contoh cek lengkap

Ini hanya berfungsi untuk Android SDK 21 ke atas untuk versi sebelumnya, periksa contoh lengkapnya

Ismail Almetwally
sumber
5

Cukup gunakan lib ini kompilasi di file kelas Anda

complie'me.anwarshahriar:calligrapher:1.0'

dan menggunakannya dalam metode onCreate dalam aktivitas utama

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

Ini adalah cara super cepat yang paling elegan untuk melakukan itu.

Mohamed Ayed
sumber
2

Ini berfungsi untuk proyek saya, sumber https://gist.github.com/artem-zinnatullin/7749076

Buat direktori font di dalam Folder Aset dan kemudian salin font khusus Anda ke direktori font, misalnya saya menggunakan trebuchet.ttf;

Buat kelas 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) {

        }
    }
}

Edit tema di styles.xml tambahkan di bawah

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

Contoh di My 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>

Terakhir, di Activity atau Fragment onCreate, panggil TypefaceUtil.java

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

Android tidak menyediakan banyak dukungan untuk penerapan font di seluruh aplikasi (lihat masalah ini ). Anda memiliki 4 opsi untuk mengatur font untuk seluruh aplikasi:

  • Opsi1: Terapkan refleksi untuk mengubah font sistem
  • Option2: Buat dan subkelas kelas tampilan kustom untuk setiap tampilan yang membutuhkan font khusus
  • Opsi3: Menerapkan View Crawler yang melintasi hierarki tampilan untuk layar saat ini
  • Option4: Gunakan perpustakaan pihak ke-3.

Detail opsi ini dapat ditemukan di sini .

Phileo99
sumber
0

Saya tahu pertanyaan ini sudah cukup lama, tetapi saya telah menemukan solusi yang bagus. Pada dasarnya, Anda meneruskan tata letak wadah ke fungsi ini, dan itu akan menerapkan font ke semua tampilan yang didukung, dan secara berulang berulang dalam tata letak anak:

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
sumber
0

untuk hanya set jenis huruf dari aplikasi untuk normal, sans, serifatau monospace(tidak font kustom!), Anda dapat melakukan hal ini.

tentukan tema dan atur android:typefaceatribut ke jenis huruf yang ingin Anda gunakan di 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>

terapkan tema ke seluruh aplikasi dalam AndroidManifest.xmlfile:

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

referensi android

Eric
sumber
Anda yakin itu berhasil? Menurut Android doc: "Harus salah satu dari nilai konstan berikut: normal, sans, serif, monospace".
tomrozb
1
Oh saya mengerti ... Anda benar ... saya tidak mengerti pertanyaannya: x Saya hanya ingin seluruh aplikasi saya menggunakan font monospace (tidak kustom) dan saya melihatnya berfungsi jadi saya memposting ini di sini ......... saya pikir jawaban saya masih bisa berguna bagi orang lain yang ingin melakukan sesuatu yang serupa .... jadi saya akan mengeditnya dan meninggalkannya di sini ..... saya baik-baik saja kan mengumpulkan suara. terima kasih telah menunjukkan itu
Eric
Hey @Dave Cruise, apakah ini hanya berfungsi untuk monospace? Saya hanya mengujinya untuk monospace ... dan tidak ada yang lain .... jadi saya tidak yakin ... tetapi menurut dokumentasi, itu harus bekerja untuk "normal", "sans" dan "serif" juga .. Saya pikir jenis huruf lebih umum daripada font, jadi kami tidak dapat menggunakannya untuk mengatur font aplikasi ke font tertentu seperti "konsol" atau sesuatu.
Eric
@ Ya ya. saya juga tidak tahu. monospace bekerja seperti mantra tetapi tidak beruntung untuk yang normal, tanpa atau serif.
Dave Cruise
0

Coba pustaka ini, ringan dan mudah diimplementasikan

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
sumber
-7

Jawabannya adalah tidak, Anda tidak bisa. Lihat Apakah mungkin untuk mengatur font khusus untuk seluruh aplikasi? untuk informasi lebih lanjut.

Ada beberapa solusi, tetapi tidak ada dalam baris "satu baris kode di sini dan semua font saya akan menjadi ini, bukan itu ".

(Saya agak berterima kasih kepada Google -dan Apple- untuk itu). Font khusus memiliki tempat, tetapi membuatnya mudah untuk menggantikan lebar aplikasi, akan menciptakan seluruh dunia aplikasi Comic Sans )

Martin Marconcini
sumber
41
Sepenuhnya tidak setuju dengan komentar Anda. Menyetel font secara global harus sepele untuk dilakukan, bukan sesuatu yang membutuhkan jenis solusi yang diperlukan. Terserah pengembang / perancang dunia untuk menghindari aplikasi "Sans Komik", bukan Google / Apple untuk menegakkan itu.
LocalPCGuy
4
Konsistensi> Desain mewah.
Martin Marconcini
14
Namun, konsistensi <fungsionalitas. Kami mengembangkan aplikasi yang menampilkan bahasa Ibrani alkitabiah. Semua fonta stok yang ditemukan pada perangkat Android (termasuk font Android L terbaru) melakukan pekerjaan yang sangat buruk dalam memberikan tanda cantillation (dan mereka melakukan pekerjaan yang biasa-biasa saja pada tanda vokal, dalam hal ini, meskipun mereka semakin baik). Kami benar-benar harus menggunakan font khusus di seluruh aplikasi kami, dan kami harus menulis terlalu banyak kode hanya untuk mendapatkan semua tampilan yang diperlukan menggunakannya.
Ted Hopp