Android:如何在styles.xml中自定义声明XML命名空间?

我试图把自定义XML命名空间在styles.xml并inheritance它在布局。 我不知道如何在styles.xml声明自定义XML命名空间,就像我在layout xml中所做的那样(例如xmlns:app="http://schemas.android.com/tools" )。

如何在styles.xml使用自定义XML名称空间?

我拥有的:

  1. 字体资产ReallyCoolFont.ttf保存在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> 

我想要的是:

  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:(1403, 21) No resource found that matches the given name: attr 'app:customFont'. 

Solutions Collecting From Web of "Android:如何在styles.xml中自定义声明XML命名空间?"

1)你需要在res文件夹的attr.xml文件中为你的字体定义一个属性:

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

2)你需要为你的TextView定义自定义样式,在这里我们使用我们定义的属性(myfonts):

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

3)

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

总结你到目前为止:

 <?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)现在你的布局是:

 <?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),你的MyCustomTextView是:

 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(); } } 

我以为你把资产的字体,而不是资产/字体目录。

也强烈推荐阅读。

您不需要添加任何前缀以在样式资源文件中引用您的自定义属性。 这样做会工作得很好:

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

你不需要任何前缀,它将工作没有他们。 这是我的一个项目的代码,工作得很好

 <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" /> 

答案是不要在样式中指定名称空间。

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

我接下来做了自定义字体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; } }} 

然后在我创buildattr.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> 

接下来创build了风格

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

这种风格,你可以使用你的XML布局

 style="@style/TextView.Example" 
 <?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> 

您正在尝试将XML名称空间应用于属性值,这不起作用。 在这种情况下,您应该直接指定包名称,如下所示:

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

通过代码快速解决

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

第三方库 ,用XML解决问题!

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

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

我的build议

您将有其他需求,并且对于每个组件,您将不得不自定义一个类。

另一个问题你有其他布局和N个TextView 组件进行维护,你将会有很多的工作。

我在我的活动的OnCreate项目中使用这种方法,如果我需要更改字体,我只能在每个活动的OnCreate方法做这个。

  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) ); 

自定义属性是使用<declare-styleable>标签定义的; 通常该文件被称为attrs.xml。 名称空间声明将在其中包含应用程序的包名称。

整个过程在这里描述: 创build一个View Class | Android开发者