programing

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

closeapi 2023. 10. 8. 09:53
반응형

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

제가 만들고 있는 안드로이드 어플리케이션에 커스텀 폰트를 사용하고 싶습니다.
나는 코드에서 각 개체의 서체를 개별적으로 변경할 수 있지만 수백 개의 서체를 가지고 있습니다.

그렇게,

  • XML에서 이 작업을 수행할 수 있는 방법이 있습니까? [사용자 지정 서체 설정]
  • 전체 애플리케이션과 모든 구성 요소가 기본 서체가 아닌 사용자 지정 서체를 사용해야 한다는 것을 한 곳에서 코드로 수행할 수 있는 방법이 있습니까?

네 가능합니다.

텍스트 보기를 확장하는 사용자 정의 보기를 작성해야 합니다.

attrs.xml인에values폴더:

<resources>
    <declare-styleable name="MyTextView">
        <attr name="first_name" format="string"/>
        <attr name="last_name" format="string"/>
        <attr name="ttf_name" format="string"/>
    </declare-styleable>
</resources>

main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:lht="http://schemas.android.com/apk/res/com.lht"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView  android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:text="Hello"/>
    <com.lht.ui.MyTextView  
        android:id="@+id/MyTextView"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:text="Hello friends"
        lht:ttf_name="ITCBLKAD.TTF"
        />   
</LinearLayout>

MyTextView.java:

package com.lht.ui;

import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

public class MyTextView extends TextView {

    Context context;
    String ttfName;

    String TAG = getClass().getName();

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;

        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            Log.i(TAG, attrs.getAttributeName(i));
            /*
             * Read value of custom attributes
             */

            this.ttfName = attrs.getAttributeValue(
                    "http://schemas.android.com/apk/res/com.lht", "ttf_name");
            Log.i(TAG, "firstText " + firstText);
            // Log.i(TAG, "lastText "+ lastText);

            init();
        }

    }

    private void init() {
        Typeface font = Typeface.createFromAsset(context.getAssets(), ttfName);
        setTypeface(font);
    }

    @Override
    public void setTypeface(Typeface tf) {

        // TODO Auto-generated method stub
        super.setTypeface(tf);
    }

}

XML에서 이것을 할 수 있는 방법이 있습니까?

아니요, 미안해요.XML을 통해서만 내장 서체를 지정할 수 있습니다.

전체 애플리케이션과 모든 구성 요소가 기본 서체가 아닌 사용자 지정 서체를 사용해야 한다는 것을 한 곳에서 코드로 수행할 수 있는 방법이 있습니까?

내가 알고 있는 것은 아닙니다.

요즘에는 다음과 같은 다양한 옵션이 있습니다.

레이아웃 xml이나 Activities를 변경할 필요가 없는 보다 "잔인한 힘"의 방식으로 이 작업을 수행했습니다.

Android 버전 2.1에서 4.4까지 테스트되었습니다.응용 프로그램 클래스에서 앱 시작 시 실행:

private void setDefaultFont() {

    try {
        final Typeface bold = Typeface.createFromAsset(getAssets(), DEFAULT_BOLD_FONT_FILENAME);
        final Typeface italic = Typeface.createFromAsset(getAssets(), DEFAULT_ITALIC_FONT_FILENAME);
        final Typeface boldItalic = Typeface.createFromAsset(getAssets(), DEFAULT_BOLD_ITALIC_FONT_FILENAME);
        final Typeface regular = Typeface.createFromAsset(getAssets(),DEFAULT_NORMAL_FONT_FILENAME);

        Field DEFAULT = Typeface.class.getDeclaredField("DEFAULT");
        DEFAULT.setAccessible(true);
        DEFAULT.set(null, regular);

        Field DEFAULT_BOLD = Typeface.class.getDeclaredField("DEFAULT_BOLD");
        DEFAULT_BOLD.setAccessible(true);
        DEFAULT_BOLD.set(null, bold);

        Field sDefaults = Typeface.class.getDeclaredField("sDefaults");
        sDefaults.setAccessible(true);
        sDefaults.set(null, new Typeface[]{
                regular, bold, italic, boldItalic
        });

    } catch (NoSuchFieldException e) {
        logFontError(e);
    } catch (IllegalAccessException e) {
        logFontError(e);
    } catch (Throwable e) {
        //cannot crash app if there is a failure with overriding the default font!
        logFontError(e);
    }
}

