アプリケーション全体にカスタムフォントを設定することは可能ですか?


270

アプリケーション全体で特定のフォントを使用する必要があります。同じための.ttfファイルがあります。アプリケーションの起動時にこれをデフォルトのフォントとして設定して、アプリケーションの他の場所で使用することはできますか?設定した場合、レイアウトXMLでどのように使用しますか?


アンドロイドスタジオ3.0で簡単にカスタムフォントを設定することができます。developer.android.com/guide/topics/ui/look-and-feel/...
MHSFisher

@MHSFisher Fonts in XMLはAndroid 8.0(APIレベル26)の機能です
Emi Raz

1
@EmiRazは、ドキュメントdeveloper.android.com/guide/topics/ui/look-and-feel/…を読んでください。この機能は、サポートライブラリ26が、API 16からの支援で追加
MHSFisher

回答:


449

はい、反射があります。これは機能します(この回答に基づく):

(注:カスタムフォントのサポートが不足しているため、これは回避策です。この状況を変更したい場合は、スターを付けてAndroidの問題をここで投票してください)。注:その問題について「私も」というコメントを残さないでください。それを開始した人は全員、メールを受け取ります。だから「星」だけにしてください。

import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Typeface;

public final class FontsOverride {

    public static void setDefaultFont(Context context,
            String staticTypefaceFieldName, String fontAssetName) {
        final Typeface regular = Typeface.createFromAsset(context.getAssets(),
                fontAssetName);
        replaceFont(staticTypefaceFieldName, regular);
    }

    protected static void replaceFont(String staticTypefaceFieldName,
            final Typeface newTypeface) {
        try {
            final Field staticField = Typeface.class
                    .getDeclaredField(staticTypefaceFieldName);
            staticField.setAccessible(true);
            staticField.set(null, newTypeface);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

次に、たとえばアプリケーションクラスで、いくつかのデフォルトフォントをオーバーロードする必要があります。

public final class Application extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();
        FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
        FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
        FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
        FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
    }
}

または、同じフォントファイルを使用している場合は、これを改善して一度だけロードすることができます。

ただし、私は1つをオーバーライドする傾向があります。たとえば"MONOSPACE"、フォントの書体をアプリケーション全体に強制するスタイルを設定します。

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

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <item name="android:typeface">monospace</item>
    </style>
</resources>

API 21 Android 5.0

コメントでレポートが機能しない、およびテーマと互換性がないように思われるという報告を調査しましたandroid:Theme.Material.Light

そのテーマが重要でない場合は、古いテーマを使用してください。例:

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
    <item name="android:typeface">monospace</item>
</style>

11
モノスペースの太字または斜体をどのように上書きしますか?
Christopher Rivera 14年

2
@ChristopherRivera "DEFAULT_BOLD"プライベートフィールドもあります。private static Typeface[] sDefaults;リフレクションとsDefaults[Typeface.ITALIC]yourTypefaceへの設定により、これにアクセスできます。これを
ウェストン2014年

5
@weston気にしないで。私はそれを達成しました。私の理解に誤りがありました。あなたは素晴らしい仕事をしました。一つだけ教えてもらえますか?DEFAULT Typefaceで機能しないのはなぜですか?私はあなたの提案としてTypefaceをMONOSPACEに変更してから、logincを適用しました。しかし、DEFAULTで働いていません
Jay Pandya 2014年

2
ネイティブの書体をエラーにすることはできません。フォントパスを追加することで修正。"FontsOverride.setDefaultFont(this、" DEFAULT "、" fonts / MyFontAsset.ttf ");"
Sai

3
TextViewカスタムフォントを使用したり、このようなリフレクションベースのソリューションを使用したりするために、どこでもデフォルトを交換しなければならないのは本当に面倒です。Androidで使用できるフォントの制限セットと組み合わせると、見栄えの良いアプリの開発は大変な労力になります。Androidの課題追跡に機能リクエストを追加しました。この機能をご覧になりたい場合は、code.google.com
Sam

64

Androidにはカスタムフォント用の素晴らしいライブラリがあります:書道

使い方のサンプルはこちらです。

Gradleでは、次の行をアプリのbuild.gradleファイルに追加する必要があります。

dependencies {
    compile 'uk.co.chrisjenx:calligraphy:2.2.0'
}

次に、Applicationこのコードを拡張して記述するクラスを作成します。

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                        .setDefaultFontPath("your font path")
                        .setFontAttrId(R.attr.fontPath)
                        .build()
        );
    }
} 

