전체 Android 앱에 기본 글꼴 모음을 설정하는 방법


282

내 앱에서 Roboto light 글꼴을 사용하고 있습니다. 글꼴을 설정하려면 android:fontFamily="sans-serif-light"모든보기에 를 추가해야 합니다. Roboto 글꼴을 전체 앱의 기본 글꼴 모음으로 선언하는 방법이 있습니까? 나는 이렇게 시도했지만 작동하지 않는 것 같습니다.

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

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

2
이것은 당신을 도울 수 있습니다 : stackoverflow.com/a/16883281/1329733
Jacob R

답변:


289

대답은 '예'입니다.

글로벌 로봇 조명 TextViewButton클래스 :

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="android:buttonStyle">@style/RobotoButtonStyle</item>
</style>

<style name="RobotoTextViewStyle" parent="android:Widget.TextView">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

<style name="RobotoButtonStyle" parent="android:Widget.Holo.Button">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

themes.xml 목록에서 원하는 스타일을 선택한 다음 원래 스타일을 기반으로 사용자 정의 스타일을 만듭니다. 마지막으로 응용 프로그램의 테마로 스타일을 적용하십시오.

<application
    android:theme="@style/AppTheme" >
</application>

Roboto와 같은 내장 글꼴에서만 작동하지만 문제였습니다. 애셋에서로드 된 사용자 정의 글꼴의 경우이 방법이 작동하지 않습니다.

08/13/15 수정

AppCompat 테마를 사용하는 경우 android:접두사 를 제거해야 합니다. 예를 들면 다음과 같습니다.

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="buttonStyle">@style/RobotoButtonStyle</item>
</style>

(가) 주 buttonStyle포함하지 않는 android:접두사를하지만, textViewStyle그것을 포함해야합니다.


4
어디에서 sans-serif-light가치 를 얻었 습니까? fontFamily어딘가에 유효한 값 목록이 있습니까? Android 소스의 테마 및 스타일 파일뿐만 아니라 문서를 살펴본 결과 아무것도 찾을 수 없습니다.
Christopher Perry

34
이것은 API 레벨 16에서만 가능합니다. "android : fontFamily"라는 이름은 16 레벨 이상에서만 존재합니다. 예를 들어 API 14에서도 그렇게 할 수있는 방법이 있습니까?
Lorenzo Barbagli

3
@LorenzoBarbagli, 당신은 서예
Brais Gabin

10
사용자 정의 글꼴이 있으면 어떻게해야합니까?
Rohit Tigga

2
예, 전체 앱에 맞춤 글꼴을 추가하고 싶습니다. 어떻게해야합니까?. 첫 번째 답변에서 제안한대로 TextView를 재정의하고 모든 TextView를 바꾸어야합니까
John

144

Android Oreo가 출시되면 지원 라이브러리를 사용하여이 목표를 달성 할 수 있습니다.

  1. 지원 라이브러리 > = 26.0.0 이있는 경우 앱 build.gradle을 확인하십시오.
  2. 리소스 폴더에 " font "폴더를 추가하고 거기에 글꼴을 추가하십시오
  3. 앱 기본 스타일에서 기본 글꼴 모음을 참조하십시오.

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

자세한 내용은 https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html 을 확인 하십시오 .


9
API 26+를 타겟팅 할 때는 이것이 허용되는 방법이어야합니다. 지원 라이브러리를 사용 하는 경우 android:접두사를 제거하십시오.
webo80

2
접두사를 사용하지 않는 경우에만 문제가 없습니다. 단지 API <26 무시됩니다 앞에 둔 한
webo80

2
이것은 어디서나 글꼴을 설정하지 않습니다. 예를 들어 Base.TextAppearance.AppCompat, 에서 파생 된 스타일이있는 경우 에는 사용되지 않습니다.
Ixx

3
@ Ixx, 그 스타일을 재정의하는 방법?
Primož Kralj

2
api <26
Codelicious을

37

앱 글꼴을 변경하려면 다음 단계를 따르십시오.

  1. res디렉토리 안에 새 디렉토리를 만들고 호출합니다 font.
  2. 서체 폴더 안에 서체 .ttf / .otf를 삽입하십시오. 서체 이름은 소문자와 밑줄 만 사용해야합니다.
  3. 내부 res-> values-> styles.xml내부 <resources>-> <style>글꼴을 추가하십시오 <item name="android:fontFamily">@font/font_name</item>.

여기에 이미지 설명을 입력하십시오

