Android : 런타임이 아닌 전체 애플리케이션에 대해 사용자 지정 글꼴을 설정하고 싶습니다.


100

응용 프로그램의 모든 컨트롤에서 사용자 지정 글꼴을 설정할 수 있습니까? 그리고 반드시 런타임은 아닙니다. (즉, 가능한 경우 xml에서 또는 JAVA 파일의 전체 응용 프로그램에 대해 한 번만)

이 코드에서 하나의 컨트롤에 대한 글꼴을 설정할 수 있습니다.

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

    textView.setTypeface(tf);

}

그리고이 코드의 문제점은 모든 컨트롤에 대해 호출되어야한다는 것입니다. 그리고이 메서드 또는 유사한 메서드를 한 번 호출하거나 가능한 경우 xml에서 속성을 설정하고 싶습니다. 가능할까요?


6
TextView를 확장하고 생성자에서 글꼴을 설정하여 사용자 지정 컨트롤을 작성할 수 있습니다. 그런 다음 텍스트보기 대신 앱 전체에서이 컨트롤을 사용할 수 있습니다. 또한 메모리를 절약하기 위해 정적 서체 유형을 사용하여 리소스로드를 방지 할 수 있습니다.
Varun

@Varun : 글쎄,이 아이디어는 내 시간을 절약 할 수 있지만 모든 컨트롤을 설정해야하며 각각에 대한 사용자 지정 컨트롤을 작성하는 것이 글꼴 런타임을 설정하는 것보다 더 긴 방법이 될 것입니다. 어떻게 생각하십니까? (그러나 사용자 지정 컨트롤을 작성하려면 +1)
Prasham

textView를 확장하는 사용자 지정 컨트롤을 하나만 작성하고 싶을 수 있으며 유일한 수정은 서체를 설정하는 것입니다. 레이아웃 파일에서 cusotm 컨트롤을 사용하면 각 textview에 대해 eveytime을 수동으로 수행 할 필요가 없으며 원하는 글꼴을 사용하고 있음을 여전히 확신 할 수 있습니다.
Varun

VIEWa custom text view와 a를 custom button view따로 작성하는 대신 사용자 정의 를 작성하는 것은 어떻습니까? 내 요구 사항은 모든 컨트롤에 대한 것이며 텍스트보기는 단지 예일뿐입니다. 죄송합니다, 나는 그것을 언급하는 것을 잊었다 ... :-(
Prasham

1
satckoverflow 질문 stackoverflow.com/questions/2711858/을 살펴보십시오 . 도움이됩니다.
애쉬 위니

답변:


123

편집 : 그래서 오랜만에 이것을 수행하는 가장 좋은 방법이라고 생각하는 것을 XML을 통해 추가하고 싶습니다!

따라서 먼저 사용자 정의하려는 뷰를 재정의하는 새 클래스를 만들고 싶을 것입니다. (예 : 사용자 정의 서체가있는 버튼을 원하십니까? 확장 Button). 예를 들어 보겠습니다.

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

이제 XML 문서가없는 경우 아래에 XML 문서를 res/values/attrs.xml추가하고 다음을 추가합니다.

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

자, 이제 그 parseAttributes()방법으로 이전 의 방법으로 돌아 갑시다 .

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

이제 모든 설정이 완료되었습니다. 무엇이든에 대해 더 많은 속성을 추가 할 수 있지만 (굵게, 기울임 꼴 등) typefaceStyle에 대해 다른 속성을 추가 할 수 있습니다. 이제 사용 방법을 살펴 보겠습니다.

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

xmlns:custom줄은 정말 아무것도 할 수 있지만 규칙은 위에 표시되는 것입니다. 중요한 것은 고유하다는 것이므로 패키지 이름이 사용됩니다. 이제 custom:속성에 접두사를 사용하고 android:Android 속성에 접두사를 사용합니다.

마지막으로, 스타일 ( res/values/styles.xml) 에서 이것을 사용 하려면 줄을 추가 하지 않아야 합니다 xmlns:custom. 접두사없이 속성 이름을 참조하십시오.

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

                               (PREVIOUS ANSWER)

Android에서 사용자 지정 서체 사용

이것은 도움이 될 것입니다. 기본적으로 XML로이 작업을 수행 할 수있는 방법이 없으며 내가 알 수있는 한 코드에서이 작업을 수행하는 더 쉬운 방법이 없습니다. 서체를 한 번 생성 한 다음 각각에 대해 setTypeface ()를 실행하는 setLayoutFont () 메서드를 항상 가질 수 있습니다. 레이아웃에 새 항목을 추가 할 때마다 업데이트하면됩니다. 아래와 같은 것 :

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

편집 : 그래서 나는 이것과 같은 것을 직접 구현하고 어떻게 끝 냈는지 다음과 같은 기능을 만드는 것으로 끝났습니다.

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

그런 다음 onCreate ()에서이 메서드를 사용하고 업데이트하려는 모든 TextView를 전달합니다.

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

9/5/12 수정 :

그래서 이것은 여전히 ​​조회수와 투표를 받고 있기 때문에 훨씬 더 좋고 완전한 방법을 추가하고 싶습니다.

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

레이아웃의 루트에 전달하면 해당 레이아웃 내에서 TextView또는 Button뷰 (또는 if 문에 추가 한 다른 항목)를 재귀 적으로 확인 하고 ID로 지정할 필요없이 글꼴을 설정합니다. 물론 이것은 모든 뷰에 글꼴을 설정하고 싶다고 가정합니다 .


1
전체 응용 프로그램에 대한 팩토리 방법으로 메서드를 사용하고 코드가 하나의 활동에 대해 작성된 것처럼 보이는 것을 제외하고는 코드와 코드에 차이가 없습니다. 추신 : 글꼴을 변경하기 위해 읽기 전용 textView에 대한 개체를 하나 더 추가하는 것은 정말 이상합니다. Off Topic : Android는 실제로 assests 폴더에서 글꼴을 가져오고 R에 포함되어 디자인 타임을 변경할 수있는 메커니즘을 도입해야합니다.)
Prasham

