10

我想View在 Android 上创建一个自定义。我试图尽可能简单地做到这一点,并创建了一个几乎空的类MyView并在我的中使用它,LinearLayout但应用程序在“强制关闭”开始时失败。我怎样才能做一个简单的定制View?根据构建自定义组件View如果我不覆盖,则大小为 100x100 onMeasure()

public class MyView extends View {

    public MyView(Context context) {
        super(context);
    }
}

我将它用于LinearLayout

<view
    class="com.example.MyView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0.0" />

我究竟做错了什么?


如果我使用item建议的构造函数和对超类的相应调用。然后“强制关闭”消失了,但我LinearLayout的坏了,之后的组件MyView没有显示。

这是我的main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    >
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0.0"
    android:background="#f00"
    android:text="Hello"
/>
<view
    class="com.example.MyView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0.0"
/>
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0.0"
    android:background="#00f"
    android:text="World"
/>
</LinearLayout>
4

2 回答 2

10

可能你可以像这样定义另一个构造方法:

public MyView(Context context, AttributeSet attrs)

android 框架将尝试使用上面构造函数中的视图构建 UI。

于 2010-12-14T14:31:26.340 回答
10

Android 开发人员指南中有一个名为“构建自定义组件”的部分。不幸的是,XML 属性的讨论只涉及在布局文件中声明控件,而不是实际处理类初始化中的值。步骤如下:

在 values\attrs.xml 中声明属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyCustomView">
        <attr name="android:text"/>
        <attr name="android:textColor"/>            
        <attr name="extraInformation" format="string" />
    </declare-styleable>
</resources>

请注意在 declare-styleable 标记中使用了非限定名称。像 extraInformation 这样的非标准 android 属性需要声明它们的类型。在超类中声明的标签将在子类中可用,而无需重新声明。

创建构造函数

由于有两个使用 AttributeSet 进行初始化的构造函数,因此可以方便地为构造函数创建单独的初始化方法来调用。

private void init(AttributeSet attrs){  
    TypedArray a=getContext().obtainStyledAttributes(attrs,R.styleable.MyCustomView);
    //Use a
    Log.i("test",a.getString(R.styleable.MyCustomView_android_text));
    Log.i("test",""+a.getColor(R.styleable.MyCustomView_android_textColor, Color.BLACK));
    Log.i("test",a.getString(R.styleable.MyCustomView_android_extraInformation));
    //Don't forget this
    a.recycle();
}

R.styleable.MyCustomView 是一个自动生成的 int[] 资源,其中每个元素都是属性的 ID。通过将属性名称附加到元素名称来为 XML 中的每个属性生成属性。然后可以使用各种 get 函数从 TypedArray 中检索属性。如果该属性未在 XML 中定义,则返回 null。当然,除非返回类型是原始类型,在这种情况下返回第二个参数。

如果您不想检索所有属性,可以手动创建此数组。标准android属性的ID包含在android.R.attr中,而该项目的属性在R.attr中。

int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};

请注意,您不应该在 android.R.styleable 中使用任何东西,因为根据这个线程它可能会在未来发生变化。它仍然在文档中,因为在一个地方查看所有这些常量很有用。

在布局文件中使用它,例如 layout\main.xml 包含命名空间声明

xmlns:app="http://schemas.android.com/apk/res/com.mycompany.projectname"

在顶级 xml 元素中。

<com.mycompany.projectname.MyCustomView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    android:text="Test text"
    android:textColor="#FFFFFF"
app:extraInformation="My extra information";
/> 

使用完全限定名称引用自定义视图。

Android 标签视图示例

如果您想要一个完整的示例,请查看 android 标签视图示例。

标签视图.java

TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequences=a.getString(R.styleable.LabelView_text);
attrs.xml

<declare-styleable name="LabelView">
    <attr name="text"format="string"/>
    <attr name="textColor"format="color"/>
    <attr name="textSize"format="dimension"/>
</declare-styleable>

custom_view_1.xml

<com.example.android.apis.view.LabelView
    android:background="@drawable/blue"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    app:text="Blue"app:textSize="20dp"/>

这包含在具有命名空间属性的 LinearLayout 中:

xmlns:app="http://schemas.android.com/apk/res/com.example.android.apis"

于 2012-01-11T14:52:09.797 回答