이제 모든 앱 텍스트는 추가 한 내용에 속합니다.


8
사용자 정의 글꼴을 사용하는 동안 일반 글꼴과 함께 굵은 글꼴을 추가하려면 어떻게해야합니까?
Rajbir Shienh

API 레벨 26 이상에서만 작동합니다. API 21 이하는 어떻습니까?
zulkarnain shah

34

아래의 업데이트 읽기

새 글꼴을 포함하는 것과 동일한 문제가 발생하여 마침내 TextView를 확장하고 내부에서 글꼴을 설정하는 작업을 수행했습니다.

public class YourTextView extends TextView {

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

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

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

    private void init() {
        Typeface tf = Typeface.createFromAsset(context.getAssets(),
            "fonts/helveticaneue.ttf");
        setTypeface(tf);
    }
}

나중에 모든 요소에서 TextView 요소를에서 요소로 변경해야합니다. 그리고 Eclipse에서 UI-Creator를 사용하면 때로는 TextView가 올바르게 표시되지 않습니다. 나를 위해 일한 유일한 사람이었습니다 ...

최신 정보

요즘에는 TextView를 확장하지 않고 전체 응용 프로그램에서 서체를 변경하기 위해 리플렉션을 사용하고 있습니다. 이 SO 게시물을 확인하십시오

업데이트 2

API 레벨 26부터 '지원 라이브러리'에서 사용 가능

android:fontFamily="@font/embeddedfont"

추가 정보 : XML의 글꼴


25
이것은 해결책이 아닙니다. TextView뿐만 아니라 많은 다른보기를 사용하고 있습니다. 글꼴을 한 번 설정하고 잊고 싶습니다. 또한 코드는 모든 TextView에 대해 새 객체를 만듭니다. 최소한 애셋에서 글꼴을 한 번로드하려면 필드를 정적으로 선언하십시오.
tomrozb

2
...이 경우에는 정말 잘 작동하는 찾기 및 바꾸기 기능이 있습니다.
longi

1
작동하지 않습니다. getContext()변수가 정적 일 때는 호출 할 수 없습니다 . 단일 방식으로 구현해야합니다. 그렇지 않으면 현재 코드가 컴파일되지 않습니다.
tomrozb

1
나는 마지막 커밋을 되 돌렸다.
longi

1
@tomrozb : D 방금 내가 한 마지막 빠른 변화는 당신의 의견 때문이라는 것을 깨달았습니다! 포인트가 충분하면 코드 예제를 직접 최적화 할 수 있습니다. 그렇지 않으면 우리는 여전히 때 스마트 폰에 대해 아무도 걱정은 더 이상 몇 년의 주제에 대해 이야기합니다)
longi

8

이 코드 줄을 res / value / styles.xml에 추가하십시오.

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

전체 스타일은 다음과 같습니다

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:fontFamily">@font/circular_medium</item>
</style>

"circular_medium"을 자신의 글꼴 이름으로 변경하십시오.


6

성능에 대해 이야기하지 말고 사용자 정의 글꼴의 경우 모든보기를 통해 재귀 메서드 루프를 사용하고 TextView 인 경우 서체를 설정할 수 있습니다.

public class Font {
    public static void setAllTextView(ViewGroup parent) {
        for (int i = parent.getChildCount() - 1; i >= 0; i--) {
            final View child = parent.getChildAt(i);
            if (child instanceof ViewGroup) {
                setAllTextView((ViewGroup) child);
            } else if (child instanceof TextView) {
                ((TextView) child).setTypeface(getFont());
            }
        }
    }

    public static Typeface getFont() {
        return Typeface.createFromAsset(YourApplicationContext.getInstance().getAssets(), "fonts/whateverfont.ttf");
    }
}

모든 활동에서 setContentView 후에 현재 ViewGroup을 전달하십시오.

ViewGroup group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
Font.setAllTextView(group);

조각의 경우 비슷한 것을 할 수 있습니다.


1
recyclerView 컨텐츠에서 작동하게 만드는 방법이 궁금합니다.
Srujan Barai 2016 년

방금 시도했습니다. 렌더링하기에는 너무 무겁습니다. 아래로 둔화 recyclerView지옥 같은합니다.
Srujan Barai 2016 년

목록보기에는 전혀 권장되지 않지만이 트릭은 정적보기를 코딩하는 시간을 절약하기위한 것입니다.
Allen Chan

5

전체 앱 에서이 작업을 수행하는 또 다른 방법은이 답변을 기반으로 리플렉션을 사용하는 것입니다.

