Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How To Make a Custom View in Android

DZone's Guide to

How To Make a Custom View in Android

This tutorial shows you how to create a custom view in your Android app to easily give you more control over the appearance and other properties of your app.

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

Android provides you with a bunch of common views and ways to modify them. Sometimes you need to set a few of the same properties on the same types of views throughout your app. In that case, you could make a layout and use the include tag to include it in every layout you need it in, so you can re-use it wherever you need it.

That may be fine, but what if you want to change a property on that view in one place it’s included? For example, you want to change the text color of a TextView inside that layout. Since it’s in the included layout, you can either change it for every place it’s used or you have to do it programmatically. You can’t set it through the include tag.

To solve this problem, you can create a custom view by extending one of the existing views.

Example

To demonstrate this, I created an example custom view. It extends from LinearLayout and has two TextViews inside of it.

public class CustomView extends LinearLayout {

    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setOrientation(LinearLayout.VERTICAL);
        LayoutInflater.from(context).inflate(R.layout.customview, this, true);

        String title;
        String subtitle;
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, 0, 0);

        try {
            title = a.getString(R.styleable.CustomView_customViewTitle);
            subtitle = a.getString(R.styleable.CustomView_customViewSubtitle);
        } finally {
            a.recycle();
        }

        // Throw an exception if required attributes are not set
        if (title == null) {
            throw new RuntimeException("No title provided");
        }
        if (subtitle == null) {
            throw new RuntimeException("No subtitle provided");
        }

        init(title, subtitle);
    }

    // Setup views
    private void init(String title, String subtitle) {
        TextView titleView = (TextView) findViewById(R.id.customview_textview_title);
        TextView subtitleView = (TextView) findViewById(R.id.customview_textview_subtitle);

        titleView.setText(title);
        subtitleView.setText(subtitle);
    }
}


I could have added the TextViews programmatically, but I prefer to have a layout inflated instead. You can see the layout below:

<merge
    xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:id="@+id/customview_textview_title"
        android:textColor="@color/colorPrimary"
        android:textSize="18sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/customview_textview_subtitle"
        android:textColor="@color/colorAccent"
        android:textSize="16sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</merge>


I use the merge tag so the layout can be inflated directly into my view, which is a LinearLayout.

In my CustomView layout, I have TextViews for a title and subtitle. I want to be able to set these in any layout where they are included, so I have to add custom attributes in my attrs.xml file.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="CustomView">
        <attr name="customViewTitle" format="string" />
        <attr name="customViewSubtitle" format="string" />
    </declare-styleable>
</resources>


Now, to actually use this view, I created an example activity which adds my view to its layout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <com.piercezaifman.customview.CustomView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:customViewTitle="My Title"
        app:customViewSubtitle="My Subtitle"/>

    <com.piercezaifman.customview.CustomView
        android:layout_marginLeft="16dp"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:customViewTitle="Other Title"
        app:customViewSubtitle="Other Subtitle"/>

</LinearLayout>


The result looks like this:

example

I had included checks to make sure the title and subtitle were included, throwing an exception otherwise. If they aren’t included, the renderer will not display the views and shows the appropriate exception. For example, if I forgot to set the subtitle, I would see this exception:

error

The standard views provided by Android are usually enough to solve most problems. But if they are lacking or you find you’re often duplicating layouts, consider making a custom view. It may save you some time.

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:
android ,mobile ,mobile apps ,app development ,android views

Published at DZone with permission of Pierce Zaifman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}