Android: Muốn đặt phông chữ tùy chỉnh cho toàn bộ ứng dụng không phải thời gian chạy


100

Có thể đặt bất kỳ phông chữ tùy chỉnh nào trong mọi điều khiển của ứng dụng không? Và không nhất thiết phải thời gian chạy? (tức là từ xml nếu có thể hoặc chỉ một lần cho toàn bộ ứng dụng trong tệp JAVA)

Tôi có thể đặt phông chữ cho một điều khiển từ mã này.

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

    textView.setTypeface(tf);

}

Và vấn đề với mã này là nó phải được gọi cho mọi điều khiển. Và tôi muốn gọi phương thức này hoặc bất kỳ phương thức nào tương tự một lần, hoặc nếu có thể hãy đặt thuộc tính trong xml. Nó có khả thi không?


6
Có thể bạn có thể viết một điều khiển tùy chỉnh bằng cách mở rộng TextView và đặt phông chữ trong phương thức khởi tạo có thể là một tùy chọn, Sau đó, bạn có thể sử dụng điều khiển này trong toàn bộ ứng dụng thay thế cho textview của bạn. cũng để tiết kiệm bộ nhớ, u có thể ngăn tải tài nguyên bằng cách sử dụng kiểu chữ tĩnh.
Varun

@Varun: ý tưởng này có thể tiết kiệm thời gian của tôi, nhưng tôi phải đặt mọi điều khiển và viết điều khiển tùy chỉnh cho từng điều khiển sẽ là một cách lâu hơn so với đặt thời gian chạy phông chữ, bạn nghĩ sao? (Tuy nhiên +1 để viết điều khiển tùy chỉnh)
Prasham

Bạn có thể chỉ muốn viết một điều khiển tùy chỉnh mở rộng textView và sửa đổi duy nhất sẽ thiết lập kiểu chữ. Bằng cách sử dụng điều khiển cusotm trong các tệp bố cục của bạn, bạn không phải thực hiện thủ công trong thời gian dài cho mỗi lần xem văn bản và bạn vẫn có thể yên tâm rằng mình đang sử dụng phông chữ bạn muốn.
Varun

Viết một tập quán VIEWthay vì viết a custom text viewvà a custom button viewriêng lẻ thì sao? Yêu cầu của tôi là đối với mọi điều khiển và chế độ xem văn bản chỉ là một ví dụ. Xin lỗi, tôi quên đề cập đến nó .. :-(
Prasham

1
Hãy xem câu hỏi satckoverflow stackoverflow.com/questions/2711858/… nó sẽ giúp bạn.
Ashwini

Câu trả lời:


123

CHỈNH SỬA : Vì vậy, đã được một thời gian, và tôi muốn thêm những gì tôi nghĩ là cách tốt nhất để làm điều này, và thông qua XML không hơn không kém!

Vì vậy, trước tiên, bạn sẽ muốn tạo một lớp mới ghi đè bất kỳ Chế độ xem nào bạn muốn tùy chỉnh. (ví dụ: muốn một Nút có kiểu chữ tùy chỉnh? Mở rộng Button). Hãy làm một ví dụ:

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

Bây giờ, nếu bạn chưa có, hãy thêm tài liệu XML bên dưới res/values/attrs.xmlvà thêm:

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

Được rồi, vậy là xong, hãy quay lại parseAttributes()phương pháp trước đó:

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

Bây giờ bạn đã sẵn sàng. Bạn có thể thêm nhiều thuộc tính hơn cho bất kỳ thứ gì (bạn có thể thêm một thuộc tính khác cho typefaceStyle - đậm, nghiêng, v.v.) nhưng bây giờ hãy xem cách sử dụng nó:

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

Các xmlns:customdòng thực sự có thể được bất cứ điều gì, nhưng ước là những gì đang hiển thị ở trên. Điều quan trọng là nó là duy nhất và đó là lý do tại sao tên gói được sử dụng. Bây giờ bạn chỉ cần sử dụng custom:tiền tố cho các thuộc tính của mình và android:tiền tố cho các thuộc tính android.

Một điều cuối cùng: nếu bạn muốn sử dụng điều này trong một style ( res/values/styles.xml), bạn không nên thêm xmlns:customdòng. Chỉ cần tham chiếu tên của thuộc tính không có tiền tố:

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

                               (PREVIOUS ANSWER)

Sử dụng kiểu chữ tùy chỉnh trong Android

Điều này sẽ giúp ích. Về cơ bản, không có cách nào để làm điều này trong XML, và theo như tôi có thể nói, không có cách nào dễ dàng hơn để làm điều đó trong mã. Bạn luôn có thể có một phương thức setLayoutFont () tạo kiểu chữ một lần, sau đó chạy setTypeface () cho mỗi phương thức. Bạn chỉ cần cập nhật nó mỗi khi bạn thêm một mục mới vào bố cục. Một cái gì đó như dưới đây:

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

CHỈNH SỬA : Vì vậy, tôi chỉ cần tự mình thực hiện một cái gì đó như thế này, và cách tôi thực hiện nó là tạo ra một hàm như thế này:

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

Sau đó, chỉ cần sử dụng phương thức này từ onCreate () và chuyển tất cả các TextView bạn muốn cập nhật:

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

CHỈNH SỬA 9/5/12:

Vì vậy, vì điều này vẫn đang nhận được lượt xem và phiếu bầu, tôi muốn thêm một phương pháp tốt hơn và hoàn thiện hơn:

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

Nếu bạn chuyển nó vào thư mục gốc của bố cục, nó sẽ kiểm tra đệ quy TextViewhoặc các Buttonchế độ xem (hoặc bất kỳ người nào khác mà bạn thêm vào câu lệnh if đó) trong bố cục đó và đặt phông chữ mà bạn không cần phải chỉ định chúng theo ID. Tất nhiên, điều này giả sử bạn muốn đặt phông chữ cho mọi chế độ xem.


1
Tôi không thấy bất kỳ sự khác biệt nào trong mã của bạn và mã của tôi ngoại trừ tôi sử dụng phương thức này làm phương pháp ban đầu cho toàn bộ ứng dụng và mã của bạn dường như được viết cho một hoạt động. Tái bút thật là kỳ lạ khi thêm một đối tượng nữa cho một textView chỉ đọc chỉ để thay đổi phông chữ. Tắt Chủ đề: Android sẽ thực sự đưa ra một cơ chế để lấy một phông chữ từ thư mục Tài sản và được đưa vào R để nó có thể được thay đổi thời gian thiết kế)
Prasham