public class TypefaceUtil {
    /**
     * Using reflection to override default typefaces
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE
     * OVERRIDDEN
     *
     * @param typefaces map of fonts to replace
     */
    public static void overrideFonts(Map<String, Typeface> typefaces) {
        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", "Can not set custom fonts");
        }
    }

    public static Typeface getTypeface(int fontType, Context context) {
        // here you can load the Typeface from asset or use default ones
        switch (fontType) {
            case BOLD:
                return Typeface.create(SANS_SERIF, Typeface.BOLD);
            case ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.ITALIC);
            case BOLD_ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.BOLD_ITALIC);
            case LIGHT:
                return Typeface.create(SANS_SERIF_LIGHT, Typeface.NORMAL);
            case CONDENSED:
                return Typeface.create(SANS_SERIF_CONDENSED, Typeface.NORMAL);
            case THIN:
                return Typeface.create(SANS_SERIF_MEDIUM, Typeface.NORMAL);
            case MEDIUM:
                return Typeface.create(SANS_SERIF_THIN, Typeface.NORMAL);
            case REGULAR:
            default:
                return Typeface.create(SANS_SERIF, Typeface.NORMAL);
        }
    }
}

그런 다음 글꼴을 재정의 할 때마다 메서드를 호출하고 다음과 같이 서체 맵을 제공 할 수 있습니다.

Typeface regular = TypefaceUtil.getTypeface(REGULAR, context);
Typeface light = TypefaceUtil.getTypeface(REGULAR, context);
Typeface condensed = TypefaceUtil.getTypeface(CONDENSED, context);
Typeface thin = TypefaceUtil.getTypeface(THIN, context);
Typeface medium = TypefaceUtil.getTypeface(MEDIUM, context);
Map<String, Typeface> fonts = new HashMap<>();
fonts.put("sans-serif", regular);
fonts.put("sans-serif-light", light);
fonts.put("sans-serif-condensed", condensed);
fonts.put("sans-serif-thin", thin);
fonts.put("sans-serif-medium", medium);
TypefaceUtil.overrideFonts(fonts);

전체 예제 확인

이전 버전의 Android SDK 21 이상에서만 작동합니다. 전체 예를 확인하십시오.


5

이 lib를 사용하여 등급 파일로 컴파일하십시오.

complie'me.anwarshahriar:calligrapher:1.0'

주요 활동의 onCreate 메소드에서 사용하십시오.

Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "yourCustomFontHere.ttf", true);

이것이 가장 우아한 슈퍼 빠른 방법입니다.


2

이것은 내 프로젝트, 소스 https://gist.github.com/artem-zinnatullin/7749076에 대한 작업입니다.

Asset Folder 내에 fonts 디렉토리를 만든 다음 사용자 정의 글꼴을 fonts 디렉토리에 복사합니다 (예 : trebuchet.ttf를 사용하고 있습니다).

TypefaceUtil.java 클래스를 작성하십시오.

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

import java.lang.reflect.Field;
public class TypefaceUtil {

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

        }
    }
}

styles.xml에서 테마 편집 아래 추가

<item name="android:typeface">serif</item>

내 styles.xml의 예

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:typeface">serif</item><!-- Add here -->
    </style>


    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowFullscreen">true</item>
    </style>
</resources>

마지막으로, Activity 또는 Fragment에서 CreateCreate TypeTypeUtil.java를 호출하십시오.

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
    }

0

Android는 전체 앱에 글꼴을 적용 할 수있는 방법을 많이 제공하지 않습니다 (이 문제 참조 ). 전체 앱의 글꼴을 설정하는 4 가지 옵션이 있습니다.

  • 옵션 1 : 반사를 적용하여 시스템 글꼴 변경
  • 옵션 2 : 사용자 정의 글꼴이 필요한 각보기에 대한 사용자 정의보기 클래스 작성 및 서브 클래스
  • 옵션 3 : 현재 화면의 뷰 계층 구조를 가로 지르는 뷰 크롤러 구현
  • 옵션 4 : 타사 라이브러리를 사용하십시오.

이러한 옵션에 대한 자세한 내용은 여기를 참조하십시오 .


0

나는이 질문이 꽤 오래되었다는 것을 알고 있지만 좋은 해결책을 찾았습니다. 기본적으로 컨테이너 레이아웃을이 함수에 전달하면 지원되는 모든보기에 글꼴이 적용되고 자식 레이아웃에서 재귀 적으로 순환됩니다.

