How to create a simple custom View?
Solution 1
may be you could define another constructor method like this:
public MyView(Context context, AttributeSet attrs)
the android framework will try to build the UI with your view from the constructor above.
Solution 2
The Android Developer Guide has a section called Building Custom Components. Unfortunately, the discussion of XML attributes only covers declaring the control inside the layout file and not actually handling the values inside the class initialisation. The steps are as follows:
Declare attributes in 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>
Notice the use of an unqualified name in the declare-styleable tag. Non-standard android attributes like extraInformation need to have their type declared. Tags declared in the superclass will be available in subclasses without having to be redeclared.
Create constructors
Since there are two constructors that use an AttributeSet for initialisation, it is convenient to create a separate initialisation method for the constructors to call.
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 is an autogenerated int[] resource where each element is the ID of an attribute. Attributes are generated for each property in the XML by appending the attribute name to the element name. Attributes can then be retrieved from the TypedArray using various get functions. If the attribute is not defined in the XML, then null is returned. Except, of course, if the return type is a primitive, in which case the second argument is returned.
If you don't want to retrieve all of the attributes, it is possible to create this array manually.The ID for standard android attributes are included in android.R.attr, while attributes for this project are in R.attr.
int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};
Please note that you should not use anything in android.R.styleable, as per this thread it may change in the future. It is still in the documentation as being to view all these constants in the one place is useful.
Use it in a layout files such as layout\main.xml Include the namespace declaration
xmlns:app="http://schemas.android.com/apk/res/com.mycompany.projectname"
in the top level xml element.
<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";
/>
Reference the custom view using the fully qualified name.
Android LabelView Sample
If you want a complete example, look at the android label view sample.
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>
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"/>
This is contained in a LinearLayout with a namespace attribute:
xmlns:app="http://schemas.android.com/apk/res/com.example.android.apis"
Jonas
Passionated Software Developer interested in Distributed Systems
Updated on July 15, 2022Comments
-
Jonas almost 2 years
I would like to create an custom
View
on Android. I have tried to do it as simple as possible and created an almost empty classMyView
and used it in myLinearLayout
but the application fails on start with "Force Close". How can I do a simple customView
? According to Building Custom Components theView
gets the size 100x100 if I don't overrideonMeasure()
.public class MyView extends View { public MyView(Context context) { super(context); } }
And I use it in a
LinearLayout
with:<view class="com.example.MyView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0.0" />
What am I doing wrong?
If I use the constructor that itemon suggest and the corresponding call to the superclass. Then the "Force Close" is gone, but my
LinearLayout
is broken, the components afterMyView
isn't shown.Here is my
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>
-
Jonas over 13 yearsThanks, that's removes the "Force Close" message, but my
LinearLayout
is broken, the component after isn't shown.