Is it possible to use fancy fonts in Android?

2019-09-10 07:32发布

问题:

I know that the TextView has an attribute called fontFamily and I thought you can change the font of the text by changing the value of this attribute. So I wrote:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="my text"
    android:fontFamily="OCR A Std"
    android:textSize="20pt"/>

And then I run the app but the font of the text is still in the plain old Arial-like font. I think there must be a way to use fancy fonts in android, right?

If I just can't use fancy fonts, what font(s) do(es) android support? Only Arial is impossible, right?

回答1:

you should do it in this way

first create a folder named assets and create another folder within it named as fonts now paste some .ttf fonts file into it lets say you've file named as neutra_bold.ttf

now create a class that extends TextView for eg.

package com.view9.costumviews;

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

public class NeutraBoldTextView extends TextView {

    public NeutraBoldTextView(Context context) {
        super(context);
        Typeface face=Typeface.createFromAsset(context.getAssets(), "fonts/neutra_bold.ttf");
        this.setTypeface(face);
    }

    public NeutraBoldTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Typeface face=Typeface.createFromAsset(context.getAssets(), "fonts/neutra_bold.ttf");
        this.setTypeface(face);
    }

    public NeutraBoldTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        Typeface face=Typeface.createFromAsset(context.getAssets(), "fonts/neutra_bold.ttf");
        this.setTypeface(face);
    }

    protected void onDraw (Canvas canvas) {
        super.onDraw(canvas);


    }

}

now to use this view you can do this in xml layout like this

<com.view9.costumviews.NeutraBoldTextView

                android:id="@+id/tvViewAttachmentDescLabel"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:ellipsize="end"
                android:maxLines="1"
                android:text="@string/text_description"
                android:textColor="@color/heading_text_color"
                 />


回答2:

Android's TextView widget is that you couldn't specify a custom font in the XML layout. You just need to download the required font from the internet, and then place it in assets/fonts folder.

After putting fonts in the assets folder under fonts folder, you can access it in your java code through Typeface class. First , get the reference of the text view in the code. Its syntax is given below −

TextView tx = (TextView)findViewById(R.id.textview1);

The next thing you need to do is to call static method of Typeface class createFromAsset() to get your custom font from assets. Its syntax is given below −

Typeface custom_font = Typeface.createFromAsset(getAssets(), "fonts/font name.ttf");

The last thing you need to do is to set this custom font object to your TextView Typeface property. You need to call setTypeface() method to do that. Its syntax is given below −

tx.setTypeface(custom_font);

Reference .For more details Using-custom-fonts-in-your-android-apps And Custom Fonts on Android — Extending TextView



回答3:

You need to place your font file in assets folder. You need to add Typeface to your textview or any other view like below:

This method is suitable for one or few views but for multiple view it will be duplicating the code.

Typeface type = Typeface.createFromAsset(getAssets(),"Kokila.ttf"); 
 txtyour.setTypeface(type);

A better approach is to use your own font manager like this one:

public class QuickFontManager {

    private static int cacheSize=6;
    private static boolean debuggable=false;
    private static LruCache<String, Typeface> lruCache;


    private QuickFontManager(int cacheSize, boolean debuggable)
    {
        QuickFontManager.debuggable=debuggable;

        if(lruCache==null)
        {
            QuickFontManager.cacheSize=cacheSize;
            lruCache= new LruCache<String, Typeface>(cacheSize);

        }else
        {
            Log.e("QuickFonts","Cache already configured, use configuration before using typeface. Application class is a good contender.");
        }
    }

    public static void clearCache()
    {
        if(lruCache!=null)
        {
            lruCache.evictAll();
            lruCache=null;
        }
    }

    /**
     *
     * @param context
     * @param name
     * @return A pair containing required typeface and boolean value for whether it was fetched from cache.Boolean works only for debuggable mode.
     */
    public static Pair<Typeface, Boolean> getTypeface(Context context, String name) {

        if(lruCache==null)
        {
            lruCache= new LruCache<String, Typeface>(cacheSize);
        }

        Typeface typeface = lruCache.get(name);
        boolean fromCache=true;
        if (typeface == null) {
            try {
                typeface = Typeface.createFromAsset(context.getApplicationContext().getAssets(), name);
                fromCache=false;
            } catch (Exception e) {
                typeface=null;
            }

            if (typeface == null) {
                throw new NullPointerException("Resource named " + name + " not found in assets");
            } else
            {
                lruCache.put(name, typeface);
            }
        }
        if(!QuickFontManager.debuggable)
        {
            fromCache=true;  // User has not asked for debugging ,let's fool views
        }
        return Pair.create(typeface,fromCache);
    }