보다 완벽한 예는 http://github.com/perchrh/FontOverrideExample 을 참조하십시오.

Manish의 답변을 가장 빠르고 목표로 하는 방법으로 지지하고 있지만, 보기 계층 구조를 통해 재귀적으로 반복하고 모든 요소의 서체를 차례로 업데이트하는 순진한 솔루션도 보았습니다.이와 같은 것:

public static void applyFonts(final View v, Typeface fontToSet)
{
    try {
        if (v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++) {
                View child = vg.getChildAt(i);
                applyFonts(child, fontToSet);
            }
        } else if (v instanceof TextView) {
            ((TextView)v).setTypeface(fontToSet);
        }
    } catch (Exception e) {
        e.printStackTrace();
        // ignore
    }
}

에서 에서 이 .onContentChanged()방법들.

이를 중앙 집중식으로 수행할 수 있었습니다. 그 결과는 다음과 같습니다.

enter image description here

과 같은 가 .Activity사용자 지정 글꼴이 필요한 경우 확장합니다.

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater.Factory;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class CustomFontActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    getLayoutInflater().setFactory(new Factory() {

        @Override
        public View onCreateView(String name, Context context,
                AttributeSet attrs) {
            View v = tryInflate(name, context, attrs);
            if (v instanceof TextView) {
                setTypeFace((TextView) v);
            }
            return v;
        }
    });
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

private View tryInflate(String name, Context context, AttributeSet attrs) {
    LayoutInflater li = LayoutInflater.from(context);
    View v = null;
    try {
        v = li.createView(name, null, attrs); 
    } catch (Exception e) {
        try {
            v = li.createView("android.widget." + name, null, attrs);
        } catch (Exception e1) {
        }
    }
    return v;
}

private void setTypeFace(TextView tv) {
    tv.setTypeface(FontUtils.getFonts(this, "MTCORSVA.TTF"));
}
}

하지만 지원 패키지의 활동을 사용하는 경우에는 예를 예로 들 수 있습니다.FragmentActivity그럼 이걸 사용합니다.Activity:

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class CustomFontFragmentActivity extends FragmentActivity {

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

// we can't setLayout Factory as its already set by FragmentActivity so we
// use this approach
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    View v = super.onCreateView(name, context, attrs);
    if (v == null) {
        v = tryInflate(name, context, attrs);
        if (v instanceof TextView) {
            setTypeFace((TextView) v);
        }
    }
    return v;
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public View onCreateView(View parent, String name, Context context,
        AttributeSet attrs) {
    View v = super.onCreateView(parent, name, context, attrs);
    if (v == null) {
        v = tryInflate(name, context, attrs);
        if (v instanceof TextView) {
            setTypeFace((TextView) v);
        }
    }
    return v;
}

private View tryInflate(String name, Context context, AttributeSet attrs) {
    LayoutInflater li = LayoutInflater.from(context);
    View v = null;
    try {
        v = li.createView(name, null, attrs);
    } catch (Exception e) {
        try {
            v = li.createView("android.widget." + name, null, attrs);
        } catch (Exception e1) {
        }
    }
    return v;
}

private void setTypeFace(TextView tv) {
    tv.setTypeface(FontUtils.getFonts(this, "MTCORSVA.TTF"));
}
}

로 이 코드를 본 적이 .Fragment아직, 하지만 잘 되기를 바랍니다.

나의FontUtils간단하기 때문에 여기 https://code.google.com/p/android/issues/detail?id=9904 에서 언급된 ICS 이전 문제도 해결할 수 있습니다.

import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.graphics.Typeface;

public class FontUtils {

private static Map<String, Typeface> TYPEFACE = new HashMap<String, Typeface>();

public static Typeface getFonts(Context context, String name) { 
    Typeface typeface = TYPEFACE.get(name);
    if (typeface == null) {
        typeface = Typeface.createFromAsset(context.getAssets(), "fonts/"
                + name);
        TYPEFACE.put(name, typeface);
    }
    return typeface;
}
}

