如何创建简单的自定义视图?

Jon*_*nas 9 android view custom-view android-linearlayout

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

public class MyView extends View {

    public MyView(Context context) {
        super(context);
    }
}
Run Code Online (Sandbox Code Playgroud)

我用它来LinearLayout:

<view
    class="com.example.MyView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0.0" />
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?


如果我使用itemon建议的构造函数和对超类的相应调用.然后"强制关闭"消失,但我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>
Run Code Online (Sandbox Code Playgroud)

ite*_*mon 9

可能你可以定义另一个构造函数方法,如下所示:

public MyView(Context context, AttributeSet attrs)
Run Code Online (Sandbox Code Playgroud)

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

  • 我不得不重写`onMeasure()`.现在它很棒. (2认同)

小智 9

Android开发人员指南有一个名为Building Custom Components的部分.不幸的是,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>
Run Code Online (Sandbox Code Playgroud)

请注意在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();
}
Run Code Online (Sandbox Code Playgroud)

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};
Run Code Online (Sandbox Code Playgroud)

请注意,您不应该在android.R.styleable中使用任何内容,因为根据此主题,它可能会在将来更改.它仍然在文档中,因为在一个地方查看所有这些常量是有用的.

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

的xmlns:应用= "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";
/> 
Run Code Online (Sandbox Code Playgroud)

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

Android LabelView示例

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

LabelView.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>
Run Code Online (Sandbox Code Playgroud)

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"/>
Run Code Online (Sandbox Code Playgroud)

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

的xmlns:应用= "http://schemas.android.com/apk/res/com.example.android.apis"