24

I want to use Font Awesome's icon set in my android application. I have some TextView to set those icons. I don't want to use any png image. My Textview is like this ->

<TextView
    android:id="@+id/userLogin"
    android:text="Login Now"
    android:clickable="true"
    android:onClick="login"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

No, I want to put a icon before the text Login Now. How to do that ?

  • 3
    Check out my blog post (works on latest android) - https://niveditagautam.wordpress.com/2018/10/15/adding-font-awesome-to-your-android-app – user63762453 Jan 03 '19 at 23:34
  • Here's a GitHub repository providing a Kotlin solution to this (all the fonts are included too): https://github.com/finnmglas/fontawesome-android – finnmglas May 18 '20 at 20:29

11 Answers11

37

You can follow this answer.

First Download the fontawesome.ttf from here. And put the file in asset/fontawesome.ttf.

Then Make a FontAwesome class which actually represents the textview of FontAwesome like this way.

public class FontAwesome extends TextView {


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

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

    public FontAwesome(Context context) {
        super(context);
        init();
    }

    private void init() {
    
    //Font name should not contain "/".
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
                "fontawesome.ttf");
        setTypeface(tf);
    }
    
}

now you can use the Fontawesome class as your need and also follow the cheatsheet. to get your icon's Unicode.

So, your TextView will be like this.

<PACKAGE_NAME.FontAwesome 
    android:id="@+id/userLogin"
    android:text="&#xf007;  Login Now"
    android:clickable="true"
    android:onClick="login"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
Pratik Butani
  • 60,504
  • 58
  • 273
  • 437
Zahidul Islam
  • 3,180
  • 1
  • 25
  • 35
  • This is the answer i'm looking for. Thanks . –  Jun 22 '16 at 06:16
  • 4
    android.view.InflateException: Binary XML file line #27: Binary XML file line #27: Error inflating class package.gui.custom.FaTextView with this class – Ninja Coding Aug 18 '16 at 13:56
  • 1
    How can I use it programatically? I tried setting text using setText, but it prints the cheat code. – Sagar Mehta Feb 18 '17 at 14:45
  • @sagar, please follow the answer – Zahidul Islam Feb 18 '17 at 14:47
  • I get icon code(f007) form server as a string, How I suppose to use it as the icon, I tried setting up appended text () but it shows only text – Brijesh Kumar Jul 11 '18 at 10:48
  • You shouldn't import all fonts and all images, it will increase the size of your app. The best way is to import each svg you want to use. – Nicolas Jan 13 '19 at 18:45
  • @SagarMehta I use `\uf007` to substitute the `` – Hzzkygcs Jan 12 '22 at 11:21
  • @Nicolas That depends, actually. Sure, if you only want to use a few selected symbols, then it makes sense to only import those. But there are situations where you simply want to have the whole set. For example if you want to add a set of icons for selection by the user. – arkascha May 27 '23 at 14:55
9

Here are the steps to follow:

  1. First download font-awesome from here: http://fontawesome.io/
  2. Create assets folder and add fontawesome-webfont.ttf to this folder
  3. Create a helper class by below code:
public class FontManager {
    public static final String ROOT = "fonts/",
    FONTAWESOME = ROOT + "fontawesome-webfont.ttf";   
    public static Typeface getTypeface(Context context, String font) {
        return Typeface.createFromAsset(context.getAssets(), font);
    }    
}

4. Now use font awesome to your textview using below code

Typeface iconFont = FontManager.getTypeface(getApplicationContext(), FontManager.FONTAWESOME);
tvIcon1 = (TextView) findViewById(R.id.tvIcon1);
tvIcon2 = (TextView) findViewById(R.id.tvIcon2);
tvIcon3 = (TextView) findViewById(R.id.tvIcon3);
tvIcon1.setTypeface(iconFont);
tvIcon2.setTypeface(iconFont);
tvIcon3.setTypeface(iconFont);