    public static class QuickFontBuilder
    {
        private int cacheSize;
        private boolean debuggable=false;
        public QuickFontBuilder()
        {

        }

        public QuickFontBuilder setCachesize(int cachesize)
        {
            this.cacheSize=cachesize;
            return this;
        }

        public QuickFontManager build()
        {
                return new QuickFontManager(this.cacheSize,this.debuggable);
        }

        public QuickFontBuilder setDebuggable(boolean debuggable) {
            this.debuggable = debuggable;
            return this;
        }
    }
}

Then create your custom textview or any other view (radio button,checkbox etc) like:

public class TextView extends android.widget.TextView {
    private String quickfont;
    public TextView(Context context) {
        super(context);
        init(null, 0);
    }

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

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

    private void init(AttributeSet attrs, int defStyle) {
        // Load attributes
        final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.TextView, defStyle, 0);
        try {
            quickfont = a.getString(R.styleable.TextView_quickfont);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            a.recycle();
        }
        if(quickfont!=null&!isInEditMode())
        {
            Pair<Typeface,Boolean> pair= QuickFontManager.getTypeface(getContext(), quickfont);
            Typeface typeface=pair.first;
            boolean fromCache=pair.second;

            if(typeface!=null)
            {
                setTypeface(typeface);
            }

            if(!fromCache)setTextColor(Color.RED);
        }

        // Note: This flag is required for proper typeface rendering
        setPaintFlags(getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);

    }

and in your values folder create a resource file attrs.xml(if not created) and add this:

<!--for custom views-->
<declare-styleable name="TextView">
    <attr name="quickfont" format="string" />
</declare-styleable>

all the hard work is done.Now you can simple use it in your xml for any view like

<com.abc.views.TextView
                app:quickfont="OpenSans-Regular_1.ttf"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@android:color/white"
                />

see that i assigned the font using app:quickfont.Where OpenSans-Regular_1.ttf is my font file in assets folder and com.abc.views.TextView is my custom textview.



回答4:

Download and Copy Font Files (.ttf,.ttc,.otf etc ) to Assets Folder

set Fonts is to do it programatically:

TextView tv= (TextView)findViewById(R.id.custom);
Typeface face=Typeface.createFromAsset(getAssets(), "fonts/heartbre.ttf");
tv.setTypeface(face);

or Else Create CustomText Class

public class CustomTextView extends TextView 
{
    Context context;
    String ttfName;
    String attrName ;
    String TAG = getClass().getName();
    public CustomTextView(Context context, AttributeSet attrs) 
    {
        super(context, attrs);
        this.context = context;
        for (int i = 0; i < attrs.getAttributeCount(); i++) 
        {
            try 
            {
                    attrName = attrs.getAttributeName(i);
                    if(attrName.equals("fontFamily"))
                    {
                        this.ttfName = attrs.getAttributeValue(i);
                        Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/"+this.ttfName);
                        setTypeface(font);
                    }
            } 
            catch (Exception e) 
            {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void setTypeface(Typeface tf) 
    {
        super.setTypeface(tf);
    }
}

you Can set Font Family through xml for Example

 <com.gm.custom_classes.CustomTextView
        android:id="@+id/updater_invalid_vin_content"
        android:layout_width="629dp"
        android:layout_height="266dp"
        android:layout_marginLeft="86dp"
        android:layout_marginTop="91dp"
        android:fontFamily="GMSansUI_Light.ttf"
        android:gravity="left"
        android:maxLines="7"
        android:singleLine="false"
        android:text="@string/updater_invalid_vin_content"
        android:textColor="#ffffff"
        android:textSize="28sp" />


回答5:

I did all of these things mentioned in the answers, but honestly the easiest and most convenient method for applying fonts was to use this library.

Calligraphy by Christopher Jenkins

Blog post summarising his architecture

The setup is very easy and supports all cases.

I would suggest you use this because there is no point re-inventing the wheel and the library is constantly being improved, so you can depend on it for all your other projects also!

Hope it helps! :)