【问题标题】:Android: How to custom-declare XML namespace in styles.xml?Android:如何在styles.xml 中自定义声明XML 命名空间?
【发布时间】:2015-06-03 22:52:55
【问题描述】:

我正在尝试将自定义 XML 命名空间放在 styles.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:

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

【问题讨论】:

    标签: android xml android-layout layout android-styles


    【解决方案1】:

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

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

    我也强烈推荐阅读this

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 正确答案。
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        您不需要任何前缀,没有它们也能正常工作。这是我的一个项目的代码,效果很好

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

        【讨论】:

          【解决方案5】:

          我已经完成了自定义字体的下一步 自定义文本视图

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

          然后在我创建的值中 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" 
          

          【讨论】:

            【解决方案6】:
            <?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>
            

            【讨论】:

              【解决方案7】:

              快速解决方案通过代码!

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

              【讨论】:

                【解决方案8】:

                自定义属性使用&lt;declare-styleable&gt;标签定义;通常该文件称为 attrs.xml。命名空间声明将包含您应用的包名称。

                整个过程描述在这里:Creating a View Class | Android Developers

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-03-31
                  • 2012-05-13
                  • 1970-01-01
                  • 2011-01-27
                  • 2023-03-17
                  • 1970-01-01
                  相关资源
                  最近更新 更多