Is het mogelijk om een ​​aangepast lettertype in te stellen voor de hele applicatie?

Ik moet een bepaald lettertype gebruiken voor mijn hele toepassing. Ik heb een .ttf-bestand voor hetzelfde.
Is het mogelijk om dit als standaardlettertype in te stellen bij het opstarten van de applicatie en het dan ergens anders in de applicatie te gebruiken? Wanneer ingesteld, hoe gebruik ik het dan in mijn lay-out-XML’s?


Antwoord 1, autoriteit 100%

Ja met reflectie. Dit werkt (op basis van dit antwoord):

(Opmerking: dit is een tijdelijke oplossing vanwege het ontbreken van ondersteuning voor aangepaste lettertypen, dus als u deze situatie wilt wijzigen, moet u een ster geven om de Android-probleem hier). Opmerking:laat geen “ik ook” opmerkingen over dat onderwerp achter, iedereen die ernaar heeft gekeken krijgt een e-mail als je dat doet. Dus geef het alsjeblieft een ster.

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

Je moet dan de paar standaardlettertypen overbelasten, bijvoorbeeld in een applicatieklasse:

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

Of natuurlijk, als u hetzelfde lettertypebestand gebruikt, kunt u dit verbeteren door het slechts één keer te laden.

Ik heb echter de neiging om er gewoon een te negeren, zeg "MONOSPACE", en stel dan een stijl in om die lettertypetoepassing breed te forceren:

<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

Ik heb de rapporten in de opmerkingen onderzocht dat het niet werkt en dat het niet compatibel lijkt te zijn met het thema android:Theme.Material.Light.

Als dat thema niet belangrijk voor je is, gebruik dan een ouder thema, bijvoorbeeld:

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

Antwoord 2, autoriteit 14%

Er is een geweldige bibliotheek voor aangepaste lettertypen in Android:Kalligrafie

hier is een voorbeeld van hoe je het kunt gebruiken.

in Gradle moet je deze regel in het build.gradle-bestand van je app plaatsen:

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

en maak dan een klasse die Applicationuitbreidt en schrijf deze code:

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

en plaats deze methode in de activiteitsklasse vóór onCreate:

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

en het laatste wat uw manifestbestand er zo uit zou moeten zien:

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

en het verandert de hele activiteit in je lettertype! het is eenvoudig en schoon!


Antwoord 3, autoriteit 10%

Hoewel dit niet zou werken voor een hele applicatie, zou het wel werken voor een activiteit en zou het opnieuw kunnen worden gebruikt voor elke andere activiteit. Ik heb mijn code bijgewerkt dankzij @FR073N om andere weergaven te ondersteunen. Ik ben niet zeker van problemen met Buttons, RadioGroups, enz. omdat deze klassen allemaal TextViewuitbreiden, dus ze zouden prima moeten werken. Ik heb een booleaanse voorwaarde toegevoegd voor het gebruik van reflectie omdat het erg hackachtig lijkt en de prestaties aanzienlijk zou kunnen compromitteren.

Opmerking: zoals aangegeven, werkt dit niet voor dynamische inhoud! Daarvoor is het mogelijk om deze methode aan te roepen met bijvoorbeeld een onCreateViewof getViewmethode, maar vereist extra inspanning.

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

Om het vervolgens te gebruiken, zou je zoiets als dit doen:

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

Hopelijk helpt dat.


Antwoord 4, autoriteit 7%

Samengevat:

Optie#1:gebruik reflectie om lettertype toe te passen (combinatie van westonen Het antwoord van Roger 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();
            } 
        }
    }
} 

Gebruik in applicatieklasse:

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

stel een stijl in om die lettertypetoepassing breed te forceren (gebaseerd op lovefish):

Pre-lolly:

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

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

Optie2:subklasse elke weergave waar u het lettertype moet aanpassen, bijv. ListView, EditTextView, Button, etc. (Palani‘s antwoord):

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

Optie 3:Implementeer een weergavecrawler die de weergavehiërarchie van uw huidige scherm doorloopt:

Variatie#1 (Tom‘s antwoord):

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

Gebruik:

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

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

Optie #4:Gebruik een lib van derden genaamd Kalligrafie.

Persoonlijk zou ik optie #4 aanraden, omdat het veel kopzorgen bespaart.


Antwoord 5, autoriteit 6%

Ik wil het antwoord van westonvoor API 21 Android 5.0 verbeteren.

Oorzaak

Onder API 21 bevatten de meeste tekststijlen een fontFamily-instelling, zoals:

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

Wat het standaard Roboto Regular-lettertype toepast:

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

