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

19

我正在尝试在styles.xml中放置自定义XML命名空间,并在布局中继承它。我不知道如何像在布局xml中一样在styles.xml中声明自定义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:

  4. <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>
  • 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'.
    
    8个回答

    18

    你需要在 res 文件夹下的 attr.xml 文件中定义字体的属性:

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

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

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

    然后可以声明样式:

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

    我假设您将字体放在 asset 而不是 asset/fonts 目录中。

    此外,我强烈建议阅读此内容


    11

    在样式资源文件中,您不需要添加任何前缀来引用自定义属性。按照以下方式进行操作即可:

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

    正确答案。 - oxied

    7
    答案是在样式中不要指定命名空间。
    <?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>
    

    5

    你不需要任何前缀,没有前缀也可以正常工作。这是我其中一个项目的代码,它运行良好。

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

    2

    我已经为自定义字体完成了以下步骤: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;
    
        }
    }}
    

    然后在values文件夹中我创建了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>
    

    下一步是创建 样式
      <style name="TextView.Example">
        <item name="typeface">klavika_bold</item>
      </style>
    

    你可以在xml布局中使用这种风格。
    style="@style/TextView.Example" 
    

    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>
    

    你正在尝试将XML命名空间应用于属性值,这是行不通的。在这种情况下,你应该直接指定包名称,如下所示:
     <style name="my_style"> <item name="com.my.project:tag">some_value</item> </style>
    

    1
    快速解决方案,通过编程实现!
     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

    我的建议

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

    另一个问题是您有其他布局和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) );
    

    0
    自定义属性是使用标签定义的;通常文件名为attrs.xml。命名空间声明中将包含您应用程序的包名称。
    整个过程在此处描述:创建视图类 | Android Developers

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接