アクティビティクラスでは、このメソッドをonCreateの前に配置します。

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}

そして最後にマニフェストファイルは次のようになります。

<application
   .
   .
   .
   android:name=".App">

アクティビティ全体がフォントに変更されます!シンプルできれいです!


1
これは完璧なソリューションです。
nizam.sp 2016

1
確かに、その非常に完璧なソリューションです。このようにして、メニュー項目、ラジオボタン、またはチェックボックスのフォントを更新するために別のクラスを記述する必要はありません。すべてに適用されます!! ありがとう:)
Manisha

2
間違いなく完璧な解決策ではありません:太字/斜体/太字斜体のスタイルは上書きされます。現在、これらのファミリーを設定する簡単な方法はありません。
0101100101 2016年

2
その場合、太字から標準に切り替えるにはどうすればよいですか?
GMX 2017年

2
太字、斜体、または下線の機能を使用するため<b></b>に、私はを使用<u></u><i></i>ましたが、strings.xmlファイル内ではこれまでのところ機能します。
jlively

47

これはアプリケーション全体では機能しませんが、アクティビティで機能し、他のアクティビティで再利用できます。@ FR073Nのおかげで、他のビューをサポートするようにコードを更新しました。これらのクラスはすべて拡張されているためButtons、問題なく動作するはずなのでRadioGroups、、、などの問題についてはわかりませんTextView。リフレクションを使用するためのブール条件を追加しました。これは非常にハックに見え、特にパフォーマンスが低下する可能性があるためです。

注:指摘したように、これは動的コンテンツでは機能しません!そのため、このメソッドを、たとえばonCreateViewor getViewメソッドで呼び出すことは可能ですが、追加の作業が必要です。

/**
 * Recursively sets a {@link Typeface} to all
 * {@link TextView}s in a {@link ViewGroup}.
 */
public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
{
    if (mContainer == null || mFont == null) return;

    final int mCount = mContainer.getChildCount();

    // Loop through all of the children.
    for (int i = 0; i < mCount; ++i)
    {
        final View mChild = mContainer.getChildAt(i);
        if (mChild instanceof TextView)
        {
            // Set the font if it is a TextView.
            ((TextView) mChild).setTypeface(mFont);
        }
        else if (mChild instanceof ViewGroup)
        {
            // Recursively attempt another ViewGroup.
            setAppFont((ViewGroup) mChild, mFont);
        }
        else if (reflect)
        {
            try {
                Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
                mSetTypeface.invoke(mChild, mFont); 
            } catch (Exception e) { /* Do something... */ }
        }
    }
}

それを使用するには、次のようにします。

final Typeface mFont = Typeface.createFromAsset(getAssets(),
"fonts/MyFont.ttf"); 
final ViewGroup mContainer = (ViewGroup) findViewById(
android.R.id.content).getRootView();
HomeActivity.setAppFont(mContainer, mFont);

お役に立てば幸いです。


4
最善の方法は、textviewをオーバーライドすることだと思います。多数のビューを持つアプリケーションがある場合、このメソッドは多少冗長になる可能性があります。
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

1
それは可能です...しかし、Androidの仕様によると、4レベルより深いレイアウトと100ビュー幅のレイアウトは避けたいです(それでもかなりです)。再帰はパフォーマンスの点で悪い場合がありますが、レイアウトが20レベルであったとしても、それほど重要ではありません。
トム

私はそれがパフォーマンスに顕著な影響を与えないことに同意します、そして私はあなたの答えが間違っているとは言いません。必要がない場合は、レイアウト内のすべてのビューを循環するのは好きではありません。また、TextViewを拡張することで、外観を別の方法で変更したい場合は、コードを1箇所変更するだけで済みます。
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 2012

1
上記のコードを追加したいのは、TextViewsをカバーするだけですが、ListViews、Alerts、Toasts、Map Markersなどは引き続きシステムフォントを使用します。
csch 2013年

2
みんなこの関数は3つのパラメーターを受け取り、再帰的に呼び出すと2つのパラメーターが渡されます??? どちらが正しいですか?リフレクトとは何ですか?
MBH

