自定义视图样式,Android属性被忽略

15

我创建了一个自定义组合视图 - 视图加载,没有崩溃,一切都很顺利。

现在,我计划在我的应用程序中多次使用此视图,因此该视图需要一个样式。

我在attr.xml文件中为它声明了一个可定制的样式。

  <declare-styleable name="MyCustomView">

        <attr name="ff_label" format="string" />
        <attr name="ff_fieldText" format="string" />
    </declare-styleable>
    
    <declare-styleable name="MyCustomViewStyle">
        <attr name="customViewStyle" format="reference" />
    </declare-styleable>

然后我进入我的主题文件,写下了以下内容

<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">

    <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    //bunch of other stuff
    <item name="customViewStyle">@style/customViewStyle</item>
</style>

然后在我的Android清单中声明

<application
        android:name="com.my.app.App"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

然后在我的styles.xml文件中写入:

   <style name="customViewStyleStyle" parent="@android:style/Widget.EditText">
        <item name="android:paddingBottom">@dimen/space_between_adjacent_widgets_vertical</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="ff_label">@string/default_label_text</item>
        <item name="ff_fieldText">@string/default_label_text</item>
    </style>

我的问题:我的自定义属性完全被识别了。
为什么标记为"android:..."的属性会被忽略?

MyCustomView.java

public MyCustomView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initAttributes(context, attrs, R.attr.customViewStyle);
}

public MyCustomView(Context context) {
    super(context);
    initAttributes(context, null, R.attr.customViewStyle);
}

private void initAttributes(Context context, AttributeSet attrs, int defStyle) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.custom_view, this, true);
    label = (TextView) findViewById(R.id.label);
    formField = (EditText) findViewById(R.id.formField);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle,0);

    if (a.hasValue(R.styleable.MyCustomView_ff_label)) {
        labelText = a.getString(R.styleable.MyCustomView_ff_label);
        label.setText(labelText);
    }

    
    if (a.hasValue(R.styleable.MyCustomView_ff_fieldText)) {
        fieldText = a.getString(R.styleable.MyCustomView_ff_fieldText);
        field.setHint(fieldText);
    }
    
    
    a.recycle();
}

布局文件.xml

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

    <com.my.app.MyCustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          />

   <com.my.app.MyCustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          />

    <com.my.app.MyCustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          />

    <com.my.app.MyCustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          />

    <com.my.app.MyCustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          />

    <com.my.app.MyCustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          />

    <com.my.app.MyCustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          />

    <com.my.app.MyCustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          />

    <include layout="@layout/layout_set_default" />

</TableLayout>

一个视图的默认高度大约为30dp,我不能使用列表视图。 每个视图之间应该有10dp的填充。


关于在Android中为自定义视图设置样式的文章(http://onetouchcode.com/2016/11/25/styling-custom-views-android/)。 - Shailendra
1个回答

13

您需要像这样更改MyCustomView的代码:

    ...
    public MyCustomView(Context context, AttributeSet attrs) {
            //Called by Android if <com.my.app.MyCustomView/> is in layout xml file without style attribute.
            //So we need to call MyCustomView(Context context, AttributeSet attrs, int defStyle) 
            // with R.attr.customViewStyle. Thus R.attr.customViewStyle is default style for MyCustomView.
            this(context, attrs, R.attr.customViewStyle);
    }

    public MyCustomView(Context context) {
            this(context, null);
    }

    public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
            //Called by Android if <com.my.app.MyCustomView/> is in layout xml with style attribute
            // For example:
            //         <com.my.app.MyCustomView
            //                android:layout_width="match_parent"
            //                android:layout_height="wrap_content"
            //                style="@style/customViewStyleStyle"
            //                />
            //
            super(context, attrs, defStyle);
            initAttributes(context, attrs, defStyle);
    }
    ...

那么您可以在layout.xml中使用样式属性,而customViewStyle也将成为MyCustomView的默认样式。与textViewStyleTextView的默认样式相同。

    <com.my.app.MyCustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/customViewStyleStyle"
      />

之前您拥有这个构造函数:

public MyCustomView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initAttributes(context, attrs, R.attr.customViewStyle);
}

正如您所看到的,您将R.attr.customViewStyle传递给initAttributes()方法,但未将其传递给父构造函数。


我添加了一个主题,并写下了我将主题添加到应用程序中。我写下了“我的自定义”属性被识别。但是被忽略的是“android:bottomPadding”,为什么? - Lena Bru
这篇文章逐步展示了我如何添加主题 - 主题可以正常工作。只是如果我放入自定义样式“normal”安卓属性,它们会被忽略...... - Lena Bru
我特意不想添加样式属性,因为我正在为整个应用程序使用主题,而不仅仅是一个小部件 - 通过主题的自定义样式是被识别的。这不是问题所在。 - Lena Bru
你能解释一下它们的区别吗?我看不出来。但它确实起作用了。 - Lena Bru
我也遇到了这个问题,因为我的边距属性被忽略了,我尝试了你的解决方案,但没有运气。 - Burhan Khanzada
显示剩余5条评论

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