开发者

Android - Using Custom Font

开发者_StackOverflow社区I applied a custom font to a TextView, but it doesn't seems to change the typeface.

Here is my code:

    Typeface myTypeface = Typeface.createFromAsset(getAssets(), "fonts/myFont.ttf");
    TextView myTextView = (TextView)findViewById(R.id.myTextView);
    myTextView.setTypeface(myTypeface);

Can anyone please get me out of this issue?


On Mobiletuts+ there is very good tutorial on Text formatting for Android. Quick Tip: Customize Android Fonts

EDIT: Tested it myself now. Here is the solution. You can use a subfolder called fonts but it must go in the assets folder not the res folder. So

assets/fonts

Also make sure that the font ending I mean the ending of the font file itself is all lower case. In other words it should not be myFont.TTF but myfont.ttf this way must be in lower case


After trying most of the solutions described in this thread, I accidentally found Calligraphy (https://github.com/chrisjenx/Calligraphy) - a library by Christopher Jenkins that lets you easily add custom fonts to your app. The advantages of his lib comparing to approaches suggested here are:

  1. you don't have to introduce your own overriden TextView component, you use the built-in TextView
  2. you can easily include the library using gradle
  3. The library doesn't limit your choice of fonts; you just add your preferred ones to the assets dir
  4. you not only get custom text views — all the other text-based Android compontents will also be displayed using your custom font.


I know there are good answers already, but here's a fully working implementation.

Here's the custom text view:

package com.mycompany.myapp.widget;

/**
 * Text view with a custom font.
 * <p/>
 * In the XML, use something like {@code customAttrs:customFont="roboto-thin"}. The list of fonts
 * that are currently supported are defined in the enum {@link CustomFont}. Remember to also add
 * {@code xmlns:customAttrs="http://schemas.android.com/apk/res-auto"} in the header.
 */
public class CustomFontTextView extends TextView {

    private static final String sScheme =
            "http://schemas.android.com/apk/res-auto";
    private static final String sAttribute = "customFont";

    static enum CustomFont {
        ROBOTO_THIN("fonts/Roboto-Thin.ttf"),
        ROBOTO_LIGHT("fonts/Roboto-Light.ttf");

        private final String fileName;

        CustomFont(String fileName) {
            this.fileName = fileName;
        }

        static CustomFont fromString(String fontName) {
            return CustomFont.valueOf(fontName.toUpperCase(Locale.US));
        }

        public Typeface asTypeface(Context context) {
            return Typeface.createFromAsset(context.getAssets(), fileName);
        }
    }

    public CustomFontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        if (isInEditMode()) {
            return;
        } else {
            final String fontName = attrs.getAttributeValue(sScheme, sAttribute);

            if (fontName == null) {
                throw new IllegalArgumentException("You must provide \"" + sAttribute + "\" for your text view");
            } else {
                final Typeface customTypeface = CustomFont.fromString(fontName).asTypeface(context);
                setTypeface(customTypeface);
            }
        }
    }
}

Here's the custom attributes. This should go to your res/attrs.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomFontTextView">
        <attr name="customFont" format="string"/>
    </declare-styleable>
</resources>

And here's how you use it. I'll use a relative layout to wrap it and show the customAttr declaration, but it could obviously be whatever layout you already have.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:customAttrs="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.mycompany.myapp.widget.CustomFontTextView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="foobar"
         customAttrs:customFont="roboto_thin" />

</RelativeLayout>


I've successfully used this before. The only difference between our implementations is that I wasn't using a subfolder in assets. Not sure if that will change anything, though.


Provided that you placed the font in the right place and there is no error in the font file itself, your code should work like that, RATTLESNAKE.

However, it would be a lot easier if you could just define a font in your layout xml, like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- This text view is styled with the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This uses my font in bold italic style" />

    <!-- This text view is styled here and overrides the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:flFont="anotherFont"
        android:textStyle="normal"
        android:text="This uses another font in normal style" />

    <!-- This text view is styled with a style and overrides the app theme -->
    <com.innovattic.font.FontTextView
        style="@style/StylishFont"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This also uses another font in normal style" />

</LinearLayout>

