37

I want my button text to be in the Copperplate Gothic Light font and I yet have not come across a simple clean code for a simple function as this. Help!

PS: Since android comes with ariel and a few other fonts on its own we need to import (apologies for the lack of a better word since I'm new to this) the font we wish to use. This is all I have been able to gather till yet and this is where the trail ends for me.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Garima Tiwari
  • 1,490
  • 6
  • 28
  • 46
  • yes you need to create folder names assets in your android projects, then use it like this Typeface font = Typeface.createFromAsset(getAssets(), "copperplate_gothic_light.TTF"); and then use it on button – Marko Niciforovic May 20 '13 at 11:13
  • I didnt get what u meant by "use it", what do i create within that folder and where to put the code you've posted? – Garima Tiwari May 20 '13 at 11:17
  • import your font file (copy your font file (Copperplate Gothic Light.ttf) from where you have downloaded it or if its windows font to assets folder) inside your project. Then you add this lines of code when you create a button in code, or refer to it by finditbyid. So right after it should be Typeface font = Typeface.createFromAsset(getAssets(), "copperplate_gothic_light.TTF"); button.setTypeface(font); – Marko Niciforovic May 20 '13 at 11:21
  • Error: native typeface cannot be made. – Garima Tiwari May 20 '13 at 11:27
  • Okay, that means the font file is either corrupt or unsupported for some reason. You can drop it on the SD card and load it from FILE, to make sure it's not a problem with your assets. It will most likely work like that – Marko Niciforovic May 20 '13 at 11:29
  • check this question, it will most likely help you http://stackoverflow.com/questions/12766930/native-typeface-cannot-be-made-only-for-some-people – Marko Niciforovic May 20 '13 at 11:34

9 Answers9

139

If you plan to add the same font to several buttons I suggest that you go all the way and implement it as a style and subclass button:

public class ButtonPlus extends Button {

    public ButtonPlus(Context context) {
        super(context);
    }

    public ButtonPlus(Context context, AttributeSet attrs) {
        super(context, attrs);
        CustomFontHelper.setCustomFont(this, context, attrs);
    }

    public ButtonPlus(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        CustomFontHelper.setCustomFont(this, context, attrs);
    }
}

This is a helper class to set a font on a TextView (remember, Button is a subclass of TextView) based on the com.my.package:font attribute:

public class CustomFontHelper {

    /**
     * Sets a font on a textview based on the custom com.my.package:font attribute
     * If the custom font attribute isn't found in the attributes nothing happens
     * @param textview
     * @param context
     * @param attrs
     */
    public static void setCustomFont(TextView textview, Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomFont);
        String font = a.getString(R.styleable.CustomFont_font);
        setCustomFont(textview, font, context);
        a.recycle();
    }

    /**
     * Sets a font on a textview
     * @param textview
     * @param font
     * @param context
     */
    public static void setCustomFont(TextView textview, String font, Context context) {
        if(font == null) {
            return;
        }
        Typeface tf = FontCache.get(font, context);
        if(tf != null) {
            textview.setTypeface(tf);
        }
    }

}

And here's the FontCache to reduce memory usage on older devices:

public class FontCache {

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

    public static Typeface get(String name, Context context) {
        Typeface tf = fontCache.get(name);
        if(tf == null) {
            try {
                tf = Typeface.createFromAsset(context.getAssets(), name);
            }
            catch (Exception e) {
                return null;
            }
            fontCache.put(name, tf);
        }
        return tf;
    }
}

In res/values/attrs.xml we define the custom styleable attribute

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

And finally an example use in a layout:

    <com.my.package.buttons.ButtonPlus
        style="@style/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_sometext"/>

And in res/values/style.xml

<style name="button" parent="@android:style/Widget.Button">
    <item name="com.my.package:font">fonts/copperplate_gothic_light.TTF</item>
</style>

This may seem like an awful lot of work, but you'll thank me once you have couple of handfuls of buttons and textfields that you want to change font on.

