Cách đặt họ phông chữ mặc định cho toàn bộ ứng dụng Android


282

Tôi đang sử dụng phông chữ Roboto trong ứng dụng của mình. Để đặt phông chữ tôi phải thêm android:fontFamily="sans-serif-light"vào mọi chế độ xem. Có cách nào để khai báo phông chữ Roboto là họ phông chữ mặc định cho toàn bộ ứng dụng không? Tôi đã thử như thế này nhưng nó dường như không hoạt động.

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

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

2
Điều này có thể giúp bạn: stackoverflow.com/a/16883281/1329733
Jacob R

2
Bây giờ bạn có thể chỉ định phông chữ tùy chỉnh ngay từ XML trong android studio 3.0 developer.android.com/guide/topics/ui/look-and-feel/
Bảy

Câu trả lời:


289

Câu trả lời là có.

Ánh sáng Roboto toàn cầu cho TextViewButtoncác lớp học:

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

Chỉ cần chọn kiểu bạn muốn từ danh sách Themes.xml , sau đó tạo kiểu tùy chỉnh của bạn dựa trên kiểu gốc. Cuối cùng, áp dụng phong cách như chủ đề của ứng dụng.

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

Nó sẽ chỉ hoạt động với các phông chữ tích hợp như Roboto, nhưng đó là câu hỏi. Đối với phông chữ tùy chỉnh (được tải từ tài sản chẳng hạn) phương pháp này sẽ không hoạt động.

EDIT 08/13/15

Nếu bạn đang sử dụng các chủ đề AppCompat, hãy nhớ xóa android: tiền tố. Ví dụ:

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

Lưu ý buttonStylekhông chứa android:tiền tố, nhưng textViewStylephải chứa tiền tố .


4
Bạn đã nhận được sans-serif-lightgiá trị từ đâu? Có một danh sách các giá trị hợp lệ cho fontFamilymột nơi nào đó? Tôi đã xem qua các tài liệu, cũng như các tệp chủ đề và kiểu trong nguồn Android và không thể tìm thấy gì.
Christopher Perry

34
điều này chỉ có thể áp dụng cho API cấp 16 .. tên "android: fontF Family" chỉ tồn tại ở cấp 16 trở lên .. có cách nào để làm điều đó cho API 14 không?
Lorenzo Barbagli

3
@LorenzoBarbagli, bạn có thể kiểm tra Thư pháp
Brais Gabin

10
Tôi phải làm gì nếu tôi có một phông chữ tùy chỉnh?
Rohit Tigga

2
có, tôi cũng muốn thêm phông chữ tùy chỉnh vào toàn bộ ứng dụng. Làm thế nào tôi có thể làm điều đó ?. Tôi có cần ghi đè TextView và thay thế tất cả TextView như được đề xuất trong câu trả lời đầu tiên không
John

144

Với việc phát hành Android Oreo, bạn có thể sử dụng thư viện hỗ trợ để đạt được mục tiêu này.

  1. Kiểm tra build.gradle ứng dụng của bạn nếu bạn có thư viện hỗ trợ > = 26.0.0
  2. Thêm " phông chữ thư mục " " vào thư mục tài nguyên của bạn và thêm phông chữ của bạn vào đó
  3. Tham khảo họ phông chữ mặc định của bạn theo kiểu chính của ứng dụng:

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

Kiểm tra https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html để biết thêm thông tin chi tiết.


9
Khi nhắm mục tiêu API 26+, đây phải là phương pháp được chấp nhận. Khi sử dụng Thư viện hỗ trợ , chỉ cần xóa android:tiền tố
webo80

2
nếu bạn chỉ sử dụng phiên bản chưa được chuẩn bị, nó sẽ ổn thôi. Tiền tố sẽ chỉ bị bỏ qua trên API <26
webo80

2
Điều này không đặt phông chữ ở mọi nơi ... ví dụ: nếu bạn có kiểu xuất phát từ Base.TextAppearance.AppCompatđó, nó không được sử dụng ở đó.
Ixx

3
@Ixx, làm thế nào để ghi đè lên các phong cách quá?
Primož Kralj

2
Cũng nhớ sử dụng AppCompatTextView khi nhắm mục tiêu api <26
Codelicy

37

Để thay đổi phông chữ ứng dụng của bạn, hãy làm theo các bước sau:

  1. Bên trong resthư mục tạo thư mục mới và gọi nó font.
  2. Chèn phông chữ của bạn .ttf / .otf trong thư mục phông chữ, Đảm bảo tên phông chữ chỉ là chữ thường và gạch dưới.
  3. Bên trong res-> values-> styles.xmlbên trong <resources>-> <style>thêm phông chữ của bạn <item name="android:fontFamily">@font/font_name</item>.

nhập mô tả hình ảnh ở đây

Bây giờ tất cả văn bản ứng dụng của bạn sẽ nằm trong tài khoản mà bạn thêm.


8
Trong khi sử dụng phông chữ tùy chỉnh, làm cách nào để thêm phông chữ đậm cùng với phông chữ thông thường?
Rajbir Shienh