With the accompanying res/values/styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

    <!-- Application theme -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
        <item name="android:textViewStyle">@style/MyTextViewStyle</item>
    </style>

    <!-- Style to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextViewStyle" parent="@android:style/Widget.Holo.Light.TextView">
        <item name="android:textAppearance">@style/MyTextAppearance</item>
    </style>

    <!-- Text appearance to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextAppearance" parent="@android:style/TextAppearance.Holo">
        <!-- Alternatively, reference this font with the name "aspergit" -->
        <!-- Note that only our own TextView's will use the font attribute -->
        <item name="flFont">someFont</item>
        <item name="android:textStyle">bold|italic</item>
    </style>

    <!-- Alternative style, maybe for some other widget -->
    <style name="StylishFont">
        <item name="flFont">anotherFont</item>
        <item name="android:textStyle">normal</item>
    </style>

</resources>

I created a couple of tools specifically for this purpose. Refer to this project from GitHub, or take a look at this blog post which explains the whole thing.


The best way to do it From Android O preview release is this way:

It works only if you have android studio-2.4 or above

  1. Right-click the res folder and go to New > Android resource directory. The New
    Resource Directory window appears.
  2. In the Resource type list, select font, and then click OK.
  3. Add your font files in the font folder.The folder structure below generates R.font.dancing_script, R.font.la_la, and R.font.ba_ba.
  4. Double-click a font file to preview the file's fonts in the editor.

Next we must create a font family:

  1. Right-click the font folder and go to New > Font resource file. The New Resource File window appears.
  2. Enter the File Name, and then click OK. The new font resource XML opens in the editor.
  3. Enclose each font file, style, and weight attribute in the font tag element. The following XML illustrates adding font-related attributes in the font resource XML:

Adding fonts to a TextView:

   <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fontFamily="@font/hey_fontfamily"/>

As from the documentation

Working With Fonts

All the steps are correct.


For Custom Fonts in android create a folder within assets folder name it "fonts" place your desired fonts.ttf or .otf file in it.

If you extends UIBaseFragment:

Typeface font = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Arial.ttf");
        tv.setTypeface(font);

else if extends Activity:

Typeface font = Typeface.createFromAsset(getContext().getAssets(), "fonts/Arial.ttf");
        tv.setTypeface(font);


You can use PixlUI at https://github.com/neopixl/PixlUI

import their .jar and use it in XML

 <com.neopixl.pixlui.components.textview.TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world"
    pixlui:typeface="GearedSlab.ttf" />


