Tüm uygulama için özel bir yazı tipi ayarlamak mümkün müdür?


270

Tüm uygulamam için belirli bir yazı tipi kullanmam gerekiyor. Aynı .ttf dosyam var. Bunu varsayılan yazı tipi olarak ayarlamak, uygulama başlangıcında ve sonra uygulamanın başka bir yerinde kullanmak mümkün müdür? Ayarlandığında, düzen XML'lerimde nasıl kullanabilirim?


android studio 3.0'da kolayca özel yazı tipleri ayarlayabilirsiniz: developer.android.com/guide/topics/ui/look-and-feel/…
MHSFisher

XML'deki @MHSFisher Yazı Tipleri Android 8.0 (API seviye 26) için bir özelliktir
Emi Raz

1
@EmiRaz lütfen doc developer.android.com/guide/topics/ui/look-and-feel/… adresini okuyun . bu özellik destek kitaplığına 26 eklendi, ancak API 16'dan desteklendi.
MHSFisher

Yanıtlar:


449

Evet yansıması ile. Bu işe yarar ( bu cevaba dayanarak ):

(Not: Bu, özel yazı tipleri için destek eksikliğinden dolayı bir çözümdür, bu nedenle bu durumu değiştirmek istiyorsanız lütfen burada android sorununu yükseltmek için yıldız yapın ). Not: Bu konuda "ben de" yorum bırakmayın, ona bakan herkes bunu yaptığınızda bir e-posta alır. Yani sadece "yıldız" lütfen.

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

Ardından, örneğin bir uygulama sınıfında birkaç varsayılan yazı tipini aşırı yüklemeniz gerekir :

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

Veya aynı yazı tipi dosyasını kullanıyorsanız, sadece bir kez yüklemek için bunu geliştirebilirsiniz.

Ancak, sadece bir geçersiz kılma eğilimi "MONOSPACE", sonra o yazı tipi yazı tipi uygulaması geniş zorlamak için bir stil kurmak eğilimindedir :

<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

Yorumlarda yer almayan raporları araştırdım ve işe yaramadı gibi görünüyor android:Theme.Material.Light.

Bu tema sizin için önemli değilse, daha eski bir tema kullanın, örneğin:

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

11
tek aralıklı kalın veya italik olarak nasıl geçersiz kılabilirsiniz?
Christopher Rivera

2
@ChristopherRivera "DEFAULT_BOLD"Özel bir alan da var: Yazınıza private static Typeface[] sDefaults;yansıtarak ve ayarlayarak sDefaults[Typeface.ITALIC]buna erişmeyi deneyebilirsiniz. Şuna bakın .
weston

5
@weston Boş ver. Ben başardım. Anlayışımda bir hata oluştu. Harika bir iş çıkardın. Bana sadece bir şey söyleyebilir misin? VARSAYILAN Yazı Tipi için neden çalışmıyor? Öneri olarak Yazı Tipi'ni MONOSPACE olarak değiştirdim ve sonra loginc'yi uyguladım, işe yaradı. Ancak VARSAYILAN için çalışmıyor
Jay Pandya

2
Yerel yazı tipi hata yapılamaz. Yazı tipi yolu ekleyerek düzeltildi. "FontsOverride.setDefaultFont (bu," VARSAYILAN "," yazı tipleri / MyFontAsset.ttf ");"
Sai

3
TextViewÖzel yazı tiplerini kullanmak veya böyle bir yansıma tabanlı bir çözüm kullanmak için varsayılanı her yerde takas etmek gerçekten can sıkıcı buluyorum . Android'de bulunan sınırlı yazı tipi seti ile birlikte, iyi görünümlü uygulamalar geliştirmeyi çok zorlaştırır. Android sorun izleyicisine bir özellik isteği ekledim. Bu özelliği görmek istiyorsanız, sorunu burada yıldızlandırabilirsiniz: code.google.com/p/android/issues/…
Sam

64

Android'de özel yazı tipleri için harika bir kütüphane var: Kaligrafi

İşte nasıl kullanılacağı ile ilgili bir örnek.

Gradle'da bu satırı uygulamanızın build.gradle dosyasına koymanız gerekir:

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

ve Applicationbu kodu genişleten bir sınıf yapın ve şu kodu yazın:

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

ve etkinlik sınıfında bu yöntemi onCreate'den önce koyun:

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

ve manifest dosyanızın son olarak şu şekilde görünmesi gerekir:

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

ve tüm etkinliği yazı tipinize dönüştürecektir! basit ve temiz!