You can get full source code in my blog post here.

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
Nimblechapps
  • 489
  • 5
  • 5
9

You can also import the raw vector images from Font Awesome and import them as drawables in your project with the help of creating a new Vector Asset in Android Studio:

Go to the folder where you have installed Font Awesome

...../fontawesome-pro-version#/advanced-options/raw-svg

There you will find 4 folders: brands, light, regular and solid.

All the icons are available as separated vector images in those 4 folders

To import an icon, go to resources, right click and select New -> Vector asset. A dialog will open. Select Local file as option, and select the vector image you want to import (path). Name of the image will be substracted from the image file.

And then you can resolve your problem by simple using a compound TextView, something like this:

 <TextView
    android:drawableStart="@drawable/my_imported_fontawesome_login_icon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Login Now"
    android:gravity="center_vertical"/>

One advantage of this solution is, that you only need to import the icons you really need, without the overhead of a complete or even more fonts, as the icons are divided over 4 fonts.

Gerard Frijters
  • 358
  • 3
  • 11
  • How to use this xml files from code. my app is in flutter I am using kotlin to create pinned shortcut. So there is no layout as such. I just want to set this icon as icon on android homescreen using .seticon under shortcutinfo – user3698694 Oct 10 '22 at 07:01
5

You can Use FontAwesome, just declare in String.xml

<resources>
    <string name="fa_icon_areachart">&#xf1fe;</string>
    <string name="fa_icon_piechart">&#xf200;</string>
    <string name="fa_icon_linechart">&#xf201;</string>
</resources>
Aditya Vyas-Lakhan
  • 13,409
  • 16
  • 61
  • 96
3
  1. First create your Font Resource Directory

    1. Right-click the res folder and go to New > Android resource directory
    2. In the Resource type list, select font, and then click OK
    3. Check this guide for more details
  2. Download the FontAwesome TTF files

  3. Add your font files in the font folder

    1. Right-click the font folder and go to Show in Explorer
    2. Move your desired TTF files to this folder
  4. Create your icon dictionary:

    1. Right-click the values resources folder and go to Show in Explorer
    2. Move the XML Files to this folder:
      • XML for Brands Icons: strings_fa_brands.xml
      • XML for Regular Icons: strings_fa_regular.xml
      • XML for Solid Icons: strings_fa_solid.xml
    3. Or check the FontAwesome Cheatsheet to create your own, the XML will look like this:
    <resources>
       <string name="fa_regular_sun">&#xf185;</string>
       <string name="fa_regular_surprise">&#xf5c2;</string>
       <string name="fa_regular_thumbs_up">&#xf164;</string>
    </resources>
    
  5. In the layout XML file, set the text and fontFamily attribute to the icon you want

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/fa_regular_thumbs_up"
            android:fontFamily="@font/fa-regular-400"/>
    
Wellington
  • 151
  • 1
  • 3
  • 2
    this was a most systematic answer I saw on this post. Could you please elaborate to tell how to use this icon directly in code without layout xml thing – user3698694 Oct 10 '22 at 07:07
  • @user3698694 Use the value directly. `android:text="@string/fa_regular_thumbs_up"` is the same as `android:text=""` – Wellington Oct 11 '22 at 16:40
2

Using Typeface you can set it directly by code

  mTypeFace = FontCache.get("font/GFont.ttf", getActivity());
  mButtonQkView.setTypeface(mTypeFace);
  mButtonQkView.setText(String.valueOf((char) 0xe907));

For setting font icon as Leftdrawable,First generate drawable from the font icon using TextDrawable class

        TextDrawable gIcon = new TextDrawable(this);
        gIcon.setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);
        gIcon.setTextAlign(Layout.Alignment.ALIGN_CENTER);
        gIcon.setTypeface(FontCache.get(getString(R.string.icomoon), this));
        gIcon.setText(String.valueOf((char) 0xe907));
        gIcon.setTextColor(getResources().getColor(color));

And set it as left drawable