Since I was not satisfied with all the presented solutions on SO, I've come up with mine. It's based on a little trick with tags (i.e. you can't use tags in your code), I put the font path there. So when defining views, you can do either this:

<TextView
        android:id="@+id/textViewHello1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World 1"
        android:tag="fonts/Oswald-Regular.ttf"/>

or this:

<TextView
        android:id="@+id/textViewHello2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World 2"
        style="@style/OswaldTextAppearance"/>

<style name="OswaldTextAppearance">
        <item name="android:tag">fonts/Oswald-Regular.ttf</item>
        <item name="android:textColor">#000000</item>
</style>

Now you can either explicitly access / setup the view as:

TextView textView = TextViewHelper.setupTextView(this, R.id.textViewHello1).setText("blah");

or just setup everything via:

TextViewHelper.setupTextViews(this, (ViewGroup) findViewById(R.id.parentLayout)); // parentLayout is the root view group (relative layout in my case)

And what is the magic class you ask? Mostly glued from another SO posts, with helper methods for both activity and fragments:

import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

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

public class TextViewHelper {
    private static final Map<String, Typeface> mFontCache = new HashMap<>();

    private static Typeface getTypeface(Context context, String fontPath) {
        Typeface typeface;
        if (mFontCache.containsKey(fontPath)) {
            typeface = mFontCache.get(fontPath);
        } else {
            typeface = Typeface.createFromAsset(context.getAssets(), fontPath);
            mFontCache.put(fontPath, typeface);
        }
        return typeface;
    }

    public static void setupTextViews(Context context, ViewGroup parent) {
        for (int i = parent.getChildCount() - 1; i >= 0; i--) {
            final View child = parent.getChildAt(i);
            if (child instanceof ViewGroup) {
                setupTextViews(context, (ViewGroup) child);
            } else {
                if (child != null) {
                    TextViewHelper.setupTextView(context, child);
                }
            }
        }
    }

    public static void setupTextView(Context context, View view) {
        if (view instanceof TextView) {
            if (view.getTag() != null) // also inherited from TextView's style
            {
                TextView textView = (TextView) view;
                String fontPath = (String) textView.getTag();
                Typeface typeface = getTypeface(context, fontPath);
                if (typeface != null) {
                    textView.setTypeface(typeface);
                }
            }
        }
    }

    public static TextView setupTextView(View rootView, int id) {
        TextView textView = (TextView) rootView.findViewById(id);
        setupTextView(rootView.getContext().getApplicationContext(), textView);
        return textView;
    }

    public static TextView setupTextView(Activity activity, int id) {
        TextView textView = (TextView) activity.findViewById(id);
        setupTextView(activity.getApplicationContext(), textView);
        return textView;
    }
}


Unfortunately there is no good solution for this.

I've seen the many articles about using a custom TextView but what they forget it that it's not only textviews that can implement fonts & there are textviews hidden away in other views inaccessible to the developer; I'm not even going to get started on Spannable.

You could use an external font utility like:

Calligraphy Font Tool

BUT This loops over every view in the application on it's creation and even this utility misses some views (ViewPager renders normal font) then you have the problem that is when Google updates their build tools this will occasionally crash because it needs to target deprecated properties. It's also a little slow as it uses Java's Reflection.

It's really up to Google to fix this. We need better font support in Android. If you look at the solution from iOS they literally have 100's of fonts built in to select from. Want a custom font? Simply drop a TFF in and it's usable..

For now were now limited to the offering that Google offers us which is extremely limited but fortunately mobile optimized.


Make sure to paste the above code into onCreate() after your call to the super and the call to setContentView(). This small detail kept my hung up for awhile.


With Android 8.0 using Custom Fonts in Application became easy with downloadable fonts. We can add fonts directly to the res/font/ folder in the project folder, and in doing so, the fonts become automatically available in Android Studio.

Android - Using Custom Font

Now set fontFamily attribute to list of fonts or click on more and select font of your choice. This will add tools:fontFamily="@font/your_font_file" line to your TextView.

This will Automatically generate few files.

1. In values folder it will create fonts_certs.xml.

2. In Manifest it will add this lines:

  <meta-data
            android:name="preloaded_fonts"
            android:resource="@array/preloaded_fonts" /> 

3. preloaded_fonts.xml

<resources>
    <array name="preloaded_fonts" translatable="false">
        <item>@font/open_sans_regular</item>
        <item>@font/open_sans_semibold</item>
    </array>
</resources>


You can use easy & simple EasyFonts third party library to set variety of custom fonts to your TextView. By using this library you should not have to worry about downloading and adding fonts into the assets/fonts folder. Also about Typeface object creation.

Instead of

Typeface myTypeface = Typeface.createFromAsset(getAssets(), "fonts/myFont.ttf");
TextView myTextView = (TextView)findViewById(R.id.myTextView);
myTextView.setTypeface(myTypeface);

Simply:

TextView myTextView = (TextView)findViewById(R.id.myTextView);
myTextView.setTypeface(EasyFonts.robotoThin(this));

This library also provides following font face.

  • Roboto
  • Droid Serif
  • Droid Robot
  • Freedom
  • Fun Raiser
  • Android Nation
  • Green Avocado
  • Recognition


I had the same problem, the TTF did not show up. I changed the font file, and with the same code it's working.


If you want to load the font from the network or easily style it, you can use:

https://github.com/shellum/fontView

Example:

<!--Layout-->
<com.finalhack.fontview.FontView
        android:id="@+id/someFontIcon"
        android:layout_width="80dp"
        android:layout_height="80dp" />

//Java:
fontView.setupFont("http://blah.com/myfont.ttf", true, character, FontView.ImageType.CIRCLE);
fontView.addForegroundColor(Color.RED);
fontView.addBackgroundColor(Color.WHITE);


Well, after seven years you can change whole app textView or what you want easily by using android.support libraries 26++.

E.g:

Create your font package app/src/res/font and move your font into it.

Android - Using Custom Font

And in your app theme just add it as a fontFamily:

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

Example for use with textView only:

<style name="fontTextView" parent="@android:style/Widget.TextView">
    <item name="android:fontFamily">monospace</item>
</style>

And add into your main theme:

<item name="android:textViewStyle">@style/fontTextView</item>

Currently it's worked on 8.1 until 4.1 API Jelly Bean And that's a wide range.


Update answer: Android 8.0 (API level 26) introduces a new feature, Fonts in XML. just use the Fonts in XML feature on devices running Android 4.1 (API level 16) and higher, use the Support Library 26.

see this link


Old answer

There are two ways to customize fonts :

!!! my custom font in assets/fonts/iran_sans.ttf



Way 1 : Refrection Typeface.class ||| best way

call FontsOverride.setDefaultFont() in class extends Application, This code will cause all software fonts to be changed, even Toasts fonts

AppController.java

public class AppController extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        //Initial Font
        FontsOverride.setDefaultFont(getApplicationContext(), "MONOSPACE", "fonts/iran_sans.ttf");

    }
}