Điều đó chỉ hoạt động với API cấp 26 trở lên, còn API 21 trở xuống thì sao?
zulkarnain shah

34

ĐỌC CẬP NHẬT DƯỚI ĐÂY

Tôi gặp vấn đề tương tự với việc nhúng một phông chữ mới và cuối cùng nó đã hoạt động với việc mở rộng TextView và đặt kiểu chữ bên trong.

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

Bạn phải thay đổi các phần tử TextView sau này thành từ trong mọi phần tử. Và nếu bạn sử dụng UI-Creator trong Eclipse, đôi khi anh ta không hiển thị TextViews đúng. Là thứ duy nhất phù hợp với tôi ...

CẬP NHẬT

Ngày nay tôi đang sử dụng sự phản chiếu để thay đổi kiểu chữ trong toàn bộ ứng dụng mà không cần mở rộng TextViews. Kiểm tra bài SO này

CẬP NHẬT 2

Bắt đầu với API cấp 26 và có sẵn trong 'thư viện hỗ trợ', bạn có thể sử dụng

android:fontFamily="@font/embeddedfont"

Thông tin khác: Phông chữ trong XML


25
Đây không phải là giải pháp. Tôi đang sử dụng nhiều chế độ xem khác nhau, không chỉ TextView. Tôi muốn đặt phông chữ một lần và quên nó đi. Ngoài ra, mã của bạn tạo đối tượng mới cho mọi TextView. Ít nhất khai báo trường là tĩnh để tải phông từ tài sản một lần.
tomrozb

2
... tốt, có một chức năng tìm và thay thế, hoạt động rất tốt trong trường hợp này
longi

1
Đây không phải là đi làm. Bạn không thể gọi getContext()khi biến tĩnh. Bạn nên triển khai nó theo cách đơn lẻ, nếu không, mã hiện tại sẽ không được biên dịch.
tomrozb

1
tôi hoàn nguyên cam kết cuối cùng.
longi

1
@tomrozb: D tôi mới nhận ra rằng những thay đổi nhanh nhất tôi đã làm là do ý kiến ​​của bạn! khi bạn có đủ điểm, bạn có thể tự mình tối ưu hóa ví dụ mã. nếu không chúng ta vẫn sẽ nói về chủ đề này trong một vài năm nữa, khi không ai quan tâm đến điện thoại thông minh nữa;)
longi

8

Thêm dòng mã này vào res / value / style.xml của bạn

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

toàn bộ phong cách sẽ trông như thế

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

thay đổi "circle_medium" thành tên phông chữ của riêng bạn ..


6

Không nói về hiệu suất, đối với phông chữ tùy chỉnh, bạn có thể có một vòng lặp phương thức đệ quy thông qua tất cả các khung nhìn và đặt kiểu chữ nếu đó là 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");
    }
}

Trong tất cả hoạt động của bạn, hãy chuyển Viewgroup hiện tại cho nó sau khi setContentView và hoàn thành:

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

Đối với mảnh bạn có thể làm một cái gì đó tương tự.


1
Âm thanh tuyệt vời nhưng tự hỏi làm thế nào để làm cho nó hoạt động trong nội dung recyclerView?
Srujan Barai

Tôi chỉ thử điều này. quá nặng để kết xuất Chậm lại recyclerViewnhư địa ngục.
Srujan Barai

Hoàn toàn không được khuyến nghị cho bất kỳ chế độ xem danh sách, thủ thuật này chỉ để tiết kiệm thời gian để mã hóa chế độ xem tĩnh.
Allen Chan

5

Một cách khác để làm điều này cho toàn bộ ứng dụng là sử dụng sự phản chiếu dựa trên câu trả lời này

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

sau đó bất cứ khi nào bạn muốn ghi đè các phông chữ, bạn chỉ cần gọi phương thức và cung cấp cho nó một bản đồ các kiểu chữ như sau:

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

để kiểm tra ví dụ đầy đủ

Điều này chỉ hoạt động cho Android SDK 21 trở lên cho các phiên bản trước kiểm tra ví dụ đầy đủ


5

Chỉ cần sử dụng lib này biên dịch nó trong tập tin lớp của bạn

complie'me.anwarshahriar:calligrapher:1.0'

và sử dụng nó trong phương thức onCreate trong hoạt động chính

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

Đây là cách siêu nhanh thanh lịch nhất để làm điều đó.


2

Đây là công việc cho dự án của tôi, nguồn https://gist.github.com/artem-zinnatullin/7749076

Tạo thư mục phông chữ trong Thư mục tài sản và sau đó sao chép phông chữ tùy chỉnh của bạn vào thư mục phông chữ, ví dụ tôi đang sử dụng trebuchet.ttf;

Tạo một lớp 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) {

        }
    }
}

Chỉnh sửa chủ đề trong style.xml thêm bên dưới

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

Ví dụ trong 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>

Cuối cùng, trong Activity hoặc Fragment onCreate, hãy gọi typefaceUtil.java

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

0

