将XML文件设置为自定义视图?

时间:2013-10-22 21:12:39

标签: android android-view

我有一个自定义表行,我正在制作过程中。我想使用XML文件来定义单行的样子。我想有一个类扩展TableRow并将自己定义为XML中定义的文件。 XML文件可能如下所示:

<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingRight="10dp"
        android:text="@string/loading"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="right"
        android:text="@string/loading"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</TableRow>

代码可能如下:

public class SpecialTableRow extends TableRow {

    public SpecialTableRow (Context context) {
        }
}   

我可以在构造函数中使用某些东西让类假设它是完整的tableRow吗?或者,是否有其他结构可以更好地工作?我发现的最好的是:

    TableRow tr=(TableRow) LayoutInflater.from(context).inflate(R.layout.text_pair,null);
    TextView mFieldName=(TextView) tr.findViewById(R.id.label);
    TextView mValue=(TextView) tr.findViewById(R.id.data);
    tr.removeAllViewsInLayout();
    addView(mFieldName);
    addView(mValue);

但这会从XML中删除布局参数。还有什么更好的吗?

3 个答案:

答案 0 :(得分:1)

查看creating custom views上的教程。您将希望子类化TableRow并添加要显示的其他视图。然后,您可以直接在XML布局中使用新视图,并另外创建您可能需要的任何自定义属性。我已经包含了一个创建名为TextPairRow的自定义TableRow的示例,使用两个TextView展开布局以在TableRow中显示,并添加showLabel和showData自定义属性,这些属性显示/隐藏两个TextView。最后,我已经介绍了如何直接在XML布局中使用新视图。

class TextPairRow extends TableRow {

    private TextView label, data;

     public TextPairRow (Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.getTheme().obtainStyledAttributes(
                                           attrs,
                                           R.styleable.TextPairRow, 0, 0);

        try {
            showLabel = a.getBoolean(R.styleable.TextPairRow_showLabel, false);
            showData = a.getBoolean(R.styleable.TextPairRow_showData, false);
        } finally {
            a.recycle();
        }

        initViews();
    }

    private void initViews(){

       // Here you can inflate whatever you want to be in your 
       // view or add views programatically.
       // In this example, we'll just assume you have a basic XML 
       // layout which defines a LinearLayout with two TextViews.
       LinearLayout mLayout = (LinearLayout) 
           LayoutInflater.from(getContext()).inflate(R.layout.textview_layout, this);

       label = (TextView) mLayout.findViewById(R.id.label);
       data = (TextView) mLayout.findViewById(R.id.data);

       if(showLabel)
           label.setVisibility(View.VISIBLE);
       else
           label.setVisibility(View.GONE); // can also use View.INVISIBLE 
                                           // depending on your needs

       if(showData){
           data.setVisibility(View.VISIBLE);
       else
           data.setVisibility(View.GONE); // can also use View.INVISIBLE 
                                           // depending on your needs
    }
}

这是您定义自定义XML属性的位置(找到或创建此文件:res / values / attrs.xml)

<resources>
   <declare-styleable name="TextPairRow">
       <attr name="showText" format="boolean" />
       <attr name="showLabel" format="boolean" />
   </declare-styleable>
</resources>

最后,直接在XML布局中使用新视图:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto">
 <com.thefull.packageforyourview.TextPairRow    
     android:orientation="horizontal"
     custom:showData="true"
     custom:showLabel="true" />
</LinearLayout>

请注意,您可能需要使用xmlns:custom="http://schemas.android.com/apk/res/com.thefull.packageforyourview",具体取决于您的自定义视图是否位于库项目中。无论如何,这个或示例中的内容都可行。

答案 1 :(得分:0)

我唯一能想到的是使用静态方法而不是构造函数。例如:

public static void newInstance (Context context) {
    this = context.getLayoutInflater().inflate(R.layout.text_pair, null, null);
}

然后不要使用构造函数初始化对象,调用此方法。

答案 2 :(得分:0)

这样做的真正诀窍实际上非常简单。使用inflate方法的第二个参数。事实上,最好的办法是:

LayoutInflater.from(context).inflate(R.layout.text_pair,this);

这将使R.layout.text_pair膨胀到此,有效地使用整行。无需手动添加视图,Android会为您处理。