1
Bu mükemmel bir çözüm.
nizam.sp

1
Doğru, çok mükemmel bir çözüm, bu şekilde menü öğeleri, radyo düğmesi veya onay kutusu fotns için yazı tiplerini güncellemek için farklı sınıflar yazmak zorunda değilim. Herkes için geçerlidir !! teşekkürler :)
Manisha

2
Kesinlikle mükemmel bir çözüm değil: Kalın / italik / kalın-italik stillerin üzerine yazılır. Şu anda bu aileleri kurmanın kolay bir yolu yok.
0101100101

2
Bunu yaparsam Kalından Düzenli'ye nasıl geçebilirim?
GMX

2
Kalın, italik veya altı çizili özelliği edinebilmek için ben kullandım <b></b>, <u></u>ve <i></i>de strings.xmldosyaya ve şimdiye kadar çalışır.
Temmuz

47

Bu, tüm bir uygulama için işe yaramayacak olsa da, bir Etkinlik için işe yarayacak ve diğer herhangi bir Etkinlik için tekrar kullanılabilecektir. Diğer Görünümleri desteklemek için @ FR073N sayesinde kodumu güncelledim. Ben ile ilgili sorunlar hakkında emin değilim Buttons, RadioGroupsbu sınıflar tüm uzanması nedeniyle vb TextViewonlar sadece iyi çalışması gerekir böylece. Yansıma kullanmak için bir boole koşulu ekledim, çünkü çok acayip görünüyor ve özellikle performansı tehlikeye atabilir.

Not: belirtildiği gibi, bu dinamik içerik için çalışmaz! Bunun için, bu yöntemi bir onCreateViewveya getViewyöntemi kullanarak çağırmak mümkündür , ancak ek çaba gerektirir.

/**
 * 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... */ }
        }
    }
}

Sonra kullanmak için böyle bir şey yapardınız:

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

Umarım yardımcı olur.


4
Bence en iyi yol textview'i geçersiz kılmak. Çok sayıda görünüme sahip bir uygulamanız varsa bu yöntem biraz gereksiz olabilir.
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

1
Olabilir ... ama Android özelliklerine göre 4 seviyeden daha derin ve 100 görünümden daha geniş düzenlerden kaçınmak istersiniz (bu biraz da olsa). Özyineleme performans açısından kötü olabilir, ancak düzeniniz 20 düzey olsa bile bu önemli değildir.
Tom

Performans üzerinde gözle görülür bir etkisi olmadığını kabul ediyorum ve cevabınızın yanlış olduğunu söylemeye çalışmıyorum. Gerekmiyorsa, mizanpajdaki her görünümde bisiklet sürmeyi sevmiyorum. Ayrıca, TextView öğesini genişleterek, görünümü başka bir şekilde değiştirmek isterseniz, kodu yalnızca bir noktada değiştirmeniz gerekir.
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

1
Sadece yukarıdaki kod sadece TextViews kapsar eklemek istedim ama ListViews, Uyarılar, Tost, Harita Markers vb hala sistem yazı tipi kullanacaktır.
csch

2
çocuklar bu işlevi 3 parametre alır, özyinelemeli çağırdığınızda 2 parametre geçti ??? hangisi doğru? yansıtmak nedir ??
MBH

34

Özetle:

Seçenek # 1: Yazı tipini uygulamak için yansımayı kullanın ( weston ve Roger Huang'ın cevabını birleştirerek ):

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

} 

Uygulama sınıfında kullanım:

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

bu yazı tipi yazı tipi uygulamasını ( lovefish'i temel alarak) genişletmek için bir stil oluşturun :

Ön Lollipop:

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

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

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

Seçenek2: Yazı tipini özelleştirmeniz gereken her Görünümü alt sınıfta , yani. ListView, EditTextView, Düğme, vb ( Palani 'ın cevabı):

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. Seçenek: Geçerli ekranınızın görünüm hiyerarşisinde dolaşan bir Görünüm Tarayıcısı uygulayın:

Varyasyon # 1 ( Tom'un cevabı):

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... */ }
        } 
    } 
} 

Kullanımı:

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

Varyasyon # 2: https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere .

Seçenek # 4: Kaligrafi adı verilen 3. Taraf Lib'i kullanın .

Şahsen, birçok baş ağrısından kurtardığı için Seçenek # 4'ü tavsiye ederim.