mButtonQkView.setCompoundDrawablesWithIntrinsicBounds(gIcon, null, null, null);

The code for class TextDrawable

public class TextDrawable extends Drawable {

/* Platform XML constants for typeface */
private static final int SANS = 1;
private static final int SERIF = 2;
private static final int MONOSPACE = 3;
/* Attribute lists to pull default values from the current theme */
private static final int[] themeAttributes = {
        android.R.attr.textAppearance
};
private static final int[] appearanceAttributes = {
        android.R.attr.textSize,
        android.R.attr.typeface,
        android.R.attr.textStyle,
        android.R.attr.textColor
};
/* Resources for scaling values to the given device */
private Resources mResources;
/* Paint to hold most drawing primitives for the text */
private TextPaint mTextPaint;
/* Layout is used to measure and draw the text */
private StaticLayout mTextLayout;
/* Alignment of the text inside its bounds */
private Layout.Alignment mTextAlignment = Layout.Alignment.ALIGN_NORMAL;
/* Optional path on which to draw the text */
private Path mTextPath;
/* Stateful text color list */
private ColorStateList mTextColors;
/* Container for the bounds to be reported to widgets */
private Rect mTextBounds;
/* Text string to draw */
private CharSequence mText = "";


public TextDrawable(Context context) {
    super();
    //Used to load and scale resource items
    mResources = context.getResources();
    //Definition of this drawables size
    mTextBounds = new Rect();
    //Paint to use for the text
    mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
    mTextPaint.density = mResources.getDisplayMetrics().density;
    mTextPaint.setDither(true);

    int textSize = 15;
    ColorStateList textColor = null;
    int styleIndex = -1;
    int typefaceIndex = -1;

    //Set default parameters from the current theme
    TypedArray a = context.getTheme().obtainStyledAttributes(themeAttributes);
    int appearanceId = a.getResourceId(0, -1);
    a.recycle();

    TypedArray ap = null;
    if (appearanceId != -1) {
        ap = context.obtainStyledAttributes(appearanceId, appearanceAttributes);
    }
    if (ap != null) {
        for (int i = 0; i < ap.getIndexCount(); i++) {
            int attr = ap.getIndex(i);
            switch (attr) {
                case 0: //Text Size
                    textSize = a.getDimensionPixelSize(attr, textSize);
                    break;
                case 1: //Typeface
                    typefaceIndex = a.getInt(attr, typefaceIndex);
                    break;
                case 2: //Text Style
                    styleIndex = a.getInt(attr, styleIndex);
                    break;
                case 3: //Text Color
                    textColor = a.getColorStateList(attr);
                    break;
                default:
                    break;
            }
        }

        ap.recycle();
    }

    setTextColor(textColor != null ? textColor : ColorStateList.valueOf(0xFF000000));
    setRawTextSize(textSize);

    Typeface tf = null;
    switch (typefaceIndex) {
        case SANS:
            tf = Typeface.SANS_SERIF;
            break;

        case SERIF:
            tf = Typeface.SERIF;
            break;

        case MONOSPACE:
            tf = Typeface.MONOSPACE;
            break;
    }

    setTypeface(tf, styleIndex);
}

/**
 * Return the text currently being displayed
 */
public CharSequence getText() {
    return mText;
}

/**
 * Set the text that will be displayed
 * @param text Text to display
 */
public void setText(CharSequence text) {
    if (text == null) text = "";

    mText = text;

    measureContent();
}

/**
 * Return the current text size, in pixels
 */
public float getTextSize() {
    return mTextPaint.getTextSize();
}

/**
 * Set the text size.  The value will be interpreted in "sp" units
 * @param size Text size value, in sp
 */
public void setTextSize(float size) {
    setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
}

/**
 * Set the text size, using the supplied complex units
 * @param unit Units for the text size, such as dp or sp
 * @param size Text size value
 */
public void setTextSize(int unit, float size) {
    float dimension = TypedValue.applyDimension(unit, size,
            mResources.getDisplayMetrics());
    setRawTextSize(dimension);
}

/*
 * Set the text size, in raw pixels
 */
private void setRawTextSize(float size) {
    if (size != mTextPaint.getTextSize()) {
        mTextPaint.setTextSize(size);

        measureContent();
    }
}

/**
 * Return the horizontal stretch factor of the text
 */
public float getTextScaleX() {
    return mTextPaint.getTextScaleX();
}

/**
 * Set the horizontal stretch factor of the text
 * @param size Text scale factor
 */
public void setTextScaleX(float size) {
    if (size != mTextPaint.getTextScaleX()) {
        mTextPaint.setTextScaleX(size);
        measureContent();
    }
}

/**
 * Return the current text alignment setting
 */
public Layout.Alignment getTextAlign() {
    return mTextAlignment;
}

/**
 * Set the text alignment.  The alignment itself is based on the text layout direction.
 * For LTR text NORMAL is left aligned and OPPOSITE is right aligned.
 * For RTL text, those alignments are reversed.
 * @param align Text alignment value.  Should be set to one of:
 *
 *   {@link Layout.Alignment#ALIGN_NORMAL},
 *   {@link Layout.Alignment#ALIGN_NORMAL},
 *   {@link Layout.Alignment#ALIGN_OPPOSITE}.
 */
public void setTextAlign(Layout.Alignment align) {
    if (mTextAlignment != align) {
        mTextAlignment = align;
        measureContent();
    }
}

/**
 * Sets the typeface and style in which the text should be displayed,
 * and turns on the fake bold and italic bits in the Paint if the
 * Typeface that you provided does not have all the bits in the
 * style that you specified.
 *
 */
private void setTypeface(Typeface tf, int style) {
    if (style > 0) {
        if (tf == null) {
            tf = Typeface.defaultFromStyle(style);
        } else {
            tf = Typeface.create(tf, style);
        }

        setTypeface(tf);
        // now compute what (if any) algorithmic styling is needed
        int typefaceStyle = tf != null ? tf.getStyle() : 0;
        int need = style & ~typefaceStyle;
        mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0);
        mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
    } else {
        mTextPaint.setFakeBoldText(false);
        mTextPaint.setTextSkewX(0);
        setTypeface(tf);
    }
}