1
Tôi đoán trên thực tế không có sự khác biệt lớn nào ngoài việc bạn sẽ không tạo nhiều lần Kiểu chữ. Ý tưởng của Varun về việc chỉ sử dụng một kiểu chữ tĩnh sẽ làm được điều tương tự.
Kevin Coppock

1
Dòng cuối cùng của mã ví dụ của bạn phải là setLayoutFont (tf, tv1, tv2, tv3, tv4, tv5); chứ không phải setTypeface (tf, tv1, tv2, tv3, tv4, tv5) ;?
Kyle Clegg

1
Không nên bạn recyclesự TypedArray values?
CorayThan

1
Nếu sử dụng Gradle, không gian tên tùy chỉnh phải làxmlns:custom="http://schemas.android.com/apk/res-auto"
Jabari

93

Có một cách khá dễ dàng để thực hiện việc này thông qua XML. Bạn chỉ cần tạo tiện ích mở rộng TextView của riêng mình.

Đầu tiên, tạo một tệp trong res / values ​​/ attrs.xml với nội dung sau:

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

Sau đó, tạo tiện ích con tùy chỉnh của bạn:

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

}

Như bạn có thể thấy, đoạn mã trên sẽ đọc một phông chữ bên trong tài sản / thư mục. Đối với ví dụ này, tôi giả định rằng có một tệp được gọi là "custom.ttf" trong thư mục nội dung. Cuối cùng, hãy sử dụng tiện ích con trong XML:

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

Lưu ý: bạn sẽ không thể thấy phông chữ tùy chỉnh của mình trong trình chỉnh sửa bố cục của Eclipse. Đây là lý do tại sao tôi đặt isInEditMode()séc. Nhưng nếu bạn chạy ứng dụng của mình, phông chữ tùy chỉnh sẽ hoạt động như một sự quyến rũ.

Hy vọng nó giúp!


Tôi đã không thử điều này, nhưng tôi đã tạo điều khiển tùy chỉnh bằng cách mở rộng TextViewlớp; thiết lập typefacetrong đó và sử dụng các điều khiển tùy chỉnh trong cách bố trí như chúng ta thường làm & nó làm việc cho tôi ... Nó rất đơn giản, tuy nhiên, rằng ở trên một ...
Mahendra Liya

1
Tôi đã làm đúng những gì bạn nói. Sự khác biệt duy nhất là tôi đã làm cho thành phần này có thể tái sử dụng, vì câu hỏi đặt ra là làm thế nào để thực hiện điều này thông qua XML. Có thực sự là một cách để làm được điều này thông qua XML và đó là cách để làm điều đó :)
leocadiotine

Rất dễ dàng để tích hợp mã. Nó làm việc cho tôi. Cảm ơn.
Durai

1
Đây là câu trả lời được chấp nhận. Được viết đẹp. Cảm ơn!
Reaz bị nguyền rủa vào

