ListView Example 4 – Custom Layout Checkbox, ImageButton, TextView

This is the fourth blog post in series of posts that will demonstrate how Android ListView can be used in your application. We started the series off with the most basic loading of hard coded arraylist in a ListView. In the second post we loaded the data from the Xml file. In the third post, we loaded the listview from an Xml resource file and displayed it as multiple selection checkboxes which user can select and unselect and also save/load their selections.

In this post we will take it one step further and bind the ListView with a custom layout for single row. The single row layout will have a Checkbox, a TextView and an ImageButton to demonstrate how these three can be repeated on each row. We will still load the data from Xml file and save the user selection in Sharedpreferences.

To keep it easy to understand we are still not doing any database operations. We will tackle loading data from Sqlite databse instead of doing it from Xml file in upcoming posts.

Skill Assumptions:

  1. You have configured your Android development environment on Eclipse or other tools
  2. You know how to create a new Android project
  3. You have gone through the example code for the previous posts in the series

What you will learn:

  1. How to load a ListView based on Xml resource file
  2. How to use a custom layout for single row to display CheckBox, TextView and ImageButton for each item in the list and allow user to select multiple items
  3. How to implement a custom Adapter by extending ArrayAdapter and bind a it to the ListView and allow user to select multiple items
  4. How to save user selections to SharedPreferences so that the selected items can be loaded back as checked items when the activity starts again
  5. How to handle onClick event so that selections are saved user clicks on each individual item in ListView

What are we doing in this project:

  1. Create an Activity [Start.java] with layout containing one button
  2. When the button is clicked we will launch another activity [CustomListView.java] that will load the listview from Xml resource file using custom adapter derived from ArrayAdapter that binds with custom layout for single row
  3. When user clicks each item to check the box, we will save the items that are checked in SharedPreferences
  4. When user clicks Clear, we will clear the selection on listview and saved items
  5. When user clicks back button or restarts the application, we will load any previously checked items from the SharedPreferences and set them as checked

Lets jump into the second example.

Step 1 – Create a new Eclipse project

Step 2 - Add a default Activity named Start which will add main.xml under layout folder and Start.java under your namespace folder under src.

Step 3 – In your eclipse project under the res folder create a new subfolder named xml [all lowercase]. Create a new Xml file named todolist.xml in your res/xml folder using your favorite editor with following content pasted in it. Save the file and refresh your res folder in Eclipse. This step is same as second post.

Here is how your folder structure will look like:

// layout/todolist.xml




	
	
	
	

Step 4 – Copy paste following Xml on your main.xml file.

// layout/main.xml






			






		





Step 5 – Copy paste following code in your AndroidManifest.xml file. The most important attribute is to android:theme=”@android:style/Theme.NoTitleBar” which will disable the default Android title bar because we are replacing that with our own Action bar.

Also, notice the additional activity node we have added that registers the activity with Android – activity android:name=”.CustomListView”. We will add the CustomeListView class and related layout in next steps.

// AndroidManifest.xml


    >
        
            
                
                
            
        
        
    
    


Step 6 – Copy and paste following code in your Start.java class file.

// src/Start.java
package com.appfulcrum.blog.examples.listviewcustom;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class Start extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btnSimple = (Button) findViewById(R.id.btnSimple);
        btnSimple.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {

				Toast.makeText(getApplicationContext(),
						" You clicked Custom ListView button", Toast.LENGTH_SHORT).show();

				Intent intent = new Intent(v.getContext(), CustomListView.class);
       		  	startActivityForResult(intent, 0);
			}
		});

    }
}

Step 7 – Add a new Android layout file in your res/layout folder named simple.xml. Then copy and paste following xml in simple.xml file.

// res/layout/simple.xml






			


			
			
		




		


Step 8 – Add a new Android layout file in your res/layout folder named single_item.xml. Then copy and paste following xml in single_item.xml file.

// res/layout/single_item.xml



	
	

		
	

Step 9 – Add a new class file named CustomListView.java to your project in your src folder. Then copy and paste following code in the SimpleListView.java file. Notice the resource id – android.R.layout.single_item.

// src/CustomListView.java

package com.appfulcrum.blog.examples.listviewcustom;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

import org.xmlpull.v1.XmlPullParserException;

import android.app.Activity;
import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;
import android.content.*;
import android.content.res.XmlResourceParser;

public class CustomListView extends ListActivity {