public static void setFont(ViewGroup layout)
{
    final int childcount = layout.getChildCount();
    for (int i = 0; i < childcount; i++)
    {
        // Get the view
        View v = layout.getChildAt(i);

        // Apply the font to a possible TextView
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Apply the font to a possible EditText
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Recursively cicle into a possible child layout
        try {
            ViewGroup vg = (ViewGroup) v;
            Utility.setFont(vg);
            continue;
        }
        catch (Exception e) { }
    }
}

0

에 응용 프로그램의 단지 세트 서체로 normal, sans, serif또는 monospace(가 아닌 사용자 정의 글꼴로!), 당신은이 작업을 수행 할 수 있습니다.

테마를 정의하고 android:typeface속성을 사용하려는 서체로 설정하십시오 styles.xml.

<resources>

    <!-- custom normal activity theme -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!-- other elements -->
        <item name="android:typeface">monospace</item>
    </style>

</resources>

AndroidManifest.xml파일 의 전체 앱에 테마를 적용 하십시오.

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application
        android:theme="@style/AppTheme" >
    </application>
</manifest>

안드로이드 참조


확실하게 작동합니까? Android 문서에 따르면 : "정상, sans, serif, monospace 상수 값 중 하나 여야합니다."
tomrozb

1
오, 알다시피 ... 당신이 맞아 ... 나는 결국 질문을 이해하지 못했다 : x 나는 단지 전체 응용 프로그램이 모노 스페이스 글꼴 (사용자 지정 아님)을 사용하도록하고 싶었고 작동하는 것을 보았 기 때문에 이것을 게시했다. 여기 ...... ... 나는 내 대답이 여전히 비슷한 것을하고 싶은 다른 사람들에게 유용 할 수 있다고 생각합니다 .... 그래서 그것을 편집하고 여기에 남겨 둘 것입니다 ..... 나는 괜찮습니다 투표를 축적합니다. 지적 해 주셔서 감사합니다
Eric

@Dave Cruise, 모노 스페이스에서만 작동합니까? 나는 단 하나의 공간에 대해서만 테스트했지만 ... 아무것도 .... 확실하지 않습니다 ...하지만 설명서에 따르면 "정상", "산"및 "분리"에서도 작동합니다. .i 서체가 글꼴보다 일반적이라고 생각하므로 앱의 글꼴을 "consolas"와 같은 특정 글꼴로 설정하는 데 사용할 수 없습니다.
Eric

@ 에릭 네. 나도 몰라 단일 공간은 매력처럼 작동하지만 일반, 산세 또는 세리프에게는 운이 없습니다.
Dave Cruise

0

가볍고 구현하기 쉬운이 라이브러리를 사용해보십시오.

https://github.com/sunnag7/FontStyler

<com.sunnag.fontstyler.FontStylerView
              android:textStyle="bold"
              android:text="@string/about_us"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingTop="8dp"
              app:fontName="Lato-Bold"
              android:textSize="18sp"
              android:id="@+id/textView64" />

-7

대답은 '아니요'입니다. 전체 응용 프로그램에 대해 사용자 정의 글꼴을 설정할 수 있습니까?를 참조하십시오 . 자세한 내용은.

이 해결 방법이 있지만의 라인에서 아무것도 "여기에 코드 내 모든 글꼴의 하나 개의 라인은 없을 것 아닌 것을 ."

(Google 및 Apple에게 감사드립니다). 사용자 정의 글꼴은 자리가 있지만 앱을 쉽게 대체 할 수있게하면 Comic Sans 응용 프로그램 의 전 세계를 만들 수 있습니다 )


41
당신의 논평에 완전히 동의하지 않습니다. 글꼴을 전역 적으로 설정하는 것은 필요한 해결 방법이 필요한 것이 아니라 사소한 일입니다. Google / Apple이 아닌 "Comic Sans"애플리케이션을 피하는 것은 전 세계 개발자 / 디자이너의 책임입니다.
LocalPCGuy

4
일관성> 팬시 디자인.
Martin Marconcini

14
그러나 일관성 <기능성. 우리는 성경 히브리어를 표시하는 앱을 개발합니다. 안드로이드 기기 (최신 안드로이드 L 폰트 포함)에서 발견되는 모든 스톡 폰트는 캔틸 레이션 마크를 렌더링하는 엄청난 작업을 수행합니다. 우리는 앱 전체에 커스텀 글꼴을 사용해야하며, 필요한 모든 뷰를 사용하려면 너무 많은 코드를 작성해야했습니다.
Ted Hopp
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.