Android: How to custom-declare XML namespace in styles.xml?

melvynkim picture melvynkim · Mar 30, 2015 · Viewed 9.1k times · Source

I'm trying to put the custom XML namespace in the styles.xml and inherit it in the layout. I don't know how to declare the custom XML namespace in the styles.xml as I do in layout xml (e.g. xmlns:app="http://schemas.android.com/tools").

How do I use custom XML namespace in the styles.xml?

What I have:

  1. The font asset, ReallyCoolFont.ttf is saved in the asset/fonts.

  2. my_layout.xml:

    <TextView
        <!-- more attributes here -->
        app:customFont="fonts/ReallyCoolFont.ttf" 
        <!-- more attributes here -->
    </TextView>
    
  3. styles.xml:

    <style name="CoolTextView">
        <!-- more items here -->
        <!-- more items here -->
    </style>
    

What I'd like to have:

  1. my_layout.xml:

    <TextView
        <!-- more attributes here -->
        style="@style/CoolTextView
        <!-- more attributes here -->
    </TextView>
    
  2. styles.xml:

    <style name="CoolTextView">
        <!-- more items here -->
        <item name="app:customFont">ReallyCoolFont.ttf</item>
        <!-- more items here -->
    </style>
    

Error I get:

Error:(1403, 21) No resource found that matches the given name: attr     'app:customFont'.

Answer

mmlooloo picture mmlooloo · Apr 10, 2015

1) you need to define an attribute for your fonts in attr.xml file in res folder:

<attr name="myfonts" format="string"></attr>

2) you need to define custom style for your TextView and here we use our defined attribute(myfonts):

<declare-styleable name="MyCustomStyle">
    <attr name="myfonts" />
</declare-styleable>

3)

<style name="CoolTextView">
    <item name="myfonts">ReallyCoolFont.ttf</item>
</style>

summary of what you have so far:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="myfonts" format="string">
    </attr>

    <declare-styleable name="MyCustomStyle">
        <attr name="myfonts" />
    </declare-styleable> 

    <style name="CoolTextView">
        <item name="myfonts">ReallyCoolFont.ttf</item>
    </style>

</resources> 

4)Now your layout would be:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.MyCustomTextView
        android:id="@+id/result"
        style="@style/CoolTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="HELLO WORLD!"
        android:textSize="24dp"
        android:gravity="center" >
    </com.example.MyCustomTextView>

</RelativeLayout>

5)and your MyCustomTextView is:

public class MyCustomTextView extends TextView {


    private static final String TAG = "TextView";

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

    public MyCustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        settingFont(context, attrs);
    }

    public MyCustomTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        settingFont(context, attrs);
    }


    private void settingFont(Context ctx, AttributeSet attrs) {
        TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.MyCustomStyle);
        String customFont = a.getString(R.styleable.MyCustomStyle_myfonts);
        Typeface tf = null;
        try {
        tf = Typeface.createFromAsset(ctx.getAssets(), customFont);  
        } catch (Exception e) {
            Log.e(TAG,e.getMessage());
            a.recycle();
            return;
        }

        setTypeface(tf);  
        a.recycle();
    }


}

I assumed you put the font in asset not in asset/fonts directory.

also I highly recommend read this.