1
현실적으로 서체를 반복해서 만들지 않는 것 외에는 큰 차이가 없다고 생각합니다. 정적 인 서체를 사용하는 Varun의 아이디어는 똑같은 일을 할 것입니다.
Kevin Coppock 2010

1
예제 코드의 마지막 줄이 setLayoutFont (tf, tv1, tv2, tv3, tv4, tv5); setTypeface (tf, tv1, tv2, tv3, tv4, tv5);가 아니라?
Kyle Clegg 2012

1
당신 recycle은 안 TypedArray values그래?
CorayThan

1
Gradle을 사용하는 경우 사용자 정의 네임 스페이스는xmlns:custom="http://schemas.android.com/apk/res-auto"
Jabari 2014

93

XML을 통해이 작업을 수행하는 매우 쉬운 방법이 있습니다. TextView를 확장하는 자체 위젯을 생성하기 만하면됩니다.

먼저 res / values ​​/ attrs.xml에 다음 내용으로 파일을 만듭니다.

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

그런 다음 사용자 정의 위젯을 만듭니다.

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

}

보시다시피 위 코드는 assets / 폴더 내의 글꼴을 읽습니다. 이 예에서는 assets 폴더에 "custom.ttf"라는 파일이 있다고 가정합니다. 마지막으로 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" />

참고 : Eclipse의 레이아웃 편집기에서 사용자 정의 글꼴을 볼 수 없습니다. 이것이 내가 isInEditMode()수표를 넣은 이유 입니다. 그러나 앱을 실행하면 사용자 지정 글꼴이 매력처럼 작동합니다.

도움이 되었기를 바랍니다.


나는 이것을 시도하지 않았지만 TextView클래스 를 확장하여 사용자 지정 컨트롤을 만들었습니다 . 을 설정 typeface그 안에 우리가 평소 & 그것은 나를 위해 일한으로 레이아웃에 사용자 지정 컨트롤을 사용 ... 그것은 간단이었다하지만, 그 위의 하나 ...
마헨드라 리야

1
나는 당신이 말한대로 정확히했습니다. 유일한 차이점은 XML을 통해이 작업을 수행하는 방법을 묻기 때문에이 구성 요소를 재사용 가능하게 만들었다는 것입니다. 실제로 XML을 통해이 작업을 수행하는 방법이 있으며 이것이 수행하는 방법입니다. :)
leocadiotine

통합하기 매우 쉬운 코드. 그것은 나를 위해 작동합니다. 감사.
Durai