FontsOverride.java

public class FontsOverride {

    public static void setDefaultFont(Context context, String staticTypefaceFieldName, String fontAssetName) {
        final Typeface regular = Typeface.createFromAsset(context.getAssets(), fontAssetName);
        replaceFont(staticTypefaceFieldName, regular);
    }

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



Way 2: use setTypeface

for special view just call setTypeface() to change font.

CTextView.java

public class CTextView extends TextView {

    public CTextView(Context context) {
        super(context);
        init(context,null);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context,attrs);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context,attrs);
    }

    public void init(Context context, @Nullable AttributeSet attrs) {

        if (isInEditMode())
            return;

        // use setTypeface for change font this view
        setTypeface(FontUtils.getTypeface("fonts/iran_sans.ttf"));

    }
}

FontUtils.java

public class FontUtils {

    private static Hashtable<String, Typeface> fontCache = new Hashtable<>();

    public static Typeface getTypeface(String fontName) {
        Typeface tf = fontCache.get(fontName);
        if (tf == null) {
            try {
                tf = Typeface.createFromAsset(AppController.getInstance().getApplicationContext().getAssets(), fontName);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
            fontCache.put(fontName, tf);
        }
        return tf;
    }

}


The correct way of doing this as of API 26 is described in the official documentation here :

https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html

This involves placing the ttf files in res/font folder and creating a font-family file.


The most simple solution android supported now!

Use custom font in xml:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fontFamily="@font/[your font resource]"/>

look details:

https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html


  • Open your project and select Project on the top left
  • app --> src --> main
  • right click to main and create directory name it as assets
  • right click to assest and create new directory name it fonts
  • you need to find free fonts like free fonts
  • give it to your Textview and call it in your Activity class
  • copy your fonts inside the fonts folder
  • TextView txt = (TextView) findViewById(R.id.txt_act_spalsh_welcome); Typeface font = Typeface.createFromAsset(getAssets(), "fonts/Aramis Italic.ttf"); txt.setTypeface(font);

name of the font must be correct and have fun


Yes, downloadable fonts are so easy, as Dipali s said.

This is how you do it...

  1. Place a TextView.
  2. In the properties pane, select the fontFamily dropdown. If it isn't there, find the caret thingy (the > and click on it to expand textAppearance) under the.
  3. Expand the font-family drop down.
  4. In the little list, scroll all the way down till you see more fonts
  5. This will open up a dialog box where you can search from Google Fonts
  6. Search for the font you like with the search bar at the top
  7. Select your font.
  8. Select the style of the font you like (i.e. bold, normal, italic, etc)
  9. In the right pane, choose the radio button that says Add font to project
  10. Click okay. Now your TextView has the font you like!

BONUS: If you would like to style EVERYTHING with text in your application with chosen font, just add <item name="android:fontfamily">@font/fontnamehere</item> into your styles.xml

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