안녕하세요 저는 또한 다른 와이드지를 위해 제 앱에 2개의 다른 폰트가 필요합니다!이 방법을 사용합니다.

응용프로그램 클래스에서 정적 메서드를 만듭니다.

public static Typeface getTypeface(Context context, String typeface) {
    if (mFont == null) {
        mFont = Typeface.createFromAsset(context.getAssets(), typeface);
    }
    return mFont;
}

문자열 서체는 자산 폴더의 xyz.ttf를 나타냅니다.(Constants Class를 만들었습니다) 이제 앱의 모든 곳에서 이를 사용할 수 있습니다.

mTextView = (TextView) findViewById(R.id.text_view);
mTextView.setTypeface(MyApplication.getTypeface(this, Constants.TYPEFACE_XY));

유일한 문제는 글꼴을 사용하려는 모든 위젯에 필요하다는 것입니다!하지만 저는 이게 최선의 방법이라고 생각합니다.

는 pospi의 제안Richard가 했던 것처럼 'tag' 속성을 이용하여 커스텀 폰트를 로드하고 그들의 태그에 따라 뷰에 적용하는 커스텀 클래스를 만들었습니다.

기본적으로 속성 Android:fontFamily에서 TypeFace를 설정하는 대신 Android:tag Attritube를 사용하여 정의된 enum 중 하나로 설정합니다.

public class Fonts {
    private AssetManager mngr;

    public Fonts(Context context) {
        mngr = context.getAssets();
    }
    private enum AssetTypefaces {
        RobotoLight,
        RobotoThin,
        RobotoCondensedBold,
        RobotoCondensedLight,
        RobotoCondensedRegular
    }

    private Typeface getTypeface(AssetTypefaces font) {
        Typeface tf = null;
        switch (font) {
            case RobotoLight:
                tf = Typeface.createFromAsset(mngr,"fonts/Roboto-Light.ttf");
                break;
            case RobotoThin:
                tf = Typeface.createFromAsset(mngr,"fonts/Roboto-Thin.ttf");
                break;
            case RobotoCondensedBold:
                tf = Typeface.createFromAsset(mngr,"fonts/RobotoCondensed-Bold.ttf");
                break;
            case RobotoCondensedLight:
                tf = Typeface.createFromAsset(mngr,"fonts/RobotoCondensed-Light.ttf");
                break;
            case RobotoCondensedRegular:
                tf = Typeface.createFromAsset(mngr,"fonts/RobotoCondensed-Regular.ttf");
                break;
            default:
                tf = Typeface.DEFAULT;
                break;
        }
        return tf;
    }
    public void setupLayoutTypefaces(View v) {
        try {
            if (v instanceof ViewGroup) {
                ViewGroup vg = (ViewGroup) v;
                for (int i = 0; i < vg.getChildCount(); i++) {
                    View child = vg.getChildAt(i);
                    setupLayoutTypefaces(child);
                }
            } else if (v instanceof TextView) {
                if (v.getTag().toString().equals(AssetTypefaces.RobotoLight.toString())){
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoLight));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoCondensedRegular.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoCondensedRegular));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoCondensedBold.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoCondensedBold));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoCondensedLight.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoCondensedLight));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoThin.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoThin));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            // ignore
        }
    }
}

활동 또는 조각에서 호출만 하면 됩니다.

Fonts fonts = new Fonts(getActivity());
fonts.setupLayoutTypefaces(mainLayout);

리사 레이의 블로그에서 좋은 해결책을 찾았습니다.새 데이터 바인딩을 사용하면 XML 파일의 글꼴을 설정할 수 있습니다.

@BindingAdapter({"bind:font"})
public static void setFont(TextView textView, String fontName){
    textView.setTypeface(Typeface.createFromAsset(textView.getContext().getAssets(), "fonts/" + fontName));
}

XML의 경우:

<TextView
app:font="@{`Source-Sans-Pro-Regular.ttf`}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

좀 더 쉽게 할 수 있는 방법이 있을 것 같습니다.다음 클래스는 응용프로그램의 모든 구성요소에 대해 사용자 정의 서체를 설정합니다(클래스당 설정).

/**
 * Base Activity of our app hierarchy.
 * @author SNI
 */