	private ListView mainListView = null;
	CustomToDoListAdapter customTODOAdapter = null;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.simple);

		Button btnClear = (Button) findViewById(R.id.btnClear);
		btnClear.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {

				Toast.makeText(getApplicationContext(),
						" You clicked Clear button", Toast.LENGTH_SHORT).show();
				ClearSelections();

			}
		});

		// Prepare an ArrayList of todo items
		ArrayList listTODO = PrepareListFromXml();

		this.mainListView = getListView();

		mainListView.setCacheColorHint(0);

		// Bind the data with the list
		this.customTODOAdapter = new CustomToDoListAdapter(CustomListView.this,
				R.layout.single_item, listTODO);
		mainListView.setAdapter(this.customTODOAdapter);

		mainListView.setItemsCanFocus(false);
		mainListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

	}

	private void ClearSelections() {

		for (int i = 0; i < this.customTODOAdapter.getCount(); i++) {
			LinearLayout v = (LinearLayout) this.mainListView.getChildAt(i);
			CheckBox chk = (CheckBox) v.getChildAt(0);
			chk.setChecked(false);

		}

		this.customTODOAdapter.ClearSelections();

	}

	private ArrayList PrepareListFromXml() {
		ArrayList todoItems = new ArrayList();
		XmlResourceParser todolistXml = getResources().getXml(R.xml.todolist);

		int eventType = -1;
		while (eventType != XmlResourceParser.END_DOCUMENT) {
			if (eventType == XmlResourceParser.START_TAG) {

				String strNode = todolistXml.getName();
				if (strNode.equals("item")) {
					todoItems.add(todolistXml.getAttributeValue(null, "title"));
				}
			}

			try {
				eventType = todolistXml.next();
			} catch (XmlPullParserException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return todoItems;
	}
}

Step – 10 Add a new class file named CustomToDoListAdapter.java to your project in your src folder. Then copy and paste following code in the CustomToDoListAdapter.java file.

Few important things to notice in this class:

1. It extends ArrayAdapter
2. It implements OnClickListener which we bind with Click event for checkbox within each row
3. It overrides getView method and sets the value for the TextView and state of the CheckBox from the SharedPreferences

// src/CustomToDoListAdapter.java

package com.appfulcrum.blog.examples.listviewcustom;

import java.util.ArrayList;
import java.util.Arrays;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.TextView;

public class CustomToDoListAdapter extends ArrayAdapter implements
		OnClickListener {

	private ArrayList todoItems;
	private Context context;
	private ArrayList selectedItems = new ArrayList();

	final String SETTING_TODOLIST = "todolist";

	public CustomToDoListAdapter(Context context, int textViewResourceId,
			ArrayList dataItems) {
		super(context, textViewResourceId, dataItems);
		this.context = context;
		this.todoItems = dataItems;
		LoadSelections();
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		View v = convertView;
		if (v == null) {
			LayoutInflater inflater = (LayoutInflater) context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			v = inflater.inflate(R.layout.single_item, null);
		}
		String itemText = this.todoItems.get(position);

		TextView bTitle = (TextView) v.findViewById(R.id.txtTitle);
		CheckBox bCheck = (CheckBox) v.findViewById(R.id.bcheck);

		bCheck.setTag(itemText);

		if (this.selectedItems.contains(itemText))
			bCheck.setChecked(true);

		bCheck.setOnClickListener(this);

		bTitle.setText(itemText);
		return (v);
	}

	@Override
	public void onClick(View v) {
		CheckBox cBox = (CheckBox) v;
		String itemText = (String) cBox.getTag();

		Log.d("debug", "message from click listener");
		if (cBox.isChecked()) {
			if (!this.selectedItems.contains(itemText))
				this.selectedItems.add(itemText);
		} else {
			if (this.selectedItems.contains(itemText))
				this.selectedItems.remove(itemText);
		}

		SaveSelections();

	}

	public void ClearSelections() {
		this.selectedItems.clear();
		SaveSelections();
	}

	private String getSavedItems() {
		String savedItems = "";

		for (int i = 0; i < selectedItems.size(); i++) {

			if (savedItems.length() > 0) {
				savedItems += "," + this.selectedItems.get(i);
			} else {
				savedItems += this.selectedItems.get(i);
			}

		}
		return savedItems;
	}

	private void SaveSelections() {

		// save the selections in the shared preference in private mode for the
		// user

		SharedPreferences settingsActivity = this.context.getSharedPreferences(
				SETTING_TODOLIST, android.content.Context.MODE_PRIVATE);

		SharedPreferences.Editor prefEditor = settingsActivity.edit();

		String savedItems = getSavedItems();

		prefEditor.putString(SETTING_TODOLIST, savedItems);

		prefEditor.commit();
	}

	private void LoadSelections() {
		// if the selections were previously saved load them

		SharedPreferences settingsActivity = this.context.getSharedPreferences(
				SETTING_TODOLIST, android.content.Context.MODE_PRIVATE);

		if (settingsActivity.contains(SETTING_TODOLIST)) {
			String savedItems = settingsActivity
					.getString(SETTING_TODOLIST, "");

			this.selectedItems.addAll(Arrays.asList(savedItems.split(",")));

		}
	}

}

Step 11 – Run the application as Android Application and you should see below for output.


Tags: , , , , , , ,

http://downloadpart.com