34

要約すれば:

オプション#1: リフレクションを使用してフォントを適用する(westonRoger Huangの回答を組み合わせたもの):

import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Typeface;

public final class FontsOverride { 

    public static void setDefaultFont(Context context,
            String staticTypefaceFieldName, String fontAssetName) {
        final Typeface regular = Typeface.createFromAsset(context.getAssets(),
                fontAssetName);
        replaceFont(staticTypefaceFieldName, regular);
    } 

    protected static void replaceFont(String staticTypefaceFieldName,final Typeface newTypeface) {
        if (isVersionGreaterOrEqualToLollipop()) {
            Map<String, Typeface> newMap = new HashMap<String, Typeface>();
            newMap.put("sans-serif", newTypeface);
            try {
                final Field staticField = Typeface.class.getDeclaredField("sSystemFontMap");
                staticField.setAccessible(true);
                staticField.set(null, newMap);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            try {
                final Field staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName);
                staticField.setAccessible(true);
                staticField.set(null, newTypeface);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } 
        }
    }

} 

Applicationクラスでの使用:

public final class Application extends android.app.Application {
    @Override 
    public void onCreate() { 
        super.onCreate(); 
        FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
        FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
        FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
        FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
    } 
} 

そのフォントタイプフェイスアプリケーションを強制的に広くするスタイルを設定します(lovefishに基づく))。

プレロリポップ:

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="android:typeface">monospace</item>
   </style>
</resources>

ロリポップ(API 21):

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="android:textAppearance">@style/CustomTextAppearance</item>
   </style>

   <style name="CustomTextAppearance">
       <item name="android:typeface">monospace</item>
   </style>
</resources>

オプション2: フォントをカスタマイズする必要があるすべてのビューをサブクラス化します。ListView、EditTextView、Buttonなど(Palaniの答え):

public class CustomFontView extends TextView {

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

public CustomFontView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(); 
} 

public CustomFontView(Context context) {
    super(context);
    init(); 
} 

private void init() { 
    if (!isInEditMode()) {
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
        setTypeface(tf);
    } 
} 

オプション3: 現在の画面のビュー階層を移動するビュークローラーを実装します。

バリエーション#1(トムの答え):

public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
{ 
    if (mContainer == null || mFont == null) return;

    final int mCount = mContainer.getChildCount();

    // Loop through all of the children. 
    for (int i = 0; i < mCount; ++i)
    { 
        final View mChild = mContainer.getChildAt(i);
        if (mChild instanceof TextView)
        { 
            // Set the font if it is a TextView. 
            ((TextView) mChild).setTypeface(mFont);
        } 
        else if (mChild instanceof ViewGroup)
        { 
            // Recursively attempt another ViewGroup. 
            setAppFont((ViewGroup) mChild, mFont);
        } 
        else if (reflect)
        { 
            try { 
                Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
                mSetTypeface.invoke(mChild, mFont); 
            } catch (Exception e) { /* Do something... */ }
        } 
    } 
} 

使用法 :

final ViewGroup mContainer = (ViewGroup) findViewById(
android.R.id.content).getRootView();
HomeActivity.setAppFont(mContainer, Typeface.createFromAsset(getAssets(),
"fonts/MyFont.ttf"));

バリエーション#2:https : //coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere

オプション#4:Calligraphy と呼ばれるサードパーティのLibを使用します。

個人的に、私はOption#4をお勧めします。


ではオプション#1、あなたは何を意味するん"sans-serif"newMap.put(、とmonospacestyles?!という名前のカスタムフォントを使用したいbarana.ttf
Dr.jacky 2018

オプション1では、最初のコードスニペットはAPIレベル22、Android 5.1.1では機能しません。しかし、他のコードセクションはそうです。もし条件がそうなら正確なはずですか?
user1510006

28

API 21 Android 5.0に対するwestonの回答を改善したいと思います。

原因

API 21では、ほとんどのテキストスタイルに次のようなfontFamily設定が含まれています。

<style name="TextAppearance.Material">
     <item name="fontFamily">@string/font_family_body_1_material</item>
</style>

デフォルトのRoboto Regularフォントが適用されます。

<string name="font_family_body_1_material">sans-serif</string>

android:fontFamilyはandroid:typeface属性よりも優先度が高いため、元の回答ではモノスペースフォントを適用できません(参照)。内部にはandroid:fontFamily設定がないため、Theme.Holo。*の使用は有効な回避策です。

解決

Android 5.0では、システムの書体を静的変数Typeface.sSystemFontMap(reference)に入れているため、同じリフレクションテクニックを使用して置き換えることができます。

protected static void replaceFont(String staticTypefaceFieldName,
        final Typeface newTypeface) {
    if (isVersionGreaterOrEqualToLollipop()) {
        Map<String, Typeface> newMap = new HashMap<String, Typeface>();
        newMap.put("sans-serif", newTypeface);
        try {
            final Field staticField = Typeface.class
                    .getDeclaredField("sSystemFontMap");
            staticField.setAccessible(true);
            staticField.set(null, newMap);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    } else {
        try {
            final Field staticField = Typeface.class
                    .getDeclaredField(staticTypefaceFieldName);
            staticField.setAccessible(true);
            staticField.set(null, newTypeface);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

4
L.の良い回避策ですが、なぜこれが私ButtonのsとTool Barのタイトルで機能しないように見えるのでしょうか。MainApplicationのデフォルトフォントを次のようにオーバーライドしていますFontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");。私はNexus 5、v5.1.1を使用しています
kip2

3
こんにちは、ありがとうございます。これは非常に役に立ちました。1つだけ、Android 6(API 22)では機能しません。次に、コードを次のように変更する必要がありますBuild.VERSION.SDK_INT == 21API 21
。-

それでも、Nexus 9でこの方法を使用してカスタムフォントを設定することはできません
Rahul Upadhyay

2
5.1+で動作しない問題がある人。values-v21スタイルの書体をオーバーライドしないでください。
ムハンマドババール2016

@MuhammadBabarありがとうございました。解決策が私の一日となりました
M.Yogeshwaran

15

その非常に単純な... 1. urカスタムフォントをダウンロードしてアセットに配置します。次に、テキストビュー用に1つの個別のクラスを次のように記述します。ここではfuturaフォントを使用しました

public class CusFntTextView extends TextView {

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

public CusFntTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public CusFntTextView(Context context) {
    super(context);
    init();
}

private void init() {
    if (!isInEditMode()) {
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
        setTypeface(tf);
    }
}

}

そして、xmlで次のようにします:

 <com.packagename.CusFntTextView
        android:id="@+id/tvtitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"         
        android:text="Hi Android"           
        android:textAppearance="?android:attr/textAppearanceLarge"
      />

はい、それは機能します:)しかし、他の残りのビュー/ウィジェットに同じフォントを適用したい場合はどうなりますか?他のすべてのビュー(ダイアログ、トースト、アクションバーを含む)にも個別のクラスを記述する必要がありますか?
Narendra Singh

はい、このソリューションでは、ビューごとに個別のクラスを作成する必要があります。
Saad Bilal

9

また、TextViewやその他のコントロールを拡張することをお勧めしますが、構造体にフォントを設定することを検討する方が良いでしょう。

public FontTextView(Context context) {
    super(context);
    init();
}

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

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

protected void init() {
    setTypeface(Typeface.createFromAsset(getContext().getAssets(), AppConst.FONT));
}

2
4.0より前のプラットフォームでこれを行う場合は注意してください。これは、Androidのバグが原因で多くのリソースをリークします。code.google.com
Ryan M

どうすればデフォルトに戻すことができますか。私は次のようなことをしています:if(configShared.getString( "storeId"、AppCredentials.DEFAULT_STORE_ID).equals( "2")){final Field staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName); staticField.setAccessible(true); staticField.set(null、newTypeface); } else {final Field staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName); staticField.setAccessible(true); staticField.set(null、null); }
キラー

8

テーマ「Theme.AppCompat」を使用して、API 21 Androidのロリポップ以上のwestonRoger Huangの回答を改善したいと思います。

Android 4.4未満

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="android:typeface">monospace</item>
   </style>
</resources>

(等しい)API 5.0以上

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="android:textAppearance">@style/CustomTextAppearance</item>
   </style>

   <style name="CustomTextAppearance">
       <item name="android:typeface">monospace</item>
   </style>
</resources>

そして、FontsOverride utilファイルはwestonの回答と同じです。私はこれらの電話でテストしました:

Nexus 5(android 5.1プライマリAndroidシステム)

ZTE V5(android 5.1 CM12.1)

XIAOMIノート(android 4.4 MIUI6)

HUAWEI C8850(android 2.3.5 UNKNOWN)


8

素晴らしいソリューションはここにあります:https : //coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere

BaseActivityからアクティビティを拡張し、それらのメソッドを記述するだけです。また、https//stackoverflow.com/a/16902532/2914140で説明されているように、フォントをより適切にキャッシュする必要があります


いくつかの調査の後、Samsung Galaxy Tab A(Android 5.0)で動作するコードを書きました。westonとRoger Huangのコードとhttps://stackoverflow.com/a/33236102/2914140を使用しました。また、動作しないLenovo TAB 2 A10-70Lでもテストされています。違いを見るために、ここに「Comic Sans」というフォントを挿入しました。

import android.content.Context;
import android.graphics.Typeface;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class FontsOverride {
    private static final int BOLD = 1;
    private static final int BOLD_ITALIC = 2;
    private static final int ITALIC = 3;
    private static final int LIGHT = 4;
    private static final int CONDENSED = 5;
    private static final int THIN = 6;
    private static final int MEDIUM = 7;
    private static final int REGULAR = 8;

    private Context context;

    public FontsOverride(Context context) {
        this.context = context;
    }

    public void loadFonts() {
        Map<String, Typeface> fontsMap = new HashMap<>();
        fontsMap.put("sans-serif", getTypeface("comic.ttf", REGULAR));
        fontsMap.put("sans-serif-bold", getTypeface("comic.ttf", BOLD));
        fontsMap.put("sans-serif-italic", getTypeface("comic.ttf", ITALIC));
        fontsMap.put("sans-serif-light", getTypeface("comic.ttf", LIGHT));
        fontsMap.put("sans-serif-condensed", getTypeface("comic.ttf", CONDENSED));
        fontsMap.put("sans-serif-thin", getTypeface("comic.ttf", THIN));
        fontsMap.put("sans-serif-medium", getTypeface("comic.ttf", MEDIUM));
        overrideFonts(fontsMap);
    }

    private void overrideFonts(Map<String, Typeface> typefaces) {
        if (Build.VERSION.SDK_INT == 21) {
            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", "Cannot set custom fonts");
            }
        } else {
            try {
                for (Map.Entry<String, Typeface> entry : typefaces.entrySet()) {
                    final Field staticField = Typeface.class.getDeclaredField(entry.getKey());
                    staticField.setAccessible(true);
                    staticField.set(null, entry.getValue());
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    private Typeface getTypeface(String fontFileName, int fontType) {
        final Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/" + fontFileName);
        return Typeface.create(tf, fontType);
    }
}

アプリケーション全体でコードを実行するには、Applicationのようなクラスに次のように記述する必要があります。

    new FontsOverride(this).loadFonts();

「assets」内に「fonts」フォルダを作成し、そこに必要なフォントを配置します。簡単な指示はここにあります:https : //stackoverflow.com/a/31697103/2914140

Lenovoデバイスも、書体の値を誤って取得します。ほとんどの場合、それはTypeface.NORMALを返し、時にはnullを返します。TextViewが太字の場合でも(xmlファイルレイアウト)。ここを参照してください:TextView isBoldは常にNORMALを返します。このようにして、画面上のテキストは常に太字や斜体ではなく通常のフォントになります。だからプロデューサーのバグだと思う。


私はアンドロイドのソースコードを勉強しました、あなたの答えは最高です。それは、薄い、中型、軽いまたは他のものを置き換えることができます。どうもありがとうございます!
Mohammad Omidvar 2017

6

Xamarin.Androidでの作業:

クラス:

public class FontsOverride
{
    public static void SetDefaultFont(Context context, string staticTypefaceFieldName, string fontAssetName)
    {
        Typeface regular = Typeface.CreateFromAsset(context.Assets, fontAssetName);
        ReplaceFont(staticTypefaceFieldName, regular);
    }

    protected static void ReplaceFont(string staticTypefaceFieldName, Typeface newTypeface)
    {
        try
        {
            Field staticField = ((Java.Lang.Object)(newTypeface)).Class.GetDeclaredField(staticTypefaceFieldName);
            staticField.Accessible = true;
            staticField.Set(null, newTypeface);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

アプリケーションの実装:

namespace SomeAndroidApplication
{
    [Application]
    public class App : Application
    {
        public App()
        {

        }

        public App(IntPtr handle, JniHandleOwnership transfer)
            : base(handle, transfer)
        {

        }

        public override void OnCreate()
        {
            base.OnCreate();

            FontsOverride.SetDefaultFont(this, "MONOSPACE", "fonts/Roboto-Light.ttf");
        }
    }
}

スタイル:

<style name="Theme.Storehouse" parent="Theme.Sherlock">
    <item name="android:typeface">monospace</item>
</style>

6

Android O以降、これはXMLから直接定義できるようになり、私のバグはクローズされました!

詳細はこちら

TL; DR:

まず、プロジェクトにフォントを追加する必要があります

次に、次のようにフォントファミリーを追加します。

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

最後に、フォントをレイアウトまたはスタイルで使用できます。

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

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

楽しい!


ありがとう。フォントフォルダーを追加するには、Android Studio 2.4を使用する必要があります。
フォトンポイント

実際にそれを自分のスタイルに適用するだけで、アプリケーションを通じて適用されます。ただし、一部(プログラムで追加されたコントロールは、Javaコードを介して適用する必要があります)
SolidSnake 2017

4

すべてのレイアウトのカスタムフォントを1つずつ設定できます。ルートのViewを渡すことにより、すべてのレイアウトから関数を1回呼び出すだけです。最初に、このようなフォントオブジェクトにアクセスするためのシングルトンアプローチを作成します。

 public class Font {
    private static Font font;
    public Typeface ROBO_LIGHT;

    private Font() {

    }

    public static Font getInstance(Context context) {
        if (font == null) {
            font = new Font();
            font.init(context);
        }
        return font;

    }

    public void init(Context context) {

        ROBO_LIGHT = Typeface.createFromAsset(context.getAssets(),
                "Roboto-Light.ttf");
    }

}

上記のクラスでさまざまなフォントを定義できます。次に、フォントを適用するフォントヘルパークラスを定義します。

   public class FontHelper {

    private static Font font;

    public static void applyFont(View parentView, Context context) {

        font = Font.getInstance(context);

        apply((ViewGroup)parentView);

    }

    private static void apply(ViewGroup parentView) {
        for (int i = 0; i < parentView.getChildCount(); i++) {

            View view = parentView.getChildAt(i);

//You can add any view element here on which you want to apply font 

            if (view instanceof EditText) {

                ((EditText) view).setTypeface(font.ROBO_LIGHT);

            }
            if (view instanceof TextView) {

                ((TextView) view).setTypeface(font.ROBO_LIGHT);

            }

            else if (view instanceof ViewGroup
                    && ((ViewGroup) view).getChildCount() > 0) {
                apply((ViewGroup) view);
            }

        }

    }

}

上記のコードでは、textViewとEditTextのみにフォントを適用していますが、他のビュー要素にも同様にフォントを適用できます。ルートビューグループのIDを上記のフォント適用メソッドに渡すだけです。例えばあなたのレイアウトは:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/mainParent"
    tools:context="${relativePackage}.${activityClass}" >

    <RelativeLayout
        android:id="@+id/mainContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/homeFooter"
        android:layout_below="@+id/edit" >

        <ImageView
            android:id="@+id/PreviewImg"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/abc_list_longpressed_holo"
            android:visibility="gone" />

        <RelativeLayout
            android:id="@+id/visibilityLayer"
            android:layout_width="match_parent"
            android:layout_height="fill_parent" >

            <ImageView
                android:id="@+id/UseCamera"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:src="@drawable/camera" />

            <TextView
                android:id="@+id/tvOR"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/UseCamera"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="20dp"
                android:text="OR"
                android:textSize="30dp" />

            <TextView
                android:id="@+id/tvAND"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="20dp"
                android:text="OR"
                android:textSize="30dp" />

</RelativeLayout>

上記のレイアウトでは、ルートの親IDは「Main Parent」になり、フォントを適用できるようになりました

public class MainActivity extends BaseFragmentActivity {

    private EditText etName;
    private EditText etPassword;
    private TextView tvTitle;
    public static boolean isHome = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       Font font=Font.getInstance(getApplicationContext());
        FontHelper.applyFont(findViewById(R.id.mainParent),          getApplicationContext());
   }    
}

乾杯:)


いいですね。同じフォントを再作成する必要はなく、すべてのフィールドで1つのフォントしか使用しません。:)
Arfan Mirza

3

TextViewを拡張し、XMLレイアウト内またはTextViewが必要な場所では常にカスタムTextViewを使用することをお勧めします。カスタムTextViewで、オーバーライドsetTypeface

@Override
public void setTypeface(Typeface tf, int style) {
    //to handle bold, you could also handle italic or other styles here as well
    if (style == 1){
        tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans700.otf");
    }else{
        tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans500.otf");
    }
    super.setTypeface(tf, 0);
}

2

トムのソリューションはうまく機能しますが、TextViewとEditTextでのみ機能します。

ほとんどのビュー(RadioGroup、TextView、Checkbox ...)をカバーしたい場合は、それを行うメソッドを作成しました。

protected void changeChildrenFont(ViewGroup v, Typeface font){
    for(int i = 0; i < v.getChildCount(); i++){

        // For the ViewGroup, we'll have to use recursivity
        if(v.getChildAt(i) instanceof ViewGroup){
            changeChildrenFont((ViewGroup) v.getChildAt(i), font);
        }
        else{
            try {
                Object[] nullArgs = null;
                //Test wether setTypeface and getTypeface methods exists
                Method methodTypeFace = v.getChildAt(i).getClass().getMethod("setTypeface", new Class[] {Typeface.class, Integer.TYPE});
                //With getTypefaca we'll get back the style (Bold, Italic...) set in XML
                Method methodGetTypeFace = v.getChildAt(i).getClass().getMethod("getTypeface", new Class[] {});
                Typeface typeFace = ((Typeface)methodGetTypeFace.invoke(v.getChildAt(i), nullArgs));
                //Invoke the method and apply the new font with the defined style to the view if the method exists (textview,...)
                methodTypeFace.invoke(v.getChildAt(i), new Object[] {font, typeFace == null ? 0 : typeFace.getStyle()});
            }
            //Will catch the view with no such methods (listview...)
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

このメソッドは、XMLで設定されたビューのスタイル(太字、斜体...)を取得し、存在する場合は適用します。

ListViewの場合は、常にアダプターを作成し、getView内にフォントを設定します。


2

現在のビュー階層のビューにタイプフェイスを割り当てるクラスを作成し、現在のタイプフェイスプロパティに基づいています(太字、通常、必要に応じて他のスタイルを追加できます)。

public final class TypefaceAssigner {

public final Typeface DEFAULT;
public final Typeface DEFAULT_BOLD;

@Inject
public TypefaceAssigner(AssetManager assetManager) {
    DEFAULT = Typeface.createFromAsset(assetManager, "TradeGothicLTCom.ttf");
    DEFAULT_BOLD = Typeface.createFromAsset(assetManager, "TradeGothicLTCom-Bd2.ttf");
}

public void assignTypeface(View v) {
    if (v instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) v).getChildCount(); i++) {
            View view = ((ViewGroup) v).getChildAt(i);
            if (view instanceof ViewGroup) {
                setTypeface(view);
            } else {
                setTypeface(view);
            }
        }
    } else {
        setTypeface(v);
    }
}

private void setTypeface(View view) {
    if (view instanceof TextView) {
        TextView textView = (TextView) view;
        Typeface typeface = textView.getTypeface();
        if (typeface != null && typeface.isBold()) {
            textView.setTypeface(DEFAULT_BOLD);
        } else {
            textView.setTypeface(DEFAULT);
        }
    }
}
}

onViewCreatedまたはonCreateViewのすべてのフラグメント、onCreateのすべてのアクティビティ、およびgetViewまたはnewViewのすべてのビューアダプターで、次のように呼び出します。

typefaceAssigner.assignTypeface(view);

2

build.gradle 3.0.0以降のAPI 26では、resにフォントディレクトリを作成し、この行をスタイルで使用できます

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

build.gradleを変更するには、build.gradle依存関係でこれを使用します

classpath 'com.android.tools.build:gradle:3.0.0'

そして、フォントをプロジェクトに挿入する方法は?
azerafati 2018年

@azerafatiフォントをres / fontにコピー
Mohammad Hosein Heidari

ええ、tanx。もうわかった。しかし、それitemだけではアプリ全体のフォントは設定されません。どんな手掛かり?
azerafati

1

最後に、Googleはこの問題の深刻さ(カスタムフォントをUIコンポーネントに適用すること)を認識し、そのためのクリーンなソリューションを考案しました。

まず、ライブラリ26+をサポートするように更新する必要があります(gradle {4.0 +}、android studioも更新する必要がある場合があります)。次に、fontという新しいリソースフォルダーを作成できます。このフォルダに、フォントリソース(.tff、...)を置くことができます。次に、デフォルトのアプリをオーバーライドして、カスタムフォントを強制する必要があります:)

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:fontFamily">@font/my_custom_font</item>
</style>

注:16より古いAPIのデバイスをサポートする場合は、androidではなくapp名前空間を使用する必要があります!


0

また、API 21 Android 5.0に対するwestonの回答を改善したいと思います。

デフォルトのフォントを使用すると、Samsung s5でも同じ問題が発生しました。(他のフォントではうまく機能しています)

TextviewまたはButtonごとに、XMLファイルで書体(「sans」など)を設定することで、それを機能させることができました

<TextView
android:layout_width="match_parent"
android:layout_height="39dp"
android:textColor="@color/abs__background_holo_light"
android:textSize="12sp"
android:gravity="bottom|center"
android:typeface="sans" />

MyApplicationクラス:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
    TypefaceUtil.overrideFont(getApplicationContext(), "SANS_SERIF",
    "fonts/my_font.ttf");
    }
}

それが役に立てば幸い。



0

書道はかなりうまく機能しますが、フォントファミリの異なる太さ(太字、斜体など)をサポートしていないため、筆者には適していません。

そこで私はFontainを試してみました。これにより、カスタムビューを定義し、それらにカスタムフォントファミリーを適用できます。

Fontainを使用するには、アプリモジュールbuild.gradleに以下を追加する必要があります。

compile 'com.scopely:fontain:1.0.0'

次に、通常のTextViewを使用する代わりに、FontTextViewを使用する必要があります

大文字と太字のコンテンツを含むFontTextViewの例:

 <com.scopely.fontain.views.FontTextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/black"
            android:textColor="@android:color/white"
            android:textSize="11dp"
            android:gravity="center"
            android:id="@+id/tv1"
            app:font_family="myCustomFont"
            app:caps_mode="characters"
            app:font_weight="BOLD"/>

0
package com.theeasylearn.demo.designdemo;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;

public class MyButton extends TextView {

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

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyButton(Context context) {
        super(context);
        init();
    }

    private void init() {

            Typeface tf =
                    Typeface.createFromAsset(
                            getContext().getAssets(), "angelina.TTF");
            setTypeface(tf);

    }

}

完璧な解決策ではありません。このソリューションを使用すると、アクセスのデフォルトのAndroidにカスタムの回避策が必要になりますTextViewS
blueware

0

TextViewのデフォルトのフォントファミリーを変更するには、アプリのテーマでtextViewStyleをオーバーライドします。

fontFamilyでカスタムフォントを使用するには、サポートライブラリにあるフォントリソースを使用します。

この機能はAndroid 26で追加されましたが、supportlibを介して古いバージョンにバックポートされました。

https://developer.android.com/guide/topics/resources/font-resource.html https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html #using-support-lib


0

Android Oreoとそのサポートライブラリ(26.0.0)のリリース以降、これは簡単に実行できます。別の質問でこの回答を参照しください。

基本的に、最終的なスタイルは次のようになります。

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
   <item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 -->
</style>


-15

はい、フォントをアプリケーション全体に設定することは可能です。

これを実現する最も簡単な方法は、目的のフォントをアプリケーションにパッケージ化することです。

これを行うに は、プロジェクトのルートにassets /フォルダーを作成し、フォント(TrueTypeまたはTTF形式)をアセットに配置します。

たとえば、assets / fonts / を作成して、そこにTTFファイルを置くことができます。

public class FontSampler extends Activity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView tv=(TextView)findViewById(R.id.custom);

Typeface face=Typeface.createFromAsset(getAssets(), "fonts/HandmadeTypewriter.ttf");
tv.setTypeface(face);
}
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.