Android không cung cấp nhiều cách hỗ trợ cho việc áp dụng phông chữ trên toàn bộ ứng dụng (xem vấn đề này ). Bạn có 4 tùy chọn để đặt phông chữ cho toàn bộ ứng dụng:

  • Tùy chọn 1: Áp dụng phản chiếu để thay đổi phông chữ hệ thống
  • Tùy chọn 2: Tạo và phân lớp tùy chỉnh Xem các lớp cho mỗi Chế độ xem cần phông chữ tùy chỉnh
  • Tùy chọn 3: Triển khai Trình thu thập dữ liệu xem qua phân cấp chế độ xem cho màn hình hiện tại
  • Tùy chọn4: Sử dụng thư viện của bên thứ 3.

Chi tiết về các tùy chọn này có thể được tìm thấy ở đây .


0

Tôi biết câu hỏi này khá cũ, nhưng tôi đã tìm thấy một giải pháp tốt đẹp. Về cơ bản, bạn chuyển một bố cục bộ chứa cho chức năng này và nó sẽ áp dụng phông chữ cho tất cả các chế độ xem được hỗ trợ và cicle đệ quy trong bố cục con:

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

0

để chỉ đơn thuần là thiết lập kiểu chữ của ứng dụng normal, sans, serifhoặc monospace(không một phông chữ tùy chỉnh!), bạn có thể làm điều này.

xác định một chủ đề và đặt android:typefacethuộc tính thành kiểu chữ bạn muốn sử dụng trong 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>

áp dụng chủ đề cho toàn bộ ứng dụng trong AndroidManifest.xmltệp:

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

tài liệu tham khảo android


Bạn có chắc rằng nó hoạt động? Theo tài liệu Android: "Phải là một trong những giá trị không đổi sau: bình thường, sans, serif, monospace".
tomrozb

1
Ồ tôi hiểu rồi ... bạn nói đúng ... tôi không hiểu câu hỏi gì cả: x Tôi chỉ muốn có toàn bộ ứng dụng của mình để sử dụng phông chữ đơn cách (không phải tùy chỉnh) và tôi thấy nó hoạt động nên tôi đã đăng nó ở đây ......... tôi nghĩ rằng câu trả lời của tôi vẫn có thể hữu ích cho những người khác muốn làm điều gì đó tương tự .... vì vậy tôi sẽ chỉnh sửa nó và để nó ở đây ..... tôi ổn tích lũy phiếu bầu. cảm ơn vì đã chỉ ra điều đó
Eric

Này @Dave Cruise, nó chỉ hoạt động cho không gian vũ trụ? Tôi chỉ thử nghiệm nó cho không gian vũ trụ ... và không có gì khác .... vì vậy tôi không chắc chắn ... nhưng theo tài liệu, nó sẽ hoạt động cho "bình thường", "sans" và "serif" quá .. .i nghĩ kiểu chữ chung chung hơn phông chữ, vì vậy chúng tôi không thể sử dụng nó để đặt phông chữ của ứng dụng thành một phông chữ cụ thể như "consolas" hoặc một cái gì đó.
Eric

@Eric yea. tôi cũng không có ý kiến ​​gì monospace hoạt động như một lá bùa nhưng không có may mắn cho bình thường, sans hoặc serif.
Dave Cruise

0

Hãy thử thư viện này, nó nhẹ và dễ thực hiện

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

-7

Câu trả lời là không, bạn không thể. Xem Có thể đặt phông chữ tùy chỉnh cho toàn bộ ứng dụng không? để biết thêm thông tin.

Có cách giải quyết, nhưng không có gì trong dòng "một dòng mã ở đây và tất cả các phông chữ của tôi sẽ là cái này thay vì cái đó ".

(Tôi cảm ơn Google - và Apple - vì điều đó). Phông chữ tùy chỉnh có một vị trí, nhưng làm cho chúng dễ dàng thay thế ứng dụng rộng, sẽ tạo ra cả một thế giới ứng dụng Comic Sans )


41
Hoàn toàn không đồng ý với bình luận của bạn. Thiết lập một phông chữ trên toàn cầu nên là việc nhỏ, không phải là việc đòi hỏi các cách giải quyết cần thiết. Tùy thuộc vào các nhà phát triển / nhà thiết kế trên thế giới để tránh các ứng dụng "Comic Sans", chứ không phải Google / Apple để thực thi điều đó.
LocalPCGuy

4
Tính nhất quán> Thiết kế lạ mắt.
Martin Marconcini

14
Tuy nhiên, tính nhất quán <chức năng. Chúng tôi phát triển các ứng dụng hiển thị tiếng Do Thái trong Kinh thánh. Tất cả các phông chữ chứng khoán được tìm thấy trên các thiết bị Android (bao gồm các phông chữ Android L mới nhất) thực hiện một công việc tuyệt vời là hiển thị các dấu hiệu chói tai (và chúng thực hiện một công việc tầm thường trên các nguyên âm, mặc dù chúng đang trở nên tốt hơn). Chúng tôi hoàn toàn cần sử dụng một phông chữ tùy chỉnh trong toàn bộ ứng dụng của mình và chúng tôi đã phải viết quá nhiều mã đơn giản để có được tất cả các chế độ xem cần thiết bằng cách sử dụng nó.
Ted Hopp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.