I won’t be covering why custom views are important or why you should be using custom views there are many blogs that have done a great job doing that. In this blog, I want just get down to the essentials of what you need to get started writing a custom view.
In part-1, let’s get started with a hello world experiment and no I won’t extend an already existing widget for this example. I get so annoyed when people do that because almost always those examples don’t explain measuring or drawing.
The very first thing to do is your custom view has to extend the View- The building block of very thing android.
In this example, let’s draw a circle.
public class CircleView extends View {
...
}
To extend a view, we have to implement the constructors and we have four options
public CircleView(Context context) {
super(context);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CircleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
So which one do we implement? I have never used the fourth one to date (was added with API 21), so I won’t be covering it. If you are just using the view for your own app and not building a library then you will be fine just implementing the first and second constructors.
That now brings us to the next question. What are the variables in the constructors.
- Context: If you need explanation regard the context, then maybe custom views are not for you just yet.
- AttributeSet: According to google, controlling the view from XML is what separates the poorly written custom view from an exceptional one. AttributeSet lets you do exactly that. I will expand on this topic more in another blog post.
- defStyleAttr: more about this in the next post
So which constructor is called when?
Single-Parameter constructor:
public CircleView(Context context) {
super(context);
}
Called when we are trying to instantiate a view from the code. A typical example would look like the following:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CircleView circleView = new CircleView(this);
... rest of the method implementation.
}
Two-Parameter constructor:
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
Called when we declare a view in the xml and instantiate it through the code. A typical example would look like the following:
<com.srikanth.CircleView
android:id="@+id/customCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /></pre>
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CircleView circleView = findViewById(R.id.customCircle);
... rest of the method implementation.
}
One interesting aspect to note is, when you are declaring the custom view in XML, you have to use the full path to your view. This is how we are telling the compiler where our view is located.