Het oorspronkelijke antwoord past geen monospace-lettertype toe, omdat android:fontFamily een grotere prioriteit heeft voor het android:typeface-kenmerk (referentie).
Het gebruik van Theme.Holo.* is een geldige oplossing, omdat er geen android:fontFamily-instellingen in zitten.

Oplossing

Sinds Android 5.0 het systeemlettertype in de statische variabele Typeface.sSystemFontMap heeft gezet (referentie), we kan dezelfde reflectietechniek gebruiken om het te vervangen:

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

Antwoord 6, autoriteit 3%

het is heel eenvoudig…
1.Download en plaats uw aangepaste lettertype in activa..schrijf vervolgens een aparte klasse voor tekstweergave als volgt: hier heb ik futura-lettertype gebruikt

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

}

en doe het volgende in 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"
      />

Antwoord 7, autoriteit 2%

Ik zou ook willen voorstellen om TextView en andere besturingselementen uit te breiden, maar het zou beter zijn als ik zou overwegen om lettertype in constructies in te stellen.

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

Antwoord 8, autoriteit 2%

Ik wil graag de weston‘s en Roger Huang‘s antwoorden voor meer dan API 21 Android-lolly met thema “Theme.AppCompat“.

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

Over (gelijke) 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>

En het FontsOverrideutil-bestand is hetzelfde als in het antwoord van weston.
Ik heb getest in deze telefoons:

Nexus 5 (Android 5.1 Primair Android-systeem)

ZTE V5(android 5.1 CM12.1)

XIAOMI-notitie (android 4.4 MIUI6)

HUAWEI C8850 (android 2.3.5 ONBEKEND)


Antwoord 9, autoriteit 2%

Een briljante oplossing is hier te vinden: https:/ /coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere.

Verleng eenvoudig activiteiten van BaseActivity en schrijf die methoden. U kunt lettertypen ook beter cachen zoals hier beschreven: https://stackoverflow.com/a/16902532/2914140.


Na wat onderzoek heb ik code geschreven die werkt op Samsung Galaxy Tab A (Android 5.0). Gebruikte code van weston en Roger Huang evenals https://stackoverflow.com/a/33236102/2914140. Ook getest op Lenovo TAB 2 A10-70L, waar het niet werkt.
Ik heb hier een lettertype ‘Comic Sans’ ingevoegd om een ​​verschil te zien.

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

Om de code in de hele applicatie uit te voeren, moet je in een klasse zoals Application het volgende schrijven:

   new FontsOverride(this).loadFonts();

Maak een map ‘fonts’ in ‘assets’ en plaats de benodigde lettertypen daar. Een eenvoudige instructie is hier te vinden: https://stackoverflow.com/a/31697103/2914140.

Het Lenovo-apparaat krijgt ook ten onrechte de waarde van een lettertype. Meestal wordt Typeface.NORMAL geretourneerd, soms null. Zelfs als een TextView vetgedrukt is (in xml-bestandslay-out). Zie hier: TextView isBold geeft altijd NORMAAL terug. Zo is een tekst op een scherm altijd in een regulier lettertype, niet vet of cursief. Dus ik denk dat het een bug van een producer is.


Antwoord 10

Werken voor Xamarin.Android:

Klasse:

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

Applicatie-implementatie:

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

Stijl:

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

Antwoord 11

Vanaf Android O is dit nu mogelijk om rechtstreeks vanuit de XML en mijn bug is nu gesloten!

Zie hier voor details

TL;DR:

Eerst moet u uw lettertypen aan het project toevoegen

Ten tweede voeg je een lettertypefamilie toe, zoals:

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

Ten slotte kunt u het lettertype in een lay-out of stijl gebruiken:

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

Veel plezier!


Antwoord 12

U kunt aangepaste lettertypen voor elke lay-out één voor één instellen, met slechts één functieaanroep van elke lay-out door de root View door te geven. Maak eerst een singleton-aanpak voor toegang tot het lettertype-object zoals dit

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

U kunt verschillende lettertypen definiëren in de bovenstaande klasse. Definieer nu een lettertype-helperklasse die lettertypen zal toepassen:

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

In de bovenstaande code pas ik alleen lettertypen toe op textView en EditText, je kunt lettertypen ook op andere weergave-elementen toepassen. Je hoeft alleen de id van je root View-groep door te geven aan de bovenstaande methode voor het toepassen van lettertypen. uw lay-out is bijvoorbeeld:

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

In de bovenstaande lay-out is de root-ouder-ID “Hoofdouder” laten we nu lettertype toepassen

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

Proost 🙂


Antwoord 13

Ik raad aan om TextView uit te breiden en altijd je eigen TextView te gebruiken in je XML-lay-outs of waar je ook maar een TextView nodig hebt. Overschrijf in uw aangepaste 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);
}

Antwoord 14

Toms oplossing werkt prima, maar werkt alleen met TextView en EditText.