britzl
  • 10,132
  • 7
  • 41
  • 38
  • Hey that's very thoughtful because I do have to implement it through a million activities. – Garima Tiwari May 20 '13 at 11:38
  • This is one of the most helpful answers I have found around StackOverflow. Thank you! – gnclmorais Jan 30 '14 at 17:02
  • Fantastic response. Out of curiosity why bother with FontCache as a separate class from the CustomFontHelper? I combined those and applied this to both buttons and textviews. – Tom S. Dec 11 '14 at 17:16
  • 1
    Off the top of my head I can't think of a good reason for separating them other than that you may want to use the FontCache in other circumstances as well. – britzl Dec 11 '14 at 18:39
  • Nice answer! But you could also override the setTypeface method. – denvercoder9 Feb 24 '15 at 09:58
  • What about the first constructor not setting the custom font? Is it not the one called when using Buttons in xml? (I truly don't know that) – Teo Inke Nov 05 '16 at 19:46
  • Can you explain style.xml?? Coz, I didn't got that the item name is upto the font package or upto the font.ttf file?? – MashukKhan Feb 08 '17 at 07:42
  • Can't Thank you enough. I had a project ready to publish but only 2 RecyclerView in that app was lagging when user scroll only in the devices which had low free ram and free storage. I always suspected that is happens due to custom fonts I set because that list item had more than 10 TextViews with different fonts. After following your answer now that problem is fixed. – Chathuranga Shan May 03 '18 at 16:19
13

1) Get the font you need as a .ttf (CopperplateGothicLight.ttf for example) file and place it in your project's /assets/ directory

2) Use this code to refer to the font and set it to your button:

Typeface copperplateGothicLight = Typeface.createFromAsset(getAppContext().getAssets(), "CopperplateGothicLight.ttf"); 
yourButton.setTypeface(copperplateGothicLight);
npace
  • 4,218
  • 1
  • 25
  • 35
  • Where do I get this .ttf file you talk about? Im extremely new to this so I'll need a little patience, thank you. – Garima Tiwari May 20 '13 at 11:19
  • 1
    It's a TrueType font file. If you do not have a .ttf for your font, just search Google or something, I'm sure there are tons of free fonts you can use. – npace May 20 '13 at 11:21
  • 1
    Take care with memory use on older devices if you don't cache the Typeface (I think the bug was solved in newer Android versions): https://code.google.com/p/android/issues/detail?id=9904 – britzl May 20 '13 at 11:58
3

After several research, my best option was :

public class CustomButton extends Button {

    Typeface normalTypeface = FontCache.get("fonts/CopperplateGothicLight.ttf", getContext());
    Typeface boldTypeface = FontCache.get("fonts/CopperplateGothicBold.ttf", getContext());

    /**
     * @param context
     */
    public CustomButton(Context context) {
        super(context);
    }

    /**
     * @param context
     * @param attrs
     */
    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public CustomButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

}

then Using fontCache from the 1st answer on this : Memory leaks with custom font for set custom font

public class FontCache {
    private static Hashtable<String, Typeface> fontCache = new Hashtable<String, Typeface>();

    public static Typeface get(String name, Context context) {
        Typeface tf = fontCache.get(name);
        if(tf == null) {
            try {
                tf = Typeface.createFromAsset(context.getAssets(), name);
            }
            catch (Exception e) {
                return null;
            }
            fontCache.put(name, tf);
        }
        return tf;
    }
}

Less code and more usage of the android standards !

Community
  • 1
  • 1
2

MainActivity.java

    package com.mehuljoisar.customfontdemo;

import android.app.Activity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Menu;
import android.widget.Button;

public class MainActivity extends Activity {

    private Button button1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button1 = (Button)findViewById(R.id.button1);
        button1.setTypeface(Typeface.createFromAsset(getAssets(), "copperplate-gothic-light.ttf"));
        button1.setText("hello");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

}

activity_main.xml

<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"
tools:context=".MainActivity" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:text="@string/hello_world" />