public class BaseActivity extends Activity {

    private static final String FONT_LOG_CAT_TAG = "FONT";
    private static final boolean ENABLE_FONT_LOGGING = false;

    private Typeface helloTypeface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        helloTypeface = Typeface.createFromAsset(getAssets(), "fonts/<your type face in assets/fonts folder>.ttf");
    }

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        View view = super.onCreateView(name, context, attrs);
        return setCustomTypeFaceIfNeeded(name, attrs, view);
    }

    @Override
    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
        View view = super.onCreateView(parent, name, context, attrs);
        return setCustomTypeFaceIfNeeded(name, attrs, view);
    }

    protected View setCustomTypeFaceIfNeeded(String name, AttributeSet attrs, View view) {
        View result = null;
        if ("TextView".equals(name)) {
            result = new TextView(this, attrs);
            ((TextView) result).setTypeface(helloTypeface);
        }

        if ("EditText".equals(name)) {
            result = new EditText(this, attrs);
            ((EditText) result).setTypeface(helloTypeface);
        }

        if ("Button".equals(name)) {
            result = new Button(this, attrs);
            ((Button) result).setTypeface(helloTypeface);
        }

        if (result == null) {
            return view;
        } else {
            if (ENABLE_FONT_LOGGING) {
                Log.v(FONT_LOG_CAT_TAG, "A type face was set on " + result.getId());
            }
            return result;
        }
    }

}

LayoutInflater의 기본 구현에서는 xml에서 글꼴 글꼴을 지정할 수 없습니다.그러나 저는 xml 태그에서 그러한 속성을 파싱할 LayoutInflater에 대한 커스텀 팩토리를 제공함으로써 xml에서 수행되는 것을 보았습니다.

기본적인 구조는 이렇게 할 겁니다.

public class TypefaceInflaterFactory implements LayoutInflater.Factory {

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        // CUSTOM CODE TO CREATE VIEW WITH TYPEFACE HERE
        // RETURNING NULL HERE WILL TELL THE INFLATER TO USE THE
        // DEFAULT MECHANISMS FOR INFLATING THE VIEW FROM THE XML
    }

}

public class BaseActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater.from(this).setFactory(new TypefaceInflaterFactory());
    }
}

문서에서는 이러한 메커니즘과 작성자가 이러한 방식으로 서체에 대한 xml 레이아웃 지원을 어떻게 제공하려고 하는지에 대한 자세한 설명을 제공합니다.저자의 구현 코드는 여기에서 확인할 수 있습니다.

일반 ProgressDialog/AlertDialog: 사용자 정의 글꼴을 일반 ProgressDialog/AlertDialog:

font=Typeface.createFromAsset(getAssets(),"DroidSans.ttf");

ProgressDialog dialog = ProgressDialog.show(this, "titleText", "messageText", true);
((TextView)dialog.findViewById(Resources.getSystem().getIdentifier("message", "id", "android"))).setTypeface(font);
((TextView)dialog.findViewById(Resources.getSystem().getIdentifier("alertTitle", "id", "android"))).setTypeface(font);

예, 기본 서체를 재정의하여 가능합니다.는 이 솔루션을 따랐고, 한 번의 변경으로 모든 텍스트 뷰와 ActionBar 텍스트에도 매력적으로 작용했습니다.

public class MyApp extends Application {

  @Override
  public void onCreate() {
    TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/Roboto-Regular.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
  }
}

styles.xml

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/pantone</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>
    <item name="android:windowDisablePreview">true</item>
    <item name="android:typeface">serif</item>
</style>

위 링크에서 언급한 memes.xml 대신, 저는 저의 기본 앱 테마 태그에서 styles.xml에서 재정의할 기본 글꼴을 언급했습니다.덮어쓸 수 있는 기본 서체는 serif, sans, monospace 및 normal입니다.

글꼴 Util.java

public class TypefaceUtil {

    /**
     * Using reflection to override default typeface
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN
     * @param context to work with assets
     * @param defaultFontNameToOverride for example "monospace"
     * @param customFontFileNameInAssets file name of the font from assets
     */
    public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
        try {
            final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

            final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
            defaultFontTypefaceField.setAccessible(true);
            defaultFontTypefaceField.set(null, customFontTypeface);
        } catch (Exception e) {
            Log.e("Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
        }
    }
}