1
이것은 받아 들여진 대답이어야합니다. 잘 작성되었습니다. 감사!
Reaz Murshed

1
@DominikSuszczewicz! 답변을 업데이트 할 수 있도록 코드를 공유해 주시겠습니까?
leocadiotine

15

roboto 서체가있는 TextView의 예 :

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

}

사용 예 :

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

리소스 : Roboto 및 Noto 글꼴


그러나 자바 클래스에서 글꼴의 ID를 수정하지 않고이 솔루션을 사용하는 방법이 있습니까? enum attrs에서 이러한 최종 필드를 읽을 수 있습니다. private final static int ROBOTO_THIN = 0; 개인 최종 정적 int ROBOTO_THIN_ITALIC = 1; 개인 최종 정적 int ROBOTO_LIGHT = 2; ...
Arthur Melo

3

너무 늦었지만 다른 사람
이 typeFace라는 속성을 가진 CustomTextView를 만들었고 캐싱하지 않고 서체 로딩으로 메모리 누수 문제를 처리 하는 데 도움이됩니다.

첫 번째 Fonts클래스는 한 번만 자산에서 글꼴을로드합니다.

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

그런 다음 attrs.xml에 사용자 정의 속성을 추가해야합니다.

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

    </declare-styleable>

그런 다음 맞춤 클래스

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

마지막으로 텍스트보기를 추가합니다.

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

setTypeFace 메소드를 사용하여 글꼴을 progrmatically 변경할 수 있습니다.
또한이보기에서 둘 이상을 사용하려면 사용자 정의 네임 스페이스를 상위 레이아웃으로 이동할 수 있습니다.

해피 코딩 :)


간단한 정답입니다.
eyadMhanna

2

onCreate ()에서 호출되고 가장 바깥쪽에있는 ViewGroup을 전달하는 아래 메서드는 동적으로 생성 된 텍스트 (예 : 동적 목록, 경고 등)를 제외한 모든 작업에서 작동합니다. 가장 바깥쪽에있는 ViewGroup을 가져 오는 쉬운 방법은 뷰 중 하나에서 getRootView를 사용하는 것입니다.

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

    }

}

이것은 동적 콘텐츠에서도 작동합니다. 생성 한 직후에 생성 한 내용을 전달하여 호출해야합니다 (하지만 테스트하지는 않았습니다).

메모리를 절약하기 위해 여기 에서처럼 루프가 실행될 때마다 새 글꼴을 만드는 대신 서체를 정적 변수로 만들고 싶을 것입니다.


이 솔루션을 권장하지 않습니다. 적용하려는 각 요소에 대해 동일한 글꼴의 새 인스턴스를 생성하기 때문입니다. 이로 인해 메모리 문제가 발생할 수 있습니다.
flawyte 2014

그것은 마지막에 내 노트에서 다룹니다.
Chris

2

보다 일반적인 프로그래밍 솔루션을 찾고 있다면 전체보기 (활동 UI)의 서체를 설정하는 데 사용할 수있는 정적 클래스를 만들었습니다. Mono (C #)로 작업하고 있지만 Java를 사용하여 쉽게 구현할 수 있습니다.

이 클래스에 사용자 정의하려는 레이아웃 또는 특정보기를 전달할 수 있습니다. 매우 효율적이기를 원한다면 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");
            }
        }

    }

활동에서 Typeface 개체를 만들어야합니다. 내 Resources / Assets / 디렉터리에있는 .ttf 파일을 사용하여 OnCreate ()에 내 파일을 만듭니다. 파일이 속성에서 Android 자산으로 표시되어 있는지 확인하십시오.

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

안타깝게도 Android는 전체 앱의 글꼴을 변경하기 위해 찾고있는 빠르고 쉽고 깔끔한 방법을 제공하지 않습니다. 하지만 최근에 저는이 문제를 조사하고 코딩없이 글꼴을 변경할 수있는 몇 가지 도구를 만들었습니다 (xml, 스타일 및 텍스트 모양을 통해 모든 작업을 수행 할 수 있음). 여기에있는 다른 답변에서 볼 수있는 것과 유사한 솔루션을 기반으로하지만 훨씬 더 많은 유연성을 허용합니다. 이 블로그 에서 모든 내용을 읽을 수 있으며 여기 에서 github 프로젝트를 볼 수 있습니다. .

