Related
I am developing an Android app. In my app, I am using multiple languages. Totally I am localizing. But I am having a problem with it. Currently, my app will support two languages. But my problem is I want to change the typeface for all TextView, EditText, Button and so on when the user change the language.
This is how I am setting typeface programmatically when the language change:
if(Language=="mm")
{
Typeface tf = Typeface.createFromAsset(getAssets(),"fonts/tharlon.ttf");
icBtnFindPlaces.setTypeface(tf);
}
else{
Typeface tf = Typeface.createFromAsset(getAssets(),"fonts/inconsolata.ttf");
icBtnFindPlaces.setTypeface(tf);
}
As you can see above I have do it for every views with text. This is not a good way. Why I want is I want to set typeface globally for all views, not one by one. Is it possible?
Hi here is a good example.
If there are many TextViews whose external font need to be set, then you have to create a your own custom TextView and set the font like as below:
Add FontManager as a Singleton Java class
public class FontManager {
public static Typeface light;
public static Typeface medium;
public static Typeface regular;
private static FontManager instance;
private AssetManager mgr;
private FontManager(AssetManager _mgr) {
this.mgr = _mgr;
lght = Typeface.createFromAsset(mgr,"---.ttf");
medium = Typeface.createFromAsset(mgr,"---.ttf");
regular = Typeface.createFromAsset(mgr,"---.ttf");
}
public static FontManager init(AssetManager mgr) {
if(instance != null)
return instance;
return instance = new FontManager(mgr);
}
public static FontManager getInstance() {
return instance;
}
private String fixAssetFilename(String asset) {
// Empty font filename?
// Just return it. We can't help.
if (asset.length() == 0)
return asset;
return asset;
}
}
Call it in your Splash Activity as:
FontManager.init(getApplicationContext().getAssets());
public class LightTextView extends TextView {
public LightTextView(Context context) {
super(context);
}
public LightTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if(context.getString(R.string.lang).equals("en"))
setTypeface(FontManager.light);
else
setTypeface(FontManager.medium);
}
}
Add values --> string.xml
<string name="lang">en</string>
values-fr --> string.xml
<string name="lang">fr</string>
<com.exa.fonttest.LightTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:textSize="20sp"
android:textColor="#color/white"
android:text="Good luck"/>
While changing the locale automatically change the font.
Good luck.
How to change the font in a TextView, as default it's shown up as Arial? How to change it to Helvetica?
First, the default is not Arial. The default is Droid Sans.
Second, to change to a different built-in font, use android:typeface in layout XML or setTypeface() in Java.
Third, there is no Helvetica font in Android. The built-in choices are Droid Sans (sans), Droid Sans Mono (monospace), and Droid Serif (serif). While you can bundle your own fonts with your application and use them via setTypeface(), bear in mind that font files are big and, in some cases, require licensing agreements (e.g., Helvetica, a Linotype font).
EDIT
The Android design language relies on traditional typographic tools
such as scale, space, rhythm, and alignment with an underlying grid.
Successful deployment of these tools is essential to help users
quickly understand a screen of information. To support such use of
typography, Ice Cream Sandwich introduced a new type family named
Roboto, created specifically for the requirements of UI and
high-resolution screens.
The current TextView framework offers Roboto in thin, light, regular
and bold weights, along with an italic style for each weight. The
framework also offers the Roboto Condensed variant in regular and bold
weights, along with an italic style for each weight.
After ICS, android includes Roboto fonts style,
Read more Roboto
EDIT 2
With the advent of Support Library 26, Android now supports custom fonts by
default. You can insert new fonts in res/fonts which can be set to TextViews individually either in XML or programmatically. The default font for the whole application can also be changed by defining it styles.xml The android developer documentation has a clear guide on this here
First download the .ttf file of the font you need (arial.ttf). Place it in the assets folder. (Inside assets folder create new folder named fonts and place it inside it.) Use the following code to apply the font to your TextView:
Typeface type = Typeface.createFromAsset(getAssets(),"fonts/arial.ttf");
textView.setTypeface(type);
Typeface tf = Typeface.createFromAsset(getAssets(),
"fonts/DroidSansFallback.ttf");
TextView tv = (TextView) findViewById(R.id.CustomFontText);
tv.setTypeface(tf);
You might want to create static class which will contain all the fonts. That way, you won't create the font multiple times which might impact badly on performance.
Just make sure that you create a sub-folder called "fonts" under "assets" folder.
Do something like:
public class CustomFontsLoader {
public static final int FONT_NAME_1 = 0;
public static final int FONT_NAME_2 = 1;
public static final int FONT_NAME_3 = 2;
private static final int NUM_OF_CUSTOM_FONTS = 3;
private static boolean fontsLoaded = false;
private static Typeface[] fonts = new Typeface[3];
private static String[] fontPath = {
"fonts/FONT_NAME_1.ttf",
"fonts/FONT_NAME_2.ttf",
"fonts/FONT_NAME_3.ttf"
};
/**
* Returns a loaded custom font based on it's identifier.
*
* #param context - the current context
* #param fontIdentifier = the identifier of the requested font
*
* #return Typeface object of the requested font.
*/
public static Typeface getTypeface(Context context, int fontIdentifier) {
if (!fontsLoaded) {
loadFonts(context);
}
return fonts[fontIdentifier];
}
private static void loadFonts(Context context) {
for (int i = 0; i < NUM_OF_CUSTOM_FONTS; i++) {
fonts[i] = Typeface.createFromAsset(context.getAssets(), fontPath[i]);
}
fontsLoaded = true;
}
}
This way, you can get the font from everywhere in your application.
Best practice ever
TextViewPlus.java:
public class TextViewPlus extends TextView {
private static final String TAG = "TextView";
public TextViewPlus(Context context) {
super(context);
}
public TextViewPlus(Context context, AttributeSet attrs) {
super(context, attrs);
setCustomFont(context, attrs);
}
public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setCustomFont(context, attrs);
}
private void setCustomFont(Context ctx, AttributeSet attrs) {
TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
String customFont = a.getString(R.styleable.TextViewPlus_customFont);
setCustomFont(ctx, customFont);
a.recycle();
}
public boolean setCustomFont(Context ctx, String asset) {
Typeface typeface = null;
try {
typeface = Typeface.createFromAsset(ctx.getAssets(), asset);
} catch (Exception e) {
Log.e(TAG, "Unable to load typeface: "+e.getMessage());
return false;
}
setTypeface(typeface);
return true;
}
}
attrs.xml: (Where to place res/values)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TextViewPlus">
<attr name="customFont" format="string"/>
</declare-styleable>
</resources>
How to use:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:foo="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.mypackage.TextViewPlus
android:id="#+id/textViewPlus1"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:text="#string/showingOffTheNewTypeface"
foo:customFont="my_font_name_regular.otf">
</com.mypackage.TextViewPlus>
</LinearLayout>
Hope this will help you.
The answers above are correct. Just make sure that you create a sub-folder called "fonts" under "assets" folder if you are using that piece of code.
Another way to consolidate font creation...
public class Font {
public static final Font PROXIMA_NOVA = new Font("ProximaNovaRegular.otf");
public static final Font FRANKLIN_GOTHIC = new Font("FranklinGothicURWBoo.ttf");
private final String assetName;
private volatile Typeface typeface;
private Font(String assetName) {
this.assetName = assetName;
}
public void apply(Context context, TextView textView) {
if (typeface == null) {
synchronized (this) {
if (typeface == null) {
typeface = Typeface.createFromAsset(context.getAssets(), assetName);
}
}
}
textView.setTypeface(typeface);
}
}
And then to use in your activity...
myTextView = (TextView) findViewById(R.id.myTextView);
Font.PROXIMA_NOVA.apply(this, myTextView);
Mind you, this double-checked locking idiom with the volatile field only works correctly with the memory model used in Java 1.5+.
Best practice is to use Android Support Library version 26.0.0 or above.
STEP 1: add font file
In res folder create new font resource dictionary
Add font file (.ttf, .orf)
For example, when font file will be helvetica_neue.ttf that will generates R.font.helvetica_neue
STEP 2: create font family
In font folder add new resource file
Enclose each font file, style, and weight attribute in the element.
For example:
<?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/helvetica_neue" />
</font-family>
STEP 3: use it
In xml layouts:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/my_font"/>
Or add fonts to style:
<style name="customfontstyle" parent="#android:style/TextAppearance.Small">
<item name="android:fontFamily">#font/lobster</item>
</style>
For more examples you can follow documentation:
Working with fonts
When your font is stored inside res/asset/fonts/Helvetica.ttf use the following:
Typeface tf = Typeface.createFromAsset(getAssets(),"fonts/Helvetica.ttf");
txt.setTypeface(tf);
Or, if your font file is stores inside res/font/helvetica.ttf use the following:
Typeface tf = ResourcesCompat.getFont(this,R.font.helvetica);
txt.setTypeface(tf);
It's a little old, but I improved the class CustomFontLoader a little bit and I wanted to share it so it can be helpfull. Just create a new class with this code.
import android.content.Context;
import android.graphics.Typeface;
public enum FontLoader {
ARIAL("arial"),
TIMES("times"),
VERDANA("verdana"),
TREBUCHET("trbuchet"),
GEORGIA("georgia"),
GENEVA("geneva"),
SANS("sans"),
COURIER("courier"),
TAHOMA("tahoma"),
LUCIDA("lucida");
private final String name;
private Typeface typeFace;
private FontLoader(final String name) {
this.name = name;
typeFace=null;
}
public static Typeface getTypeFace(Context context,String name){
try {
FontLoader item=FontLoader.valueOf(name.toUpperCase(Locale.getDefault()));
if(item.typeFace==null){
item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");
}
return item.typeFace;
} catch (Exception e) {
return null;
}
}
public static Typeface getTypeFace(Context context,int id){
FontLoader myArray[]= FontLoader.values();
if(!(id<myArray.length)){
return null;
}
try {
if(myArray[id].typeFace==null){
myArray[id].typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+myArray[id].name+".ttf");
}
return myArray[id].typeFace;
}catch (Exception e) {
return null;
}
}
public static Typeface getTypeFaceByName(Context context,String name){
for(FontLoader item: FontLoader.values()){
if(name.equalsIgnoreCase(item.name)){
if(item.typeFace==null){
try{
item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");
}catch (Exception e) {
return null;
}
}
return item.typeFace;
}
}
return null;
}
public static void loadAllFonts(Context context){
for(FontLoader item: FontLoader.values()){
if(item.typeFace==null){
try{
item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");
}catch (Exception e) {
item.typeFace=null;
}
}
}
}
}
Then just use this code on you textview:
Typeface typeFace=FontLoader.getTypeFace(context,"arial");
if(typeFace!=null) myTextView.setTypeface(typeFace);
I finally got a very easy solution to this.
use these Support libraries in app level gradle,
compile 'com.android.support:appcompat-v7:26.0.2'
compile 'com.android.support:support-v4:26.0.2'
then create a directory named "font" inside the res folder
put fonts(ttf) files in that font directory, keep in mind the naming conventions [e.g.name should not contain any special character, any uppercase character and any space or tab]
After that, reference that font from xml like this
<Button
android:id="#+id/btn_choose_employee"
android:layout_width="140dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:background="#drawable/rounded_red_btn"
android:onClick="btnEmployeeClickedAction"
android:text="#string/searching_jobs"
android:textAllCaps="false"
android:textColor="#color/white"
android:fontFamily="#font/times_new_roman_test"
/>
In this example, times_new_roman_test is a font ttf file from that font directory
import java.lang.ref.WeakReference;
import java.util.HashMap;
import android.content.Context;
import android.graphics.Typeface;
public class FontsManager {
private static FontsManager instance;
private static HashMap<String, WeakReference<Typeface>> typefaces = new HashMap<String, WeakReference<Typeface>>();
private static Context context;
private FontsManager(final Context ctx) {
if (context == null) {
context = ctx;
}
}
public static FontsManager getInstance(final Context appContext) {
if (instance == null) {
instance = new FontsManager(appContext);
}
return instance;
}
public static FontsManager getInstance() {
if (instance == null) {
throw new RuntimeException(
"Call getInstance(Context context) at least once to init the singleton properly");
}
return instance;
}
public Typeface getFont(final String assetName) {
final WeakReference<Typeface> tfReference = typefaces.get(assetName);
if (tfReference == null || tfReference.get() == null) {
final Typeface tf = Typeface.createFromAsset(context.getResources().getAssets(),
assetName);
typefaces.put(assetName, new WeakReference<Typeface>(tf));
return tf;
}
return tfReference.get();
}
}
This way, you can create a View which inherits from TextView and calls setTypeface on its constructor.
get font from asset and set to all children
public static void overrideFonts(final Context context, final View v) {
try {
if (v instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) v;
for (int i = 0; i < vg.getChildCount(); i++) {
View child = vg.getChildAt(i);
overrideFonts(context, child);
}
} else if (v instanceof TextView ) {
((TextView) v).setTypeface(Typeface.createFromAsset(context.getAssets(),"DroidNaskh.ttf"));// "BKOODB.TTF"));
}
} catch (Exception e) {
}
}
add class FontTextView.java:
public class FontTextView extends TextView {
String fonts[] = {"HelveticaNeue.ttf", "HelveticaNeueLight.ttf", "motschcc.ttf", "symbol.ttf"};
public FontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public FontTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if (!isInEditMode()) {
init(attrs);
}
}
public FontTextView(Context context) {
super(context);
if (!isInEditMode()) {
init(null);
}
}
private void init(AttributeSet attrs) {
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.FontTextView);
if (a.getString(R.styleable.FontTextView_font_type) != null) {
String fontName = fonts[Integer.valueOf(a.getString(R.styleable.FontTextView_font_type))];
if (fontName != null) {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/" + fontName);
setTypeface(myTypeface);
}
a.recycle();
}
}
}
}
add to assets library font
add to attrs.xml ,
The numbers should be in the order in array class.
<declare-styleable name="FontTextView">
<attr name="font_type" format="enum">
<enum name="HelveticaNeue" value="0"/>
<enum name="HelveticaNeueLight" value="1"/>
<enum name="motschcc" value="2"/>
<enum name="symbol" value="3"/>
</attr>
Select a font from the list
Android uses the Roboto font, which is a really nice looking font, with several different weights (regular, light, thin, condensed) that look great on high density screens.
Check below link to check roboto fonts:
How to use Roboto in xml layout
Back to your question, if you want to change the font for all of the TextView/Button in your app, try adding below code into your styles.xml to use Roboto-light font:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
......
<item name="android:buttonStyle">#style/MyButton</item>
<item name="android:textViewStyle">#style/MyTextView</item>
</style>
<style name="MyButton" parent="#style/Widget.AppCompat.Button">
<item name="android:textAllCaps">false</item>
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="MyTextView" parent="#style/TextAppearance.AppCompat">
<item name="android:fontFamily">sans-serif-light</item>
</style>
And don't forget to use 'AppTheme' in your AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
......
</application>
Maybe something a bit simpler:
public class Fonts {
public static HashSet<String,Typeface> fonts = new HashSet<>();
public static Typeface get(Context context, String file) {
if (! fonts.contains(file)) {
synchronized (this) {
Typeface typeface = Typeface.createFromAsset(context.getAssets(), name);
fonts.put(name, typeface);
}
}
return fonts.get(file);
}
}
// Usage
Typeface myFont = Fonts.get("arial.ttf");
(Note this code is untested, but in general this approach should work well.)
In my project I am using the font android: fontFamily = "sans-serif-light", and working properly.
I am also using the library viewpagerindicator. I want to use the font android: fontFamily = "sans-serif-light" also in the viewpagerindicator, but can not find how to do it
I've tried using android:fontFamily = "sans-serif-light" in <com.viewpagerindicator.TitlePageIndicator ... and in style, but without success.
I have also tried:
PageIndicator mIndicator = (TitlePageIndicator) findViewById (R.id.indicator);
Typeface myTypeface = Typeface.createFromAsset (getAssets (), "fonts / Roboto-Light.ttf");
mIndicator.setTypeface (myTypeface);
but this does not work ..
I appreciate any help.
Thanks and regards
If I don't get you wrong, you want to change titles font in view pager indicator,
I changed the library to achieve that,
for TabPageIndicator custome typeface I added this for TabPageIndicator.java
private Typeface mTypeface;
public void setTypeFace(Typeface tf) {
this.mTypeface = tf;
}
and then change addTab function to this:
private void addTab(int index, CharSequence text, int iconResId) {
final TabView tabView = new TabView(getContext());
tabView.mIndex = index;
tabView.setFocusable(true);
tabView.setOnClickListener(mTabClickListener);
tabView.setText(text);
**if (mTypeface != null) {
tabView.setTypeface(mTypeface);
}**
if (iconResId != 0) {
tabView.setCompoundDrawablesWithIntrinsicBounds(iconResId, 0, 0, 0);
}
mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, MATCH_PARENT, 1));
}
now you should just setTypeFace on your tabpagerindicator, like this:
mTabPageIndicator = (TabPageIndicator) findViewById(R.id.tab_page_indicator);
mTabPageIndicator.setTypeFace(Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/custome_font.ttf");
I'm using the ViewPageIndicator library, here's how I did it (index is the tab index in your view page indicator):
private void changeTabText(int index, boolean on){
if(tabLayout.getChildCount()-1 >= index){
TextView tv = (TextView)tabLayout.getChildAt(index);
tv.setTextColor(getResources().getColor(on? android.R.color.black : R.color.light_grey));
CustomFont.setTypeface(tv, CustomFont.NORMAL);
}
}
Here's how I got the tablayout:
tabLayout = (ViewGroup)indicator.getChildAt(0); //indicator is a horizontal scroll view, there will be only one root layout
Here's what my custom font does:
public static void setTypeface(TextView view, String font) {
Typeface typeface = Typeface.createFromAsset(view.getContext().getAssets(), BASE_PATH + font);
view.setTypeface(typeface);
}
A more OOD implementation is to modify the Library by creating a new interface:
public interface FontPagerAdapter {
/**
* Get the fonts to set.
*/
Typeface getCustomFont();}
And in class TabPageIndicator.java add a new property:
private Typeface customTypeFace;
which will be set in the notifyDataSetChanged() method by declaring:
if (adapter instanceof FontPagerAdapter) {
FontPagerAdapter fontAdapter = (FontPagerAdapter)adapter;
customTypeFace = fontAdapter.getCustomFont();
}
Later you would change the Font by setting it programatically in the addTab method, just by adding:
if (customTypeFace != null) {
tabView.setTypeface(customTypeFace);
}
Finally in the adapter that will use the library, you need to implement this interface, then override the method:
#Override
public Typeface getCustomFont() {
Typeface font = Typeface.createFromAsset(context.getAssets(),"fonts/PoetsenOne-Regular.ttf");
return font;
}
I have a ttf file, and its theoretically possible, but I'm not looking to touch over 500 different lines of code to programmatically change this. What is the easiest way?
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/Typefaces.html
To extend previous answer with static TYPEFACE:
Add new function:
public static void applyCustomFont(ViewGroup list, Typeface customTypeface) {
for (int i = 0; i < list.getChildCount(); i++) {
View view = list.getChildAt(i);
if (view instanceof ViewGroup) {
applyCustomFont((ViewGroup) view, customTypeface);
} else if (view instanceof TextView) {
((TextView) view).setTypeface(customTypeface);
}
}
}
Get root view of our Layout:
View rootView = findViewById(android.R.id.content)
Than apply custom font for whole activity form with all sub-elements:
applyCustomFont((ViewGroup)rootView, C.TYPEFACE.ArialRounded(this));
I've dealt with this problem myself; although I couldn't set a custom font globally, I was able to just make it little easier to deal with.
So in my Constants class (C.java) I have an Inner class:
public static final class TYPEFACE {
public static final Typeface Helvetica(Context ctx){
Typeface typeface = Typeface.createFromAsset(ctx.getAssets(), "helvetica.otf");
return typeface;
}
public static final Typeface ArialRounded(Context ctx){
Typeface typeface = Typeface.createFromAsset(ctx.getAssets(), "arial_rounded.ttf");
return typeface;
}
}
And in my code, after declaring and intializing the TextView I just set it's Typeface:
TextView title = (TextView)findViewById(R.id.title);
title.setTypeface(C.TYPEFACE.Helvetica(this));
I know this doesn't solve your problem but I hope it helps...
-serkan
Another way to go would be a custom view extending TextView. Not pretty, but you wouldn't need to copy the font code all over the place.
In all, its a pretty annoying problem for sure.
How to change the font in a TextView, as default it's shown up as Arial? How to change it to Helvetica?
First, the default is not Arial. The default is Droid Sans.
Second, to change to a different built-in font, use android:typeface in layout XML or setTypeface() in Java.
Third, there is no Helvetica font in Android. The built-in choices are Droid Sans (sans), Droid Sans Mono (monospace), and Droid Serif (serif). While you can bundle your own fonts with your application and use them via setTypeface(), bear in mind that font files are big and, in some cases, require licensing agreements (e.g., Helvetica, a Linotype font).
EDIT
The Android design language relies on traditional typographic tools
such as scale, space, rhythm, and alignment with an underlying grid.
Successful deployment of these tools is essential to help users
quickly understand a screen of information. To support such use of
typography, Ice Cream Sandwich introduced a new type family named
Roboto, created specifically for the requirements of UI and
high-resolution screens.
The current TextView framework offers Roboto in thin, light, regular
and bold weights, along with an italic style for each weight. The
framework also offers the Roboto Condensed variant in regular and bold
weights, along with an italic style for each weight.
After ICS, android includes Roboto fonts style,
Read more Roboto
EDIT 2
With the advent of Support Library 26, Android now supports custom fonts by
default. You can insert new fonts in res/fonts which can be set to TextViews individually either in XML or programmatically. The default font for the whole application can also be changed by defining it styles.xml The android developer documentation has a clear guide on this here
First download the .ttf file of the font you need (arial.ttf). Place it in the assets folder. (Inside assets folder create new folder named fonts and place it inside it.) Use the following code to apply the font to your TextView:
Typeface type = Typeface.createFromAsset(getAssets(),"fonts/arial.ttf");
textView.setTypeface(type);
Typeface tf = Typeface.createFromAsset(getAssets(),
"fonts/DroidSansFallback.ttf");
TextView tv = (TextView) findViewById(R.id.CustomFontText);
tv.setTypeface(tf);
You might want to create static class which will contain all the fonts. That way, you won't create the font multiple times which might impact badly on performance.
Just make sure that you create a sub-folder called "fonts" under "assets" folder.
Do something like:
public class CustomFontsLoader {
public static final int FONT_NAME_1 = 0;
public static final int FONT_NAME_2 = 1;
public static final int FONT_NAME_3 = 2;
private static final int NUM_OF_CUSTOM_FONTS = 3;
private static boolean fontsLoaded = false;
private static Typeface[] fonts = new Typeface[3];
private static String[] fontPath = {
"fonts/FONT_NAME_1.ttf",
"fonts/FONT_NAME_2.ttf",
"fonts/FONT_NAME_3.ttf"
};
/**
* Returns a loaded custom font based on it's identifier.
*
* #param context - the current context
* #param fontIdentifier = the identifier of the requested font
*
* #return Typeface object of the requested font.
*/
public static Typeface getTypeface(Context context, int fontIdentifier) {
if (!fontsLoaded) {
loadFonts(context);
}
return fonts[fontIdentifier];
}
private static void loadFonts(Context context) {
for (int i = 0; i < NUM_OF_CUSTOM_FONTS; i++) {
fonts[i] = Typeface.createFromAsset(context.getAssets(), fontPath[i]);
}
fontsLoaded = true;
}
}
This way, you can get the font from everywhere in your application.
Best practice ever
TextViewPlus.java:
public class TextViewPlus extends TextView {
private static final String TAG = "TextView";
public TextViewPlus(Context context) {
super(context);
}
public TextViewPlus(Context context, AttributeSet attrs) {
super(context, attrs);
setCustomFont(context, attrs);
}
public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setCustomFont(context, attrs);
}
private void setCustomFont(Context ctx, AttributeSet attrs) {
TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
String customFont = a.getString(R.styleable.TextViewPlus_customFont);
setCustomFont(ctx, customFont);
a.recycle();
}
public boolean setCustomFont(Context ctx, String asset) {
Typeface typeface = null;
try {
typeface = Typeface.createFromAsset(ctx.getAssets(), asset);
} catch (Exception e) {
Log.e(TAG, "Unable to load typeface: "+e.getMessage());
return false;
}
setTypeface(typeface);
return true;
}
}
attrs.xml: (Where to place res/values)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TextViewPlus">
<attr name="customFont" format="string"/>
</declare-styleable>
</resources>
How to use:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:foo="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.mypackage.TextViewPlus
android:id="#+id/textViewPlus1"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:text="#string/showingOffTheNewTypeface"
foo:customFont="my_font_name_regular.otf">
</com.mypackage.TextViewPlus>
</LinearLayout>
Hope this will help you.
The answers above are correct. Just make sure that you create a sub-folder called "fonts" under "assets" folder if you are using that piece of code.
Another way to consolidate font creation...
public class Font {
public static final Font PROXIMA_NOVA = new Font("ProximaNovaRegular.otf");
public static final Font FRANKLIN_GOTHIC = new Font("FranklinGothicURWBoo.ttf");
private final String assetName;
private volatile Typeface typeface;
private Font(String assetName) {
this.assetName = assetName;
}
public void apply(Context context, TextView textView) {
if (typeface == null) {
synchronized (this) {
if (typeface == null) {
typeface = Typeface.createFromAsset(context.getAssets(), assetName);
}
}
}
textView.setTypeface(typeface);
}
}
And then to use in your activity...
myTextView = (TextView) findViewById(R.id.myTextView);
Font.PROXIMA_NOVA.apply(this, myTextView);
Mind you, this double-checked locking idiom with the volatile field only works correctly with the memory model used in Java 1.5+.
Best practice is to use Android Support Library version 26.0.0 or above.
STEP 1: add font file
In res folder create new font resource dictionary
Add font file (.ttf, .orf)
For example, when font file will be helvetica_neue.ttf that will generates R.font.helvetica_neue
STEP 2: create font family
In font folder add new resource file
Enclose each font file, style, and weight attribute in the element.
For example:
<?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/helvetica_neue" />
</font-family>
STEP 3: use it
In xml layouts:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/my_font"/>
Or add fonts to style:
<style name="customfontstyle" parent="#android:style/TextAppearance.Small">
<item name="android:fontFamily">#font/lobster</item>
</style>
For more examples you can follow documentation:
Working with fonts
When your font is stored inside res/asset/fonts/Helvetica.ttf use the following:
Typeface tf = Typeface.createFromAsset(getAssets(),"fonts/Helvetica.ttf");
txt.setTypeface(tf);
Or, if your font file is stores inside res/font/helvetica.ttf use the following:
Typeface tf = ResourcesCompat.getFont(this,R.font.helvetica);
txt.setTypeface(tf);
It's a little old, but I improved the class CustomFontLoader a little bit and I wanted to share it so it can be helpfull. Just create a new class with this code.
import android.content.Context;
import android.graphics.Typeface;
public enum FontLoader {
ARIAL("arial"),
TIMES("times"),
VERDANA("verdana"),
TREBUCHET("trbuchet"),
GEORGIA("georgia"),
GENEVA("geneva"),
SANS("sans"),
COURIER("courier"),
TAHOMA("tahoma"),
LUCIDA("lucida");
private final String name;
private Typeface typeFace;
private FontLoader(final String name) {
this.name = name;
typeFace=null;
}
public static Typeface getTypeFace(Context context,String name){
try {
FontLoader item=FontLoader.valueOf(name.toUpperCase(Locale.getDefault()));
if(item.typeFace==null){
item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");
}
return item.typeFace;
} catch (Exception e) {
return null;
}
}
public static Typeface getTypeFace(Context context,int id){
FontLoader myArray[]= FontLoader.values();
if(!(id<myArray.length)){
return null;
}
try {
if(myArray[id].typeFace==null){
myArray[id].typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+myArray[id].name+".ttf");
}
return myArray[id].typeFace;
}catch (Exception e) {
return null;
}
}
public static Typeface getTypeFaceByName(Context context,String name){
for(FontLoader item: FontLoader.values()){
if(name.equalsIgnoreCase(item.name)){
if(item.typeFace==null){
try{
item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");
}catch (Exception e) {
return null;
}
}
return item.typeFace;
}
}
return null;
}
public static void loadAllFonts(Context context){
for(FontLoader item: FontLoader.values()){
if(item.typeFace==null){
try{
item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");
}catch (Exception e) {
item.typeFace=null;
}
}
}
}
}
Then just use this code on you textview:
Typeface typeFace=FontLoader.getTypeFace(context,"arial");
if(typeFace!=null) myTextView.setTypeface(typeFace);
I finally got a very easy solution to this.
use these Support libraries in app level gradle,
compile 'com.android.support:appcompat-v7:26.0.2'
compile 'com.android.support:support-v4:26.0.2'
then create a directory named "font" inside the res folder
put fonts(ttf) files in that font directory, keep in mind the naming conventions [e.g.name should not contain any special character, any uppercase character and any space or tab]
After that, reference that font from xml like this
<Button
android:id="#+id/btn_choose_employee"
android:layout_width="140dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:background="#drawable/rounded_red_btn"
android:onClick="btnEmployeeClickedAction"
android:text="#string/searching_jobs"
android:textAllCaps="false"
android:textColor="#color/white"
android:fontFamily="#font/times_new_roman_test"
/>
In this example, times_new_roman_test is a font ttf file from that font directory
import java.lang.ref.WeakReference;
import java.util.HashMap;
import android.content.Context;
import android.graphics.Typeface;
public class FontsManager {
private static FontsManager instance;
private static HashMap<String, WeakReference<Typeface>> typefaces = new HashMap<String, WeakReference<Typeface>>();
private static Context context;
private FontsManager(final Context ctx) {
if (context == null) {
context = ctx;
}
}
public static FontsManager getInstance(final Context appContext) {
if (instance == null) {
instance = new FontsManager(appContext);
}
return instance;
}
public static FontsManager getInstance() {
if (instance == null) {
throw new RuntimeException(
"Call getInstance(Context context) at least once to init the singleton properly");
}
return instance;
}
public Typeface getFont(final String assetName) {
final WeakReference<Typeface> tfReference = typefaces.get(assetName);
if (tfReference == null || tfReference.get() == null) {
final Typeface tf = Typeface.createFromAsset(context.getResources().getAssets(),
assetName);
typefaces.put(assetName, new WeakReference<Typeface>(tf));
return tf;
}
return tfReference.get();
}
}
This way, you can create a View which inherits from TextView and calls setTypeface on its constructor.
get font from asset and set to all children
public static void overrideFonts(final Context context, final View v) {
try {
if (v instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) v;
for (int i = 0; i < vg.getChildCount(); i++) {
View child = vg.getChildAt(i);
overrideFonts(context, child);
}
} else if (v instanceof TextView ) {
((TextView) v).setTypeface(Typeface.createFromAsset(context.getAssets(),"DroidNaskh.ttf"));// "BKOODB.TTF"));
}
} catch (Exception e) {
}
}
add class FontTextView.java:
public class FontTextView extends TextView {
String fonts[] = {"HelveticaNeue.ttf", "HelveticaNeueLight.ttf", "motschcc.ttf", "symbol.ttf"};
public FontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public FontTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if (!isInEditMode()) {
init(attrs);
}
}
public FontTextView(Context context) {
super(context);
if (!isInEditMode()) {
init(null);
}
}
private void init(AttributeSet attrs) {
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.FontTextView);
if (a.getString(R.styleable.FontTextView_font_type) != null) {
String fontName = fonts[Integer.valueOf(a.getString(R.styleable.FontTextView_font_type))];
if (fontName != null) {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/" + fontName);
setTypeface(myTypeface);
}
a.recycle();
}
}
}
}
add to assets library font
add to attrs.xml ,
The numbers should be in the order in array class.
<declare-styleable name="FontTextView">
<attr name="font_type" format="enum">
<enum name="HelveticaNeue" value="0"/>
<enum name="HelveticaNeueLight" value="1"/>
<enum name="motschcc" value="2"/>
<enum name="symbol" value="3"/>
</attr>
Select a font from the list
Android uses the Roboto font, which is a really nice looking font, with several different weights (regular, light, thin, condensed) that look great on high density screens.
Check below link to check roboto fonts:
How to use Roboto in xml layout
Back to your question, if you want to change the font for all of the TextView/Button in your app, try adding below code into your styles.xml to use Roboto-light font:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
......
<item name="android:buttonStyle">#style/MyButton</item>
<item name="android:textViewStyle">#style/MyTextView</item>
</style>
<style name="MyButton" parent="#style/Widget.AppCompat.Button">
<item name="android:textAllCaps">false</item>
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="MyTextView" parent="#style/TextAppearance.AppCompat">
<item name="android:fontFamily">sans-serif-light</item>
</style>
And don't forget to use 'AppTheme' in your AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
......
</application>
Maybe something a bit simpler:
public class Fonts {
public static HashSet<String,Typeface> fonts = new HashSet<>();
public static Typeface get(Context context, String file) {
if (! fonts.contains(file)) {
synchronized (this) {
Typeface typeface = Typeface.createFromAsset(context.getAssets(), name);
fonts.put(name, typeface);
}
}
return fonts.get(file);
}
}
// Usage
Typeface myFont = Fonts.get("arial.ttf");
(Note this code is untested, but in general this approach should work well.)