1
Amesome, @DominikSuszczewicz! Bạn vui lòng share code để mình cập nhật đáp án được không?
leocadiotine

15

Ví dụ về TextView với kiểu chữ 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;
}

}

Ví dụ sử dụng:

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

Tài nguyên: Phông chữ Roboto & Noto


Tuy nhiên, có một cách để sử dụng giải pháp này mà không sửa id phông chữ trong lớp java? có thể đọc các trường cuối cùng này từ enum attrs .. private final static int ROBOTO_THIN = 0; private cuối cùng static int ROBOTO_THIN_ITALIC = 1; private cuối cùng static int ROBOTO_LIGHT = 2; ...
Arthur Melo

3

Đã quá muộn nhưng của tôi nó giúp ích cho người khác.
Tôi đã tạo CustomTextView có một thuộc tính gọi là typeFace và nó đang giải quyết vấn đề rò rỉ bộ nhớ khi tải kiểu chữ mà không có bộ nhớ đệm

FontsLớp đầu tiên chỉ tải phông chữ từ nội dung một lần

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

thì bạn cần thêm một thuộc tính tùy chỉnh trong attrs.xml, hãy thêm cái này

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

    </declare-styleable>

sau đó tùy chỉnh lớp

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

và cuối cùng thêm chế độ xem văn bản

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

và bạn có thể thay đổi phông chữ progrmaticlly bằng phương thức setTypeFace,
bạn cũng có thể di chuyển không gian tên tùy chỉnh sang bố cục mẹ nếu bạn muốn sử dụng nhiều hơn một từ chế độ xem này

Mã hóa vui vẻ :)


câu trả lời đơn giản.
eyadMhanna

2

Phương thức bên dưới, được gọi trong onCreate () và được truyền vào ViewGroup ngoài cùng của bạn, sẽ hoạt động cho mọi thứ trừ văn bản được tạo động (tức là danh sách động, cảnh báo, v.v.). Một cách dễ dàng để có được ViewGroup ngoài cùng là sử dụng getRootView trên bất kỳ chế độ xem nào của bạn.

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

    }

}

Điều này cũng sẽ hoạt động đối với nội dung động, bạn chỉ cần gọi nó, chuyển vào bất cứ thứ gì bạn đã tạo, ngay sau khi bạn tạo nó (mặc dù vậy, tôi chưa thử nghiệm điều này).

Để tiết kiệm bộ nhớ, có thể bạn sẽ muốn đặt kiểu chữ thành một biến tĩnh, thay vì tạo một biến mới mỗi khi vòng lặp chạy như tôi có ở đây.


Tôi không khuyến nghị giải pháp này, vì bạn đang tạo một phiên bản mới của cùng một phông chữ cho từng phần tử bạn muốn áp dụng nó. Điều này có thể gây ra các vấn đề về bộ nhớ.
hoàn mỹ

Điều đó được bao gồm trong ghi chú của tôi ở cuối.
Chris

2

Nếu bạn đang tìm kiếm một giải pháp chương trình tổng quát hơn, tôi đã tạo một lớp tĩnh có thể được sử dụng để đặt Kiểu chữ của toàn bộ chế độ xem (Giao diện người dùng hoạt động). Lưu ý rằng tôi đang làm việc với Mono (C #) nhưng bạn có thể triển khai dễ dàng bằng Java.

Bạn có thể chuyển cho lớp này một bố cục hoặc một dạng xem cụ thể mà bạn muốn tùy chỉnh. Nếu bạn muốn siêu hiệu quả, bạn có thể triển khai nó bằng cách sử dụng mẫu 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");
            }
        }

    }

Trong hoạt động của mình, bạn sẽ cần tạo một đối tượng Kiểu chữ. Tôi tạo của tôi trong OnCreate () bằng cách sử dụng tệp .ttf được đặt trong thư mục Tài nguyên / Tài sản / của tôi. Đảm bảo rằng tệp được đánh dấu là Nội dung Android trong thuộc tính 'của nó.

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

2

Thật không may, Android không cung cấp cách nhanh chóng, dễ dàng và rõ ràng mà bạn đang tìm kiếm để thay đổi phông chữ cho toàn bộ ứng dụng của mình. Nhưng gần đây tôi đã xem xét vấn đề này và tạo ra một số công cụ cho phép bạn thay đổi phông chữ mà không cần bất kỳ mã hóa nào (bạn có thể thực hiện tất cả thông qua xml, kiểu và thậm chí là xuất hiện văn bản). Chúng dựa trên các giải pháp tương tự như bạn thấy trong các câu trả lời khác ở đây, nhưng cho phép linh hoạt hơn nhiều. Bạn có thể đọc tất cả về nó trên blog này và xem dự án github tại đây .