<Button
    android:id="@+id/button1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginTop="24dp"
    android:text="Button" />

Download link for your desired font: copperplate_gothic_light

put it inside your asset folder.

Screenshot: enter image description here

I hope it will be helpful !!

Mehul Joisar
  • 15,348
  • 6
  • 48
  • 57
  • Hey, I did that. Downloaded the thingy off the internet and put it in my assets folder but it doesn't seem to recognize it. Does the name of the folder has to be same or do i put in the font name itself? – Garima Tiwari May 20 '13 at 11:43
  • @GarimaTiwari:look at the screenshot,you need to put that `.ttf` file in your `assets` folder and you need to use same file name while setting typeface to the button. – Mehul Joisar May 20 '13 at 11:48
  • @GarimaTiwari:if you want to apply the font at many places,answer of `britzl` is better for your case.make custom view by extending `Button` to get rid of memory leaks occurs while `createFromAsset` method in each activity. – Mehul Joisar May 20 '13 at 11:53
0

First download TTF file for font style and then put it into the assets folder of your project.

You can set it programmatically by following way :

Typeface font_style = Typeface.createFromAsset(getAssets(), "yourcystomfontstyle.ttf");  
yourbutton.setTypeface(font_style);
baldguy
  • 2,090
  • 1
  • 16
  • 25
  • "Firstly you can not set Custom font style from XML file". This is wrong. You can define a custom style attribute and subclass Button. See my answer. – britzl May 20 '13 at 11:33
  • @britzl Oh I dnt know that.. Thanks for such useful info. – baldguy May 20 '13 at 11:56
  • 1
    Take care with memory use on older devices if you don't cache the Typeface (I think the bug was solved in newer Android versions): https://code.google.com/p/android/issues/detail?id=9904 – britzl May 20 '13 at 11:57
0

You can use custom button class as given below.Put your font in asset/font folder.

public class CustomButton extends Button{


    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
        // TODO Auto-generated constructor stub
    }
    public CustomButton(Context context) {
        super(context);
        init();
        // TODO Auto-generated constructor stub
    }
    public CustomButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
        // TODO Auto-generated constructor stub
    }
    private void init(){
        Typeface font_type=Typeface.createFromAsset(getContext().getAssets(), "font/ProximaNova-Bold.ttf");
        setTypeface(font_type);
    }
}

Now you can use the button in xml as given below.

<model.CustomButton
            android:id="@+id/search"
            android:layout_width="@dimen/edittext_width_large"
            android:layout_height="@dimen/button_height"
            android:layout_below="@+id/cars"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="@dimen/pad_20dp"
            android:background="@drawable/button_pressed_bg"
            android:text="@string/find_car"
            android:textColor="@color/white" />
Jinosh P
  • 341
  • 2
  • 8
0

Try this. Also useful for EditTextViews, TextViews.. whatever!

<your.namespace.app.FontButton
     app:font="montserrat"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"/>

How is possible? This way!

public class FontButton extends Button {

public FontEditText(Context context) {
    this( context, null );
}

public FontEditText(Context context, AttributeSet attrs) {
    this( context, attrs, 0 );
    init( context, attrs );
}

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

public FontEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super( context, attrs, defStyleAttr, defStyleRes );
    init( context, attrs );
}

private void init(Context context, AttributeSet attrs) {
    TypedArray ta = context.obtainStyledAttributes( attrs, R.styleable.Fonts );

    if ( ta != null ) {
        String fontAsset = ta.getString( R.styleable.Fonts_font );
        if ( !StringUtils.isEmpty( fontAsset ) ) {
            int type = Integer.parseInt( fontAsset );

            Typeface typeFace = FontManager.getInstance( context ).getByType( type );
            ta.recycle();
            super.setTypeface( typeFace );
        }
    }
}

}