/**
 * Return the current typeface and style that the Paint
 * using for display.
 */
public Typeface getTypeface() {
    return mTextPaint.getTypeface();
}

/**
 * Sets the typeface and style in which the text should be displayed.
 * Note that not all Typeface families actually have bold and italic
 * variants, so you may need to use
 * {@link #setTypeface(Typeface, int)} to get the appearance
 * that you actually want.
 */
public void setTypeface(Typeface tf) {
    if (mTextPaint.getTypeface() != tf) {
        mTextPaint.setTypeface(tf);

        measureContent();
    }
}

/**
 * Set a single text color for all states
 * @param color Color value such as {@link Color#WHITE} or {@link Color#argb(int, int, int, int)}
 */
public void setTextColor(int color) {
    setTextColor(ColorStateList.valueOf(color));
}

/**
 * Set the text color as a state list
 * @param colorStateList ColorStateList of text colors, such as inflated from an R.color resource
 */
private void setTextColor(ColorStateList colorStateList) {
    mTextColors = colorStateList;
    updateTextColors(getState());
}

/**
 * Optional Path object on which to draw the text.  If this is set,
 * TextDrawable cannot properly measure the bounds this drawable will need.
 * You must call {@link #setBounds(int, int, int, int) setBounds()} before
 * applying this TextDrawable to any View.
 *
 * Calling this method with <code>null</code> will remove any Path currently attached.
 */
public void setTextPath(Path path) {
    if (mTextPath != path) {
        mTextPath = path;
        measureContent();
    }
}

/**
 * Internal method to take measurements of the current contents and apply
 * the correct bounds when possible.
 */
