Monday, November 3, 2014

Using custom fonts in Android

The bad news: One can not yet (as of today) use custom fonts on UI when designing application. Custom fonts can be loaded run time only using certain methods.
The good news: In my searches, I found ways to easily use custom fonts in applications. (Yeah, easily... as in easily creating a custom turkey)

My proposal is a system containing one package and some customizations. In the package, 5 files should be implemented and AndroidManifest.xml should be altered. An enumeration, a Heart, a FontProvider and a CustomTextView.
1: The enum: To use multiple custom typefaces in application, I created an enum holding different typeface values.

 public enum FontNames {  
   Yekan  
 }  

2: The FontProvider: This is a static class, though it can be implemented by singletons too. The purpose will be to provide fonts from a pre-built cache to waste as little memory as possible. (Android v2* had a bug which resulted in poor memory management for fonts. In certain conditions created fonts were not correctly freed)


 public class FontProvider {  
   static private Map<FontNames, Typeface> mCache;  
   
   static public void Initialize(){  
     mCache = new HashMap<FontNames, Typeface>();  
     mCache.put(FontNames.Yekan, Typeface.createFromAsset(Heart.getAssets(), "BYEKAN.TTF"));  
   }  
   
   static public Typeface GetFont(FontNames font) {  
     if(mCache == null || mCache.isEmpty())  
       return Typeface.defaultFromStyle(Typeface.NORMAL);  
   
     return mCache.get(font);  
   }  
 }  

3: Heart: Taking in mind that fonts are needed to be customized for a certain application, one can see the need to customize other features of the application. For this, a "HEART" is created to manage different custom elements of the application. The heart is designed again as a static class but can also be implemented as a singleton.

 public final class Heart {  
   static private AssetManager mAssets;  
   
   private Heart() {}  
   
   static public void Initialize(AssetManager assets)  
   {  
     mAssets = assets;  
     FontProvider.Initialize();  
   }  
   
   static public AssetManager getAssets(){  
     return mAssets;  
   }  
 }  
   

4: A CustomTextView: Since custom fonts are more easily implemented in the code than specified in XML, creating a custom control seems less hassle:

 public class TextView extends android.widget.TextView {  
   public TextView(Context context) {  
     super(context);  
     init(null);  
   }  
   
   public TextView(Context context, AttributeSet attrs) {  
     super(context, attrs);  
     init(attrs);  
   }  
   
   public TextView(Context context, AttributeSet attrs, int defStyle) {  
     super(context, attrs, defStyle);  
     init(attrs);  
   }  
   
   private void init(AttributeSet attrs) {  
     if(attrs != null)  
       setTypeface(FontProvider.GetFont(FontNames.Yekan));  
   }  
 }  
   

5: Create a custom application class that starts up the HEART:

 public class Application extends android.app.Application {  
   public Application(){ }  
   
   @Override public void onCreate(){  
     super.onCreate();  
     ir.gnco.shila.ui.Heart.Initialize(getAssets());  
   }  
 }  
   

6: Modify AndroidManifest.xml to load you application class instead of the default one:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
   package="..." >  
   
   <application  
     android:name=".Application"  
     ... >  
   
      <activity>  
        ...  
      </activity>  
   </application>  
 </manifest>  
   

OK now. The hard part is finished. Just build your project and drag'n'drop your new TextView to any Activity you want.

.
.
.
.
PS: Just kidding. Copy your custom font in the assets folder. For AndroidStudio users: The place does not exist. Create it in <project>/app/src/main/assets

No comments:

Post a Comment