처음에는 덮어쓸 서체가 고정되어 있고 정의된 값이 설정되어 있다는 것을 몰랐지만, 결국 안드로이드가 글꼴과 서체를 어떻게 다루는지, 그리고 기본값을 어떻게 다루는지 이해하는 데 도움이 되었고, 이는 물론 다른 점입니다.

저는 이를 위해 (코틀린과 함께) DataBinding을 사용합니다.


바인딩 어댑터 설정:

BindingAdapter.kt

import android.graphics.Typeface
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.databinding.BindingAdapter
import java.util.*


object BindingAdapters {


    @JvmStatic
    @BindingAdapter("typeface", "typefaceStyle")
    fun setTypeface(v: TextView, tf: Typeface?, style: Int?) {
        v.setTypeface(tf ?: Typeface.DEFAULT, style ?: Typeface.NORMAL)
    }
}

용도:

fragment_custom_view.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="android.graphics.Typeface" />

        <variable
            name="typeface"
            type="android.graphics.Typeface" />

    </data>


    <TextView
        android:id="@+id/reference"
        style="@style/TextAppearance.MaterialComponents.Body1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="I'm formatted text"
        app:typeface="@{typeface}"
        app:typefaceStyle="@{Typeface.ITALIC}" />

</layout>

My Fragment.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding = FragmentCustomView.bind(view)
        binding.typeface = // some code to get user selected typeface

}

이제 사용자가 새 서체를 선택하면 바인딩 값과 설정한 모든 텍스트 보기를 업데이트할 수 있습니다.app:typeface업데이트 될 것입니다.

앱 전체가 바뀌는지는 모르겠지만, 다른 방법으로는 바꿀 수 없는 일부 구성 요소를 변경할 수 있었습니다.

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

pospi의 제안이 마음에 듭니다.XML에서 할 수 없는 추가 스타일링을 지정하기 위해 뷰의 '태그' 속성(XML - 'android:tag'에서 지정 가능)을 사용하는 것은 어떨까요. 저는 JSON을 좋아하기 때문에 키/값 집합을 지정하기 위해 JSON 문자열을 사용합니다.이 수업은 효과가 있습니다. 전화만 하면 됩니다.Style.setContentView(this, [resource id])당신의 활동중에

public class Style {

  /**
   * Style a single view.
   */
  public static void apply(View v) {
    if (v.getTag() != null) {
      try {
        JSONObject json = new JSONObject((String)v.getTag());
        if (json.has("typeface") && v instanceof TextView) {
          ((TextView)v).setTypeface(Typeface.createFromAsset(v.getContext().getAssets(),
                                                             json.getString("typeface")));
        }
      }
      catch (JSONException e) {
        // Some views have a tag without it being explicitly set!
      }
    }
  }

  /**
   * Style the passed view hierarchy.
   */
  public static View applyTree(View v) {
    apply(v);
    if (v instanceof ViewGroup) {
      ViewGroup g = (ViewGroup)v;
      for (int i = 0; i < g.getChildCount(); i++) {
        applyTree(g.getChildAt(i));
      }
    }
    return v;
  }

  /**
   * Inflate, style, and set the content view for the passed activity.
   */
  public static void setContentView(Activity activity, int resource) {
    activity.setContentView(applyTree(activity.getLayoutInflater().inflate(resource, null)));
  }
}

분명히 JSON을 사용하는 것을 가치 있게 만들기 위해 서체 이상의 것을 다루고 싶을 것입니다.

'태그' 속성의 장점은 테마로 사용하는 기본 스타일에 설정하여 모든 보기에 자동으로 적용할 수 있다는 것입니다.편집: 이렇게 하면 Android 4.0.3에서 인플레이션이 발생하는 동안 충돌이 발생합니다.스타일을 사용하여 텍스트 보기에 개별적으로 적용할 수도 있습니다.

코드에서 한 가지를 보게 될 것입니다. 일부 보기에는 태그가 명시적으로 설정되지 않은 태그가 있습니다. 이상하게도 그것은 'α ποκοπή'라는 문자열입니다. 구글 번역에 따르면, 그리스어로 '컷'되어 있다고 합니다.대체...?