private void measureContent() {
    //If drawing to a path, we cannot measure intrinsic bounds
    //We must resly on setBounds being called externally
    if (mTextPath != null) {
        //Clear any previous measurement
        mTextLayout = null;
        mTextBounds.setEmpty();
    } else {
        //Measure text bounds
        double desired = Math.ceil(Layout.getDesiredWidth(mText, mTextPaint));
        mTextLayout = new StaticLayout(mText, mTextPaint, (int) desired,
                mTextAlignment, 1.0f, 0.0f, false);
        mTextBounds.set(0, 0, mTextLayout.getWidth(), mTextLayout.getHeight());
    }

    //We may need to be redrawn
    invalidateSelf();
}

/**
 * Internal method to apply the correct text color based on the drawable's state
 */
private boolean updateTextColors(int[] stateSet) {
    int newColor = mTextColors.getColorForState(stateSet, Color.WHITE);
    if (mTextPaint.getColor() != newColor) {
        mTextPaint.setColor(newColor);
        return true;
    }

    return false;
}

@Override
protected void onBoundsChange(Rect bounds) {
    //Update the internal bounds in response to any external requests
    mTextBounds.set(bounds);
}

@Override
public boolean isStateful() {
    /*
     * The drawable's ability to represent state is based on
     * the text color list set
     */
    return mTextColors.isStateful();
}

@Override
protected boolean onStateChange(int[] state) {
    //Upon state changes, grab the correct text color
    return updateTextColors(state);
}

@Override
public int getIntrinsicHeight() {
    //Return the vertical bounds measured, or -1 if none
    if (mTextBounds.isEmpty()) {
        return -1;
    } else {
        return (mTextBounds.bottom - mTextBounds.top);
    }
}

@Override
public int getIntrinsicWidth() {
    //Return the horizontal bounds measured, or -1 if none
    if (mTextBounds.isEmpty()) {
        return -1;
    } else {
        return (mTextBounds.right - mTextBounds.left);
    }
}

@Override
public void draw(@NonNull Canvas canvas) {
    final Rect bounds = getBounds();
    final int count = canvas.save();
    canvas.translate(bounds.left, bounds.top);
    if (mTextPath == null) {
        //Allow the layout to draw the text
        mTextLayout.draw(canvas);
    } else {
        //Draw directly on the canvas using the supplied path
        canvas.drawTextOnPath(mText.toString(), mTextPath, 0, 0, mTextPaint);
    }
    canvas.restoreToCount(count);
}

@Override
public void setAlpha(int alpha) {
    if (mTextPaint.getAlpha() != alpha) {
        mTextPaint.setAlpha(alpha);
    }
}

@Override
public int getOpacity() {
    return mTextPaint.getAlpha();
}

@Override
public void setColorFilter(ColorFilter cf) {
    if (mTextPaint.getColorFilter() != cf) {
        mTextPaint.setColorFilter(cf);
    }
}

}

Nidhin
  • 1,818
  • 22
  • 23
2

If anyone wants to assign font value programmatically then this is how I did. Create an assets folder if it's not there and put ttf file in the folder

Typeface type = Typeface.createFromAsset(getContext().getAssets(), "fonts/fa_solid_900.ttf");
tvHeart.setTypeface(type);
tvHeart.setText(Html.fromHtml("&#xf004;"));
Gilliy
  • 71
  • 3
1

Similar code, But small change.

Use AppCompatTextView, because when you using TextView, you will get a warning like this:

This custom view should extend android.support.v7.widget.AppCompatTextView instead

So kindly use AppCompatTextView. It will be better if you use AppCompatTextView instead of TextView:

import android.graphics.Typeface;
import android.support.v7.widget.AppCompatTextView;
import android.content.Context;
import android.util.AttributeSet;

public class FontAwesome extends AppCompatTextView{

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

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

    public FontAwesome(Context context) {
        super(context);
        init();
    }

    private void init() {

        //Font name should not contain "/".
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
                "fontawesome.ttf");
        setTypeface(tf);
    }
}
Jérémie Bertrand
  • 3,025
  • 3
  • 44
  • 53