다음은 이러한 도구를 적용하는 방법의 예입니다. 모든 글꼴 파일을 assets/fonts/. 그런 다음 해당 글꼴을 xml 파일 (예 :)에 선언 res/xml/fonts.xml하고이 파일을 앱의 초기에로드합니다 TypefaceManager.initialize(this, R.xml.fonts);(예 : 애플리케이션 클래스의 onCreate에서). xml 파일은 다음과 같습니다.

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

이제 com.innovattic.font.FontTextViewxml 레이아웃에서 사용자 정의 UI 요소를 사용하여 스타일 또는 xml (위에서 언급 한 도구를 사용하는 경우)에서 이러한 글꼴을 사용할 수 있습니다 . 아래에서 편집하는 것만으로 전체 앱의 모든 텍스트에 글꼴을 적용하는 방법을 볼 수 있습니다 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>

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

Android 매니페스트에 테마를 적용하는 것을 잊지 마십시오.


2

훌륭한 솔루션에 메모를 추가하고 싶습니다. leocadiotine . 완벽하지만이 Custom TextView를 여러 번 사용하면 textview가 생성 될 때마다 자산에 액세스해야하므로 애플리케이션 속도가 느려집니다. 나는 다음과 같은 것을 사용하는 것이 좋습니다.View Holder pattern에서Adapters .

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

이러한 방식으로 애플리케이션은 자산 당 한 번만 자산에 액세스하고 추가 요구를 위해 메모리에 보관합니다.


0

전체 앱이 변경되는지는 모르겠지만 이렇게하면 변경할 수없는 일부 구성 요소를 변경할 수있었습니다.

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, 로케일에 따라 사용자 지정 글꼴을 설정하고 싶습니다. 예를 들어 영어 로케일을 사용할 때마다 Arial TTF를 설정하고 한국어 로케일을 사용할 때 고딕 TTF를 설정하고 싶습니다
Dwivedi Ji

0

이 링크, 링크에서 단계별 정보를 찾았습니다. https://github.com/jaydipumaretiya/CustomTypeface/

안드로이드에서 서체를 올바르게 사용하는 방법은 여러 가지가 있습니다. 서체 파일을 메인 아래에있는 assets 폴더에 직접 넣어야하며 런타임에 사용할 수 있습니다.

다른 가장 간단한 방법은 기본 라이브러리를 사용하여 xml 파일에 서체를 설정하는 것입니다. 이 사용자 지정 서체 라이브러리를 사용하여 서체를 TextView, EditText, Button, CheckBox, RadioButton 및 AutoCompleteTextView 및 Android의 기타 wedget으로 설정하는 것을 선호합니다.


github 링크가 작동하지 않습니다.
Thomas

0

Android 8.0 (API 레벨 26)에는 새로운 기능인 XML의 글꼴이 도입되었습니다. fontfamily 파일을 생성하고 styles.xml에서 설정할 수 있습니다.

글꼴을 리소스로 추가하려면 Android 스튜디오에서 다음 단계를 수행하세요.

1. res 폴더를 마우스 오른쪽 버튼으로 클릭하고 새로 만들기> Android 리소스 디렉터리로 이동합니다. 새 리소스 디렉터리 창이 나타납니다.

2. 리소스 유형 목록에서 글꼴을 선택한 다음 확인을 클릭합니다. 참고 : 리소스 디렉터리의 이름은 글꼴이어야합니다.

3. font 폴더에 글꼴 파일을 추가합니다.

글꼴 패밀리를 만들려면 다음 단계를 수행하십시오.

1. 글꼴 폴더를 마우스 오른쪽 버튼으로 클릭하고 새로 만들기> 글꼴 리소스 파일로 이동합니다. 새 리소스 파일 창이 나타납니다.

2. 파일 이름을 입력 한 다음 확인을 클릭합니다. 새 글꼴 리소스 XML이 편집기에서 열립니다.

3. 요소에 각 글꼴 파일, 스타일 및 가중치 속성을 포함합니다. 다음 XML은 글꼴 리소스 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>

스타일에 글꼴 추가

styles.xml을 열고 fontFamily 속성을 액세스하려는 글꼴 파일로 설정하십시오.

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

출처 : XML 글꼴

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.