19

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'. 

8 Answers 8

18
+500

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

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

And 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> 

Then styles can be declared:

<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.

Sign up to request clarification or add additional context in comments.

Comments

11

You don't need to add any prefix to reference your custom attributes in the style resource files. Doing it like this will work just fine:

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

1 Comment

Correct answer.
7

The answer is to NOT specify the namespace in the style.

<?xml version="1.0" encoding="utf-8" ?> <resources xmlns:custom="http://schemas.android.com/apk/res/com.custom.project"> <style name="CustomStyle"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> <item name="customAttr">value</item> <!-- tee hee --> </style> </resources> 

Comments

5

You don't need any prefixes, it will work without them. This is code from one of my projects, which works just fine

<style name="defaultTriangle"> <item name="triangleColor">#FF33B5E5</item> <item name="triangleStrokeColor">@android:color/black</item> <item name="triangleStrokeWidth">3dp</item> </style> <si.kseneman.views.Triangle style="@style/defaultTriangle" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" android:padding="10dp" android:rotation="0" /> 

Comments

2

I've done next for custom font CustomTextView

public class KlavikaTextView extends TextView { private final static int KLAVIKA_BOLD = 0; private final static int KLAVIKA_BOLD_ITALIC = 1; private final static int KLAVIKA_LIGHT = 2; private final static int KLAVIKA_LIGHT_ITALIC = 3; private final static int KLAVIKA_MEDIUM = 4; private final static int KLAVIKA_MEDIUM_ITALIC = 5; private final static int KLAVIKA_REGULAR = 6; private final static int KLAVIKA_REGULAR_ITALIC = 7; public KlavikaTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); parseAttributes(context, attrs); } public KlavikaTextView(Context context, AttributeSet attrs) { super(context, attrs); parseAttributes(context, attrs); } public KlavikaTextView(Context context) { super(context); } private void parseAttributes(Context context, AttributeSet attrs) { TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.KlavikaTextView); // The value 0 is a default, but shouldn't ever be used since the attr is an enum int typeface = values.getInt(R.styleable.KlavikaTextView_typeface, KLAVIKA_REGULAR); // You can instantiate your typeface anywhere, I would suggest as a // singleton somewhere to avoid unnecessary copies switch (typeface) { case KLAVIKA_BOLD: setTypeface(App.klavikaBold); break; case KLAVIKA_BOLD_ITALIC: setTypeface(App.klavikaBoldItalic); break; case KLAVIKA_LIGHT: setTypeface(App.klavikaLight); break; case KLAVIKA_LIGHT_ITALIC: setTypeface(App.klavikaLightItalic); break; case KLAVIKA_MEDIUM: setTypeface(App.klavikaMedium); break; case KLAVIKA_MEDIUM_ITALIC: setTypeface(App.klavikaMediumItalic); break; case KLAVIKA_REGULAR_ITALIC: setTypeface(App.klavikaRegularItalic); break; case KLAVIKA_REGULAR: default: setTypeface(App.klavikaRegular); break; } }} 

Then in values I've created attr.xml

 <!-- Define the values for the attribute --> <attr name="typeface" format="enum"> <enum name="klavika_bold" value="0" /> <enum name="klavika_bold_italic" value="1" /> <enum name="klavika_light" value="2" /> <enum name="klavika_light_italic" value="3" /> <enum name="klavika_medium" value="4" /> <enum name="klavika_medium_italic" value="5" /> <enum name="klavika_regular" value="6" /> <enum name="klavika_regular_italic" value="7" /> </attr> <!-- Tell Android that the class "KlavikaTextView" can be styled, and which attributes it supports--> <declare-styleable name="KlavikaTextView"> <attr name="typeface" /> </declare-styleable> 

Next created the style

 <style name="TextView.Example"> <item name="typeface">klavika_bold</item> </style> 

This style you can use for your xml Layouts

style="@style/TextView.Example" 

Comments

1
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res/com.my.project"> <style name="my_style"> <item name="custom:tag">some_value</item> </style> </resources> 

you are trying to apply XML namespacing to an attribute value, which won't work. In this case, you should specify the package name directly, like this:

 <style name="my_style"> <item name="com.my.project:tag">some_value</item> </style> 

Comments

1

Fast solution via code!

 String pathFont = "fonts/ReallyCoolFont.ttf"; TextView text = (TextView) findViewById(R.id.TextView1); Typeface fontFace = Typeface.createFromAsset( getAssets(), pathFont ); text.setTypeface( fontFace ); 

Third-party libraries , solve the problem, in XML!

1 - https://github.com/leok7v/android-textview-custom-fonts

2 - https://github.com/ragunathjawahar/android-typeface-textview

My suggestion

You will have other needs, and for each component you will have to customize a class.

Another problem you have other layouts and N TextView components for maintenance you will have a lot of work .

I use this method in projects in the OnCreate of my activity if I need to change the font I have to do this only in the OnCreate method of each activity .

 private static final String FONT = "ReallyCoolFont.ttf"; public static void allTextView(final Context context, final View root) { String fontPath = FONT; try { if (root instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) root; int childCount = viewGroup.getChildCount(); for (int i = 0; i < childCount; i++) allTextView(context, viewGroup.getChildAt(i) ); } else if (root instanceof TextView) ((TextView) root).setTypeface(Typeface.createFromAsset(context.getAssets(), fontPath)); } catch (Exception e) { e.printStackTrace(); } } // call in OnCreate Activity allTextView(this, findViewById(R.layout.main) ); 

Comments

0

The custom attributes are defined using <declare-styleable> tags; usually the file is called attrs.xml. The namespace declaration will have your app's package name in it.

The whole process is described here: Creating a View Class | Android Developers

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.