I'm trying to change the default font of textviews, checkbox, buttons and android.support.design.widget.TextInputLayout. For clear illustration, I set "android:fontFamily">cursive<.
It seems to appear correctly in Android Studio preview but not in the Emulator, as shown below. Also note, that password (hint) does not seems to work in both. Would appreciate your help to highlight why this is happening.
styles.xml:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">#ed328b</item>
<item name="android:titleTextColor">#ed328b</item>
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">cursive</item>
</style>
<style name="TextLabel" parent="Widget.Design.TextInputLayout">
<!-- Hint color and label color in FALSE state -->
<item name="android:textColorHint">#ed328b</item>
<item name="android:textSize">14sp</item>
<!-- Label color in TRUE state and bar color FALSE and TRUE State -->
<item name="colorAccent">#ed328b</item>
<item name="android:textColor">#ed328b</item>
<item name="colorControlNormal">#ed328b</item>
<item name="colorControlActivated">#ed328b</item>
<item name="android:textColorSecondary">#ed328b</item>
<item name="android:textColorPrimary">#ed328b</item>
<item name="android:fontFamily">cursive</item>
</style>
activity_main.xml:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/TextLabel"
android:layout_marginTop="@dimen/space_2">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:inputType="textEmailAddress"
android:hint="@string/signin_emailaddress"
android:id="@+id/txtEmail" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/TextLabel"
android:layout_marginTop="@dimen/space_2">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:inputType="textPassword"
android:hint="@string/signin_password"
android:id="@+id/txtPassword" />
</android.support.design.widget.TextInputLayout>
<CheckBox
android:id="@+id/rememberBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_gravity="start"
android:text="remember my email and password"
android:textAlignment="center"
android:textColor="#ed328b"
android:textSize="11dp" />
While selecting the Font in the Android Studio, just check the box "Add font to Project" rather choosing "create downloadable Font".
Your problem will be solved.
Android doesn't have built-in support for applying custom fonts directly to text widgets through XML.
You can refer this document to set fonts in xml: https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html
Or you need to set typeface in java code in order to change fonts.
Or you can do something like this:
First
You'll need to define your own stylable. In your /res/values folder, open/create the attrs.xml file and add a declare-styleable object like so:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="FontText">
<attr name="typefaceAsset" format="string"/>
</declare-styleable>
</resources>
Second
Assuming you want to use this widget often, you should set up a simple cache for the loaded Typeface objects, since loading them from memory on the fly can take time. Something like:
public class FontManager {
private static FontManager instance;
private AssetManager mgr;
private Map<String, Typeface> fonts;
private FontManager(AssetManager _mgr) {
mgr = _mgr;
fonts = new HashMap<String, Typeface>();
}
public static void init(AssetManager mgr) {
instance = new FontManager(mgr);
}
public static FontManager getInstance() {
if (instance == null) {
// App.getContext() is just one way to get a Context here
// getContext() is just a method in an Application subclass
// that returns the application context
AssetManager assetManager = App.getContext().getAssets();
init(assetManager);
}
return instance;
}
public Typeface getFont(String asset) {
if (fonts.containsKey(asset))
return fonts.get(asset);
Typeface font = null;
try {
font = Typeface.createFromAsset(mgr, asset);
fonts.put(asset, font);
} catch (Exception e) {
}
if (font == null) {
try {
String fixedAsset = fixAssetFilename(asset);
font = Typeface.createFromAsset(mgr, fixedAsset);
fonts.put(asset, font);
fonts.put(fixedAsset, font);
} catch (Exception e) {
}
}
return font;
}
private String fixAssetFilename(String asset) {
// Empty font filename?
// Just return it. We can't help.
if (TextUtils.isEmpty(asset))
return asset;
// Make sure that the font ends in '.ttf' or '.ttc'
if ((!asset.endsWith(".ttf")) && (!asset.endsWith(".ttc")))
asset = String.format("%s.ttf", asset);
return asset;
}
}
This one will allow you to use .ttc file extensions, but it's untested.
Third
Create a new class that subclasses TextView. This particular example takes into account the defined XML typeface (bold, italic, etc.) and apply it to the font (assuming you're using a .ttc file).
/**
* TextView subclass which allows the user to define a truetype font file to use as the view's typeface.
*/
public class FontText extends TextView {
public FontText(Context context) {
this(context, null);
}
public FontText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FontText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (isInEditMode())
return;
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FontText);
if (ta != null) {
String fontAsset = ta.getString(R.styleable.FontText_typefaceAsset);
if (!TextUtils.isEmpty(fontAsset)) {
Typeface tf = FontManager.getInstance().getFont(fontAsset);
int style = Typeface.NORMAL;
float size = getTextSize();
if (getTypeface() != null)
style = getTypeface().getStyle();
if (tf != null)
setTypeface(tf, style);
else
Log.d("FontText", String.format("Could not create a font from asset: %s", fontAsset));
}
}
}
}
Finally at last
Replace the instances of TextView in your XML with the fully qualified class name. Declare your custom namespace just like you would the Android namespace. Note that the "typefaceAsset" should point to a .ttf or .ttc file contained in your /assets directory.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.FontText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is a custom font text"
custom:typefaceAsset="fonts/AvenirNext-Regular.ttf"/>
</RelativeLayout>
Make sure your "super.onCreate(savedInstanceState)" is in the first line.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
}
If you put the lines in the wrong order. Ex:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
setContentView(R.layout.activity);
super.onCreate(savedInstanceState);
}
... then Android Studio preview will show the font correctly but in the Emulator/device it will fail.
It happened with me also, I was using an huawei honor 7c device there I have selected a different font for my entire phone. So that's why it was not reflecting in my real device
So try setting the default font from the phone settings and see it should work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With