Gelen Seçenek 1. , sen ne demek istiyorsunuz "sans-serif"içinde newMap.put(ve monospacede styles?! Adlı özel bir yazı tipi kullanmak istiyorum barana.ttf.
Dr.jacky

1. seçenekte, ilk kod snippet'i API düzeyi 22, Android 5.1.1 ile çalışmaz. Ancak diğer kod bölümü bunu yapar. Durum böyle ise tam olarak ne olmalıdır?
user1510006

28

Weston'ın API 21 Android 5.0 için yanıtını iyileştirmek istiyorum .

Sebep olmak

API 21 altında, metin stillerinin çoğu fontFamily ayarını içerir, örneğin:

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

Hangi varsayılan Roboto Düzenli yazı tipini uygular:

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

Orijinal yanıt tek aralıklı yazı tipini uygulayamaz, çünkü android: fontFamily'ın android: yazı biçimi özniteliği ( başvuru ) için daha büyük önceliği vardır . Theme.Holo. * Kullanmak geçerli bir çözümdür, çünkü içinde android: fontFamily ayarları yoktur.

Çözüm

Android 5.0, sistem yazı tipini Typeface.sSystemFontMap ( başvuru ) statik değişkenine koyduğundan , değiştirmek için aynı yansıma tekniğini kullanabiliriz:

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. için güzel bir çözüm ancak bunun neden benim Buttons ve Araç Çubuğu başlıkları için işe yaramadığını merak ediyorum . Şöyle ben MainApplication varsayılan yazı tipini geçersiz ediyorum: FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");. Nexus 5 kullanıyorum v5.1.1
kip2

3
Hey, teşekkür ederim Bu çok yardımcı oldu, sadece bir şey: bu Android 6'da çalışmıyor (API 22). Daha sonra kod şu şekilde değiştirilmelidir: Build.VERSION.SDK_INT == 21- Bu sadece API 21 API 22 ile Nexus I testinde
Saeid

Yine de Nexus 9
Rahul Upadhyay'da

2
5.1+ için çalışmama sorunu olan herhangi biri. Değerler-v21 stillerinizdeki yazı tipini geçersiz kılmayın.
Muhammad Babar

Teşekkür @MuhammadBabar Çözümünüz yapılmış benim gün
M.Yogeshwaran

15

çok basit ... 1.İndirip varlıkları ur özel yazı koymak ... sonra aşağıdaki gibi metin görünümü için ayrı bir sınıf yazmak: burada futura yazı tipi kullanılır

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

}

ve xml ile aşağıdakileri yapın:

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

Evet, işe yarıyor :) Ama, diğer fontlar / widget'lar için aynı yazı tiplerini uygulamak istersem ne olur? Diğer tüm görünümler için de (iletişim kutuları / tostlar / eylem çubukları dahil) ayrı bir sınıf yazmam gerekir mi?
Narendra Singh

Evet, bu çözüm için her bir görüşünüz için ayrı sınıflar yazmanız gerekir.
Saad Bilal

9

Ayrıca TextView ve diğer kontrolleri genişletmeyi öneririm, ancak yapılarda yazı tipi kurmayı düşünürsek daha iyi olur.

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'dan önceki platformlarda bunu yaparken dikkatli olun - bu, Android'deki bir hata nedeniyle çok fazla kaynak sızdırır: code.google.com/p/android/issues/detail?id=9904
Ryan M

nasıl varsayılana geri dönebiliriz. Ben böyle bir şey yapıyorum: if (configShared.getString ("storeId", AppCredentials.DEFAULT_STORE_ID) .equals ("2")) {final Field staticField = Typeface.class.getDeclaredField (staticTypefaceFieldName); staticField.setAccessible (doğru); staticField.set (null, newTypeface); } else {final Field staticField = Typeface.class.getDeclaredField (staticTypefaceFieldName); staticField.setAccessible (doğru); staticField.set (null, null); }
Katil

8

Weston ve Roger Huang'ın " Theme.AppCompat " temalı API 21'den fazla Android lolipopuna verdiği cevapları geliştirmek istiyorum .

Android 4.4'ün altında

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

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

Aşırı (eşit) 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>

Ve FontsOverride dosyasında util ne aynıdır weston 'ın cevabı. Bu telefonlarda test ettim:

Nexus 5 (android 5.1 Birincil Android Sistemi)

ZTE V5 (android 5.1 CM12.1)

XIAOMI notu (android 4.4 MIUI6)

HUAWEI C8850 (android 2.3.5 BİLİNMİYOR)


8