public class FontManager {

private static FontManager Instance;

private Context context;

private Typeface robotoCondensedBold;
private Typeface robotoCondensed;
private Typeface robotoLight;
private Typeface kronica;
private Typeface montserrat;
private Typeface montserratLight;
private Typeface keepCalmMedium;

private FontManager(Context context) {
    this.context = context;
    this.robotoCondensedBold = Typeface.createFromAsset( context.getAssets(), "fonts/RobotoCondensed-Bold.ttf" );
    this.robotoCondensed = Typeface.createFromAsset( context.getAssets(), "fonts/RobotoCondensed-Regular.ttf" );
    this.robotoLight = Typeface.createFromAsset( context.getAssets(), "fonts/Roboto-Light.ttf" );
    this.kronica = Typeface.createFromAsset( context.getAssets(), "fonts/kronika.ttf" );
    this.montserrat = Typeface.createFromAsset( context.getAssets(), "fonts/Montserrat-Regular.ttf" );
    this.montserratLight = Typeface.createFromAsset( context.getAssets(), "fonts/Montserrat-Light.ttf" );
    this.keepCalmMedium = Typeface.createFromAsset( context.getAssets(), "fonts/KeepCalmMedium.ttf" );
}

public synchronized static FontManager getInstance(Context context) {
    if ( Instance == null )
        Instance = new FontManager( context );

    return Instance;
}

public Typeface getByType(int type) {
    switch ( type ) {
        case 0:
            return FontManager.getInstance( context ).getRobotoCondensedBold();
        case 1:
            return FontManager.getInstance( context ).getRobotoLight();
        case 2:
            return FontManager.getInstance( context ).getKronica();
        case 3:
            return FontManager.getInstance( context ).getRobotoCondensed();
        case 4:
            return FontManager.getInstance( context ).getMontserrat();
        case 5:
            return FontManager.getInstance( context ).getMontserratLight();
        case 6:
            return FontManager.getInstance( context ).getKeepCalmMedium();
        default:
            return Typeface.DEFAULT;
    }
}

public Typeface getRobotoCondensedBold() {
    return robotoCondensedBold;
}

public Typeface getKronica() {
    return kronica;
}

public Typeface getRobotoCondensed() {
    return robotoCondensed;
}

public Typeface getRobotoLight() {
    return robotoLight;
}

public Typeface getMontserrat() {
    return montserrat;
}

public Typeface getMontserratLight() {
    return montserratLight;
}

public Typeface getKeepCalmMedium() {
    return keepCalmMedium;
}

In addition, a font_attrs.xml in your res folder:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="Fonts">
        <attr name="font" format="enum">
            <enum name="robotoCondensedBold" value="0"/>
            <enum name="robotoLight" value="1"/>
            <enum name="kronica" value="2"/>
            <enum name="robotoCondensed" value="3"/>
            <enum name="montserrat" value="4"/>
            <enum name="montserratLight" value="5"/>
            <enum name="keepCalmMedium" value="6"/>
        </attr>
    </declare-styleable>
</resources> 

Note that you only need to modify the FontManager and the font_attrs.xml to customize your fonts!

Rafa0809
  • 1,733
  • 21
  • 24
0

You can use the below code. Just replace the font name in mTextFont() method as per your requirement.

public class Button_Roboto_Regular extends Button {
public Button_Roboto_Regular(Context context) {
    super(context);
    mTextFont(context);
}

public Button_Roboto_Regular(Context context, AttributeSet attrs) {
    super(context, attrs);
    mTextFont(context);
}

public Button_Roboto_Regular(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mTextFont(context);
}
private void mTextFont(Context context) {
    Typeface face = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Regular_0.ttf");
    this.setTypeface(face);
}
VIVEK CHOUDHARY
  • 468
  • 5
  • 8
0

In kotlin you can create your custom button and override the typeface.

class StandardButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, dyfStyleAttr: Int = 0) : AppCompatButton(context, attrs, dyfStyleAttr) {
    init {
        typeface = Typeface.createFromAsset(context.assets, "fonts/CopperplateGothicBold.ttf")
    }
}
Joe Malebe
  • 614
  • 5
  • 6