Đây là một ví dụ về cách áp dụng các công cụ này. Đặt tất cả các tệp phông chữ của bạn vào assets/fonts/. Sau đó, khai báo các phông chữ đó trong tệp xml (ví dụ res/xml/fonts.xml) và tải tệp này sớm trong ứng dụng của bạn với TypefaceManager.initialize(this, R.xml.fonts);(ví dụ: trong lớp onCreate của ứng dụng của bạn). Tệp xml trông giống như sau:

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

Bây giờ bạn có thể sử dụng các phông chữ này theo phong cách của mình hoặc xml (miễn là bạn sử dụng các công cụ tôi đã đề cập ở trên), bằng cách sử dụng phần tử giao diện người dùng tùy chỉnh com.innovattic.font.FontTextViewtrong bố cục xml của bạn. Dưới đây, bạn có thể thấy cách bạn có thể áp dụng phông chữ cho tất cả văn bản trong toàn bộ ứng dụng của mình, chỉ bằng cách chỉnh sửa 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>

Với sự đi kèm 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>

Đừng quên áp dụng chủ đề trong tệp kê khai Android của bạn.


2

Tôi muốn thêm một lưu ý cho giải pháp tuyệt vời của leocadiotine. Nó là hoàn hảo, nhưng khi sử dụng TextView tùy chỉnh này nhiều lần sẽ làm chậm ứng dụng, vì nó phải truy cập nội dung mỗi khi một textview được tạo. Tôi đề nghị sử dụng một cái gì đó như View Holder patterntrong Adapters, tôi đã viết một ví dụ:

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

Bằng cách này, ứng dụng chỉ truy cập các nội dung một lần cho mỗi nội dung và nó sẽ giữ chúng trong bộ nhớ cho các nhu cầu tiếp theo.


0

Tôi không biết liệu nó có thay đổi toàn bộ ứng dụng hay không, nhưng tôi đã quản lý để thay đổi một số thành phần không thể thay đổi được bằng cách thực hiện điều này:

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, tôi muốn thiết lập phông chữ tùy chỉnh theo miền địa phương, Ví dụ, tôi muốn thiết lập các TTF Arial khi đã bao giờ chúng ta sử dụng locale tiếng Anh, và thiết lập các TTF gothic khi tôi sử dụng loacale Hàn Quốc
Dwivedi Ji

0

Tôi đã tìm thấy thông tin từng bước tại liên kết này, liên kết: https://github.com/jaydipumaretiya/CustomTypeface/

Có nhiều cách để sử dụng đúng kiểu chữ trong android, bạn phải đặt trực tiếp tệp kiểu chữ của mình vào thư mục nội dung dưới main của bạn và có thể sử dụng nó trong thời gian chạy.

Cách đơn giản khác là sử dụng thư viện mặc định để đặt kiểu chữ trong tệp xml của bạn. Tôi thích thư viện kiểu chữ tùy chỉnh này để đặt kiểu chữ thành TextView, EditText, Button, CheckBox, RadioButton và AutoCompleteTextView và wedget khác trong android.


Liên kết github không hoạt động.
Thomas

0

Android 8.0 (API cấp 26) giới thiệu một tính năng mới, Phông chữ trong XML. Bạn có thể tạo tệp fontfamily và đặt nó trong styles.xml.

Để thêm phông chữ làm tài nguyên, hãy thực hiện các bước sau trong Android Studio:

1. Nhấp chuột phải vào thư mục res và đi tới Mới> thư mục tài nguyên Android. Cửa sổ Thư mục Tài nguyên Mới xuất hiện.

2. trong danh sách Loại tài nguyên, chọn phông chữ, sau đó bấm OK. Lưu ý: Tên của thư mục tài nguyên phải là phông chữ.

3. Thêm tệp phông chữ của bạn vào thư mục phông chữ.

Để tạo họ phông chữ, hãy thực hiện các bước sau:

1. Nhấp chuột phải vào thư mục phông chữ và đi tới Mới> Tệp tài nguyên phông chữ. Cửa sổ Tệp Tài nguyên Mới xuất hiện.

Nhập tên tệp, sau đó bấm OK. Tài nguyên phông chữ mới XML sẽ mở ra trong trình chỉnh sửa.

3.Đóng từng tệp phông chữ, kiểu và thuộc tính trọng lượng trong phần tử. XML sau đây minh họa việc thêm các thuộc tính liên quan đến phông chữ trong tài nguyên phông chữ XML:

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

Thêm phông chữ vào kiểu

Mở styles.xml và đặt thuộc tính fontFamily thành tệp phông chữ bạn muốn truy cập.

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

Nguồn: Phông chữ trong XML

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.