Mükemmel bir çözüm burada bulunabilir: https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere .

Yalnızca BaseActivity'den etkinlikleri genişletin ve bu yöntemleri yazın. Ayrıca yazı tiplerini burada açıklandığı şekilde daha iyi önbelleğe almalısınız: https://stackoverflow.com/a/16902532/2914140 .


Bazı araştırmalardan sonra Samsung Galaxy Tab A'da (Android 5.0) çalışan bir kod yazdım. Weston ve Roger Huang'ın yanı sıra https://stackoverflow.com/a/33236102/2914140 kodu kullanıldı . Ayrıca çalışmadığı Lenovo TAB 2 A10-70L üzerinde de test edildi. Buraya bir fark görmek için bir 'Comic Sans' yazı tipi ekledim.

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

Kodu tüm uygulamada çalıştırmak için Uygulama gibi bir sınıfta aşağıdakileri yazmalısınız:

    new FontsOverride(this).loadFonts();

Varlıklar içinde bir 'fontlar' klasörü oluşturun ve gerekli fontları oraya koyun. Basit bir talimat burada bulunabilir: https://stackoverflow.com/a/31697103/2914140 .

Lenovo cihazı da yanlış bir yazı tipi değeri alıyor. Çoğu zaman Typeface.NORMAL döndürür, bazen null. Bir TextView kalın olsa bile (xml dosya düzeninde). Buraya bakın: TextView isBold her zaman NORMAL değerini döndürür . Bu şekilde ekrandaki bir metin, kalın veya italik değil, her zaman yasal bir yazı tipindedir. Bence bu bir yapımcının hatası.


Android kaynak kodu okudum, cevabınız en iyi en iyisi. İnce, orta, hafif veya başka bir şeyin yerini alabilir. Çok teşekkür ederim!
Mohammad Omidvar

6

Xamarin.Android için çalışmak:

Sınıf:

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

Uygulama Uygulaması:

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

Stil:

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

6

Android O'dan itibaren bu artık doğrudan XML'den tanımlamak mümkün ve hatam şimdi kapalı!

Ayrıntılar için buraya bakın

TL; DR:

İlk önce yazı tiplerini projeye eklemelisiniz

İkinci olarak, bir font ailesi eklersiniz, şöyle:

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

Son olarak, yazı tipini bir mizanpajda veya stilde kullanabilirsiniz:

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

Zevk almak!


Teşekkürler. Yazı tipi klasörü eklemek için Android Studio 2.4'ü kullanmalıyız.
Foton Noktası

aslında sadece benim tarzı uygulamak gerekir ve uygulama yoluyla uygulanacaktır. ancak bazı (programlı olarak eklenen denetimlerin java kodu aracılığıyla uygulanması gerekir)
SolidSnake

4

Kök Görünümü'nü ileterek her mizanpajdan yalnızca bir işlev çağrısı ile her mizanpaj için özel yazı tiplerini tek tek ayarlayabilirsiniz.

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

}

Yukarıdaki sınıfta farklı fontlar tanımlayabilirsiniz: Şimdi fontları uygulayacak bir font Helper sınıfı tanımlayın:

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

        }

    }

}

Yukarıdaki kodda, yalnızca textView ve EditText üzerine yazı tipleri uyguluyorum, yazı tiplerini diğer görünüm öğelerine de benzer şekilde uygulayabilirsiniz. örneğin düzeniniz:

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

Yukarıdaki Mizanpaj'da kök ana kimliği "Ana Üst" dir, şimdi yazı tipi uygulayalım

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

Şerefe :)


Güzel .. artık aynı yazı tipi yeniden oluşturmak, tüm alan için sadece 1 yazı tipi kullanın. :)
Arfan Mirza

3

TextView'i genişletmenizi ve XML düzenlerinizde veya bir TextView'a ihtiyacınız olduğunda her zaman özel TextView'inizi kullanmanızı öneririm. Özel TextView öğenizde geçersiz kılınsetTypeface

@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

Tom'un çözümü harika çalışıyor, ancak yalnızca TextView ve EditText ile çalışıyor.

Görünümlerin çoğunu (RadioGroup, TextView, Checkbox ...) kapsamak istiyorsanız, bunu yapan bir yöntem oluşturdum:

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

Bu yöntem, XML'de (bold, italic ...) ayarlanan görünümün stilini geri alır ve varsa uygular.

ListView için, her zaman bir bağdaştırıcı oluştururum ve yazı tipini getView içinde ayarlarım.


2

Geçerli görünüm hiyerarşisi görünümlerine yazı tipi atama bir sınıf yazdım ve os geçerli yazı karakteri özellikleri (kalın, normal, isterseniz diğer stilleri ekleyebilirsiniz) dayalı:

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

Şimdi onViewCreated veya onCreateView'daki tüm parçalarda, onCreate'deki tüm etkinliklerde ve getView veya newView'daki tüm görünüm bağdaştırıcılarında şunları çağırır:

typefaceAssigner.assignTypeface(view);

2

26. build.gradle 3.0.0 ve daha yüksek bir sürümle Api'de res'de bir yazı tipi dizini oluşturabilir ve bu satırı stilinizde kullanabilirsiniz

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

build.gradle değiştirmek için bunu build.gradle bağımlılıklarınızda kullanın

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

ve yazı tipini projeye nasıl ekleyebilirim?
azerafati

@azerafati yazı tipinizi res / font'a kopyalayın
Mohammad Hosein Heidari

evet, tanx. Bunu zaten aldım. Ancak bu itemtek başına tüm uygulama için yazı tipini ayarlamaz. bir ipucu?
azerafati

1

Son olarak, Google bu sorunun önemini fark etti (kullanıcı arayüzü bileşenlerine özel yazı tipi uygulayarak) ve bunun için temiz bir çözüm tasarladı.

İlk olarak, 26+ kütüphanesini desteklemek için güncellemeniz gerekir (ayrıca {4.0+}, android studio derecenizi de güncellemeniz gerekebilir), ardından font adlı yeni bir kaynak klasörü oluşturabilirsiniz. Bu klasöre yazı tipi kaynaklarınızı (.tff, ...) koyabilirsiniz. Sonra varsayılan uygulamayı geçersiz kılmanız ve özel yazı tipinizi buna zorlamanız gerekir :)

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

Not: 16'dan eski API'lı cihazları desteklemek istiyorsanız, android yerine uygulama ad alanını kullanmanız gerekir!


0

Ayrıca weston'un API 21 Android 5.0 için cevabını geliştirmek istiyorum.

DEFAULT yazı tipini kullanırken Samsung s5 cihazımda da aynı sorunu yaşadım. (diğer yazı tipleri ile iyi çalışıyor)

Her Textview veya Button için XML dosyalarında yazı tipini (örneğin "sans") ayarlayarak çalışmayı başardım

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

ve MyApplication Sınıfında:

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

Umarım yardımcı olur.



0

Hat oldukça iyi çalışıyor, ancak yazı tipi ailesi için farklı ağırlıkları (kalın, italik, vb.) Desteklemediğinden benim için uygun değil.

Bu yüzden özel Görünümler tanımlamanıza ve onlara özel yazı tipi ailelerini uygulamanıza izin veren Fontain'i denedim .

Fontain'i kullanmak için uygulama modülü build.gradle'a aşağıdakileri eklemeniz gerekir:

compile 'com.scopely:fontain:1.0.0'

Ardından, normal TextView kullanmak yerine FontTextView kullanmalısınız

Büyük ve kalın içerikli FontTextView örneği:

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

    }

}

Mükemmel bir çözüm değil. Erişim Varsayılan Android için özel geçici çözümler gerektirir Bu çözümü kullanarak TextViewler
blueware

0

TextViews'in varsayılan yazı tipi ailesini değiştirmek için uygulama temanızdaki textViewStyle'ı geçersiz kılın.

FontFamily içinde özel yazı tipi kullanmak için, destek kitaplığında bulunan yazı tipi kaynaklarını kullanın.

Bu özellik Android 26'da eklendi, ancak supportlib aracılığıyla eski sürümlere desteklendi.

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


0

Android Oreo ve destek kütüphanesinin (26.0.0) piyasaya sürülmesinden bu yana bunu kolayca yapabilirsiniz. Başka bir soruda bu cevaba bakınız .

Temel olarak son tarzınız şöyle görünecek:

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


-15

Evet, yazı tipini uygulamanın tamamına ayarlamak mümkündür.

Bunu yapmanın en kolay yolu, istediğiniz yazı tiplerini uygulamanızla birlikte paketlemektir.

Bunu yapmak için , proje kökünde bir varlık / klasör oluşturun ve yazı tiplerinizi (TrueType veya TTF, formda) varlıklara koyun.

Örneğin, varlıklar / yazı tipleri / oluşturabilir ve TTF dosyalarınızı buraya koyabilirsiniz.

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);
}
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.