Saravanan S
  • 123
  • 1
  • 13
1

As there was no really comfortable way of including FontAwesome in my Android projects,

I created a Github Repository that helps use FontAwesome with Kotlin rather than Java.

The repository helps you dynamically switch between FontAwesome types (solid, regular and brands). Dynamic example (see code):


Resources


I learned a lot through all the answers here, so thank you everybody! I hope this answer is helpful to you too!

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
finnmglas
  • 1,626
  • 4
  • 22
  • 37
0

previous cases are OK, but just imagine you need a dynamically generated menu items based on data obtained from api. We don't now what exact icon should be in each item before we obtain pages model. Of course we can put all the FA icons to String resource as shown before, but also you can insert FA icon by name just in fly

let's do it

  1. add FA fonts lib: implementation 'com.mikepenz:fontawesome-typeface:5.9.0.0-kotlin@aar'

  2. add an ext lib iconics:
    implementation "com.mikepenz:iconics-core:4.0.2"

  3. do come code (kotlin):

     //add class property in your activity
     private lateinit var navView: NavigationView
    
     //find your navigation view on activity onCreate
     navView = findViewById(R.id.event_details_nav_view)
    
     //call your updateNavigation(pages) function when you received data with menu items. i.e. Page is a data object with Id, Name, faIcon (it's name)
    
     //add function where we create menu items based on pages model
     fun updateNavigation(pages: List<Page>) {
         pages.forEach {
                     navView.menu.add(0, it.id, 0, it.name)
                         .apply {
                             IconsHelper.getFontAwesomeIcon(
                                 this,
                                 name,
                                 24,
                                 R.color.nav_drawer_item_icon_color_default
                            ).let {
                                menuItem.icon = it
                            }
                         }
                 }
      }
    

and all the magic is in IconHelper, let's do it

// add IconHelper.kt and paste it there

import android.content.Context
import com.mikepenz.iconics.Iconics.findFont
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp


object IconsHelper {
private const val defaultIconName = "faw_question_circle"

fun getFontAwesomeIcon(context: Context, name: String, size: Int, color: Int): IconicsDrawable {
    return when(name.isEmpty()) {
        true ->
            getIcon(defaultIconName, size, color, context)

        false -> {
            normalizeIconName(name)
                .let {
                    when(iconExists(context, it)) {
                        true ->
                            getIcon(it, size, color, context)

                        false ->
                            getIcon(IconsHelper.defaultIconName, size, color, context)
                    }
                }
        }
    }
}

private fun getIcon(name: String, size: Int, color: Int, context: Context): IconicsDrawable {
    return IconicsDrawable(context, name)
        .apply {
            sizeDp(size)
            colorInt(color)
        }
}

private fun normalizeIconName(name: String): String {
    name
        .replaceFirst("fa", "faw")
        .replace("-", "_")
        .let {
            return when(it.contains("sliders")) {
                true ->
                    "faw_sliders_h"
                false ->
                    it
            }
        }
}

private fun iconExists(context: Context, icon: String): Boolean {
    try {
        findFont(icon.substring(0, 3), context)
            .let {
                it!!.getIcon(icon)
            }
        return true
    } catch (e: Exception) {
        print(e)
    }

    return false
}

}

p.s. look at normalizeIconName() function, maybe you don't need it.

alexis
  • 31
  • 5
0

To get started, include the fontawesome in your build.gradle and sync your project.

dependencies {
// font awesome
implementation 'info.androidhive:fontawesome:0.0.5'
}

To use it?

<info.androidhive.fontawesome.FontTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/fa_calendar_check_solid"
            android:textColor="@color/icon_color"
            android:textSize="@dimen/icon_size"
            app:solid_icon="true" />

solid_icon: To display solid icon, set this value as true. brand_icon: To display brand icon, set this value as true.

Zenonymous
  • 149
  • 2
  • 4