@majinboo의 답변은 성능과 메모리 관리를 위해 수정되었습니다.둘 이상의 글꼴 필요 관련 활동은 생성자 자체를 매개변수로 지정하여 이 글꼴 클래스를 사용할 수 있습니다.

@Override
public void onCreate(Bundle savedInstanceState)
{
    Font font = new Font(this);
}

수정된 글꼴 클래스는 다음과 같습니다.

public class Fonts
{
    private HashMap<AssetTypefaces, Typeface> hashMapFonts;

    private enum AssetTypefaces
    {
        RobotoLight,
        RobotoThin,
        RobotoCondensedBold,
        RobotoCondensedLight,
        RobotoCondensedRegular
    }

    public Fonts(Context context)
    {
        AssetManager mngr = context.getAssets();

        hashMapFonts = new HashMap<AssetTypefaces, Typeface>();
        hashMapFonts.put(AssetTypefaces.RobotoLight, Typeface.createFromAsset(mngr, "fonts/Roboto-Light.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoThin, Typeface.createFromAsset(mngr, "fonts/Roboto-Thin.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoCondensedBold, Typeface.createFromAsset(mngr, "fonts/RobotoCondensed-Bold.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoCondensedLight, Typeface.createFromAsset(mngr, "fonts/RobotoCondensed-Light.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoCondensedRegular, Typeface.createFromAsset(mngr, "fonts/RobotoCondensed-Regular.ttf"));
    }

    private Typeface getTypeface(String fontName)
    {
        try
        {
            AssetTypefaces typeface = AssetTypefaces.valueOf(fontName);
            return hashMapFonts.get(typeface);
        }
        catch (IllegalArgumentException e)
        {
            // e.printStackTrace();
            return Typeface.DEFAULT;
        }
    }

    public void setupLayoutTypefaces(View v)
    {
        try
        {
            if (v instanceof ViewGroup)
            {
                ViewGroup vg = (ViewGroup) v;
                for (int i = 0; i < vg.getChildCount(); i++)
                {
                    View child = vg.getChildAt(i);
                    setupLayoutTypefaces(child);
                }
            }
            else if (v instanceof TextView)
            {
                ((TextView) v).setTypeface(getTypeface(v.getTag().toString()));
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            // ignore
        }
    }
}

Xamarin에서 일하고 있습니다.안드로이드:

클래스:

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>

안드로이드 O로 맞춤 글꼴 사용이 쉬워진 것 같은데, 기본적으로 xml을 사용하면 됩니다.참고용으로 Android 공식 문서 링크를 첨부하였으며, 이를 통해 여전히 이 솔루션이 필요한 사람들에게 도움이 되기를 바랍니다.Android에서 사용자 지정 글꼴 작업

Android 8.0(API 레벨 26)부터 XML에서 사용자 정의 글꼴을 사용할 수 있음을 알면 유용할 수 있습니다.

간단히 말하면 다음과 같은 방법으로 할 수 있습니다.

  1. .res/font.

  2. 위젯 속성에 사용할 수 있습니다.

<Button android:fontFamily="@font/myfont"/>

, 에 res/values/styles.xml

<style name="MyButton" parent="android:Widget.Button">
    <item name="android:fontFamily">@font/myfont</item>
</style>

스타일로 활용할 수 있습니다.

<Button style="@style/MyButton"/>

xml 파일에서 "fontPath" 속성을 직접 사용합니다.

style.xml에 사용하기 위해

<상품명="fontPath">fonts/프록시마노바 세미볼드.ttf</item>

직접 레이아웃 파일에 사용하기 위해

fontPath="fonts/ProximaNovaBold.ttf"

(참고 : 접두사에서 app/android 속성을 사용할 필요 없음)

절대 가능합니다.여러 가지 방법이 있습니다.가장 빠른 방법, Try-catch 방법으로 조건 만들기..특정 글꼴 스타일 조건을 사용해 보고 오류를 잡고 다른 글꼴 스타일을 정의합니다.

언급URL : https://stackoverflow.com/questions/2973270/using-a-custom-typeface-in-android

반응형