Als je de meeste weergaven wilt dekken (RadioGroup, TextView, Checkbox…), heb ik een methode gemaakt om dat te doen:

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

Deze methode haalt de stijl van de weergaveset in XML terug (vet, cursief…) en past deze toe als ze bestaan.

Voor de ListView maak ik altijd een adapter en stel ik het lettertype in getView in.


Antwoord 15

Ik heb een klasse geschreven waarin ik een lettertype toewijs aan de weergaven in de huidige weergavehiërarchie en gebaseerd op de huidige lettertype-eigenschappen (vet, normaal, je kunt andere stijlen toevoegen als je wilt):

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

Nu in alle fragmenten in onViewCreated of onCreateView, in alle activiteiten in onCreate en in alle view-adapters in getView of newView, roep je gewoon aan:

typefaceAssigner.assignTypeface(view);

Antwoord 16

in api 26 met build.gradle 3.0.0 en hoger kun je een lettertypemap maken in res
en gebruik deze lijn in jouw stijl

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

gebruik voor wijziging build.gradle dit in uw build.gradle-afhankelijkheden

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

Antwoord 17

Eindelijk besefte Google de ernst van dit probleem (het toepassen van een aangepast lettertype op UI-componenten) en bedachten ze er een schone oplossing voor.

Eerst moet je updaten om bibliotheek 26+ te ondersteunen (mogelijk moet je ook je gradle{4.0+}, android studio updaten), dan kun je een nieuwe bronmap maken met de naam font. In deze map kunt u uw fontbronnen (.tff,…) plaatsen.
Dan moet je de standaard app overschrijven en je aangepaste lettertype erin forceren 🙂

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

Opmerking: als u apparaten met een oudere API dan 16 wilt ondersteunen, moet u de app-naamruimte gebruiken in plaats van Android!


Antwoord 18

Ik zou ook graag het antwoord van weston voor API 21 Android 5.0 willen verbeteren.

Ik had hetzelfde probleem op mijn Samsung s5 bij het gebruik van het DEFAULT-lettertype. (met de andere lettertypen werkt het prima)

Het lukte me om het te laten werken door het lettertype(‘sans’ bijvoorbeeld) in XML-bestanden in te stellen voor elke tekstweergave of knop

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

en in MyApplication Class :

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

Hopelijk helpt het.


Antwoord 19

Deze-oplossing werkt in sommige situaties niet correct.
Dus ik verleng het:

FontsReplacer.java

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        FontsReplacer.replaceFonts(this);
        super.onCreate();
    }
}

https://gist.github.com/orwir/6df839e3527647adc2d56bfadfaad805


Antwoord 20

Kalligrafiewerkt redelijk goed, maar het is niet geschikt voor mij, omdat het geen verschillende gewichten ondersteunt (vet, cursief, enz.) voor een lettertypefamilie.

Dus ik heb Fontaingeprobeerd, waarmee je aangepaste weergaven kunt definiëren en aangepaste lettertypefamilies kunt toepassen.

om Fontain te kunnen gebruiken, moet u het volgende toevoegen aan uw app-module build.gradle:

compile 'com.scopely:fontain:1.0.0'

Vervolgens, in plaats van de gewone TextView te gebruiken, zou u FontTextView moeten gebruiken

Voorbeeld van FontTextView met hoofdletters en vetgedrukte inhoud:

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

Antwoord 21

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

Antwoord 22

Als u de standaardlettertypefamilie van TextViews wilt wijzigen, overschrijft u textViewStyle in uw app-thema.

Als u een aangepast lettertype in fontFamily wilt gebruiken, gebruikt u bronnen voor lettertypen die zich in de ondersteuningsbibliotheek bevinden.

De functie is toegevoegd in Android 26 maar terug naar oudere versies gebackporteerd via 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


Antwoord 23

Sinds de release van Android Oreo en zijn ondersteuningsbibliotheek (26.0.0) kun je dit gemakkelijk doen. Raadpleeg dit antwoordin een andere vraag.

In principe ziet je uiteindelijke stijl er als volgt uit:

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

Antwoord 24

Ik vond de combinatie van kalligrafie 3-bibliotheeken coderwall’s postals mijn uiteindelijke resultaat.


Antwoord 25

Ja, het is mogelijk om het lettertype voor de hele applicatie in te stellen.

De eenvoudigste manier om dit te bereiken, is door de gewenste lettertypen in uw toepassing te verpakken.

Om dit te doen, maakt u eenvoudig een map assets/in de hoofdmap van het project en plaatst u uw lettertypen (in
TrueType- of TTF-formulier) in de activa.

U kunt bijvoorbeeld assets/fonts/maken en uw TTF-bestanden daarin plaatsen.

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

Other episodes