1. ホーム
  2. android

[解決済み] Androidです。ランタイムではなく、アプリケーション全体にカスタムフォントを設定したい

2023-01-10 01:12:15

質問

アプリケーションのすべてのコントロールに任意のカスタムフォントを設定することは可能でしょうか?また、必ずしもランタイムでなくてもよいのでしょうか。(すなわち、可能であれば xml から、または JAVA ファイルでアプリケーション全体に対して一度だけ)

私はこのコードから1つのコントロールのためにフォントを設定することができます。

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

    textView.setTypeface(tf);

}

このコードの問題は、すべてのコントロールに対して呼び出される必要があることです。そして、私はこのまたは類似のメソッドを一度だけ呼び出したい、または可能であればxmlでプロパティを設定します。 それは可能ですか?

どのように解決するには?

編集 : というわけで、久しぶりに、私が考えるベストな方法を追加したいと思います。

まず、カスタマイズしたいViewをオーバーライドする新しいクラスを作成する必要があります。(例: カスタム書体のボタンが必要ですか? 拡張する 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ドキュメントを 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に別の属性を追加することができます -- bold, italicなど)。

<?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: の接頭辞がつきます。

最後にもうひとつ、これをスタイルで使う場合 ( res/values/styles.xml ) で使用する場合は ではなく を追加します。 xmlns:custom の行を追加します。プレフィックスを付けずに属性名を参照するだけです。

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


                               (PREVIOUS ANSWER)

Androidでカスタム書体を使用する

これは役に立つはずです。基本的に、XML でこれを行う方法はありませんし、私が知る限り、コードでこれを行うより簡単な方法もありません。書体を一度作成する setLayoutFont() メソッドを常に持つことができ、その後、各書体に対して setTypeface() を実行します。レイアウトに新しいアイテムを追加するたびに、それを更新する必要があります。以下のようなものです。

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

EDIT : ということで、自分でも実装してみたのですが、結局はこんな感じの関数を作ってみました。

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

あとはonCreate()からこのメソッドを使い、更新したいTextViewを全て渡せばOKです。

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 ビューを表示し、ID で指定することなくフォントを設定することができます。もちろん、これはフォントを ごとに ビューにフォントを設定することを想定しています。