Make a Custom ListView row (with clickable buttons in it) selectable using a custom CursorAdapter

It happens that sometimes you are making an interactive app not using buit-in classes but your own custom classes to have better and prettier interface. For that you often end up creating a custom list view that inflates layout (for a single row) from a separate XML file. But what if you want to make each row as well as items with in that row clickable separately? Many of new developers and beginners encounter bugs and are not able to achieve it without hassle.

Worry not! For you have landed on the right place where you can brush of that issue like a dirt.

CUSTOM ADAPTER TO INFLATE MY CUSTOM LISTVIEW

package com.ssa.what2do;
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
public class CustomAdapter extends BaseAdapter {
private LayoutInflater _inflater;
private List<Note> items; // the list of items to be displayed
private Context _context;
private int _position;
public CustomAdapter(Context context, List<Note> notes){
 _inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 this.items = notes;
 _context  = context;
 }
// Number of items in a collection
 public int getCount() {
 // TODO Auto-generated method stub
 return items.size();
 }
// Item at a specific location
 public Object getItem(int position) {
 // TODO Auto-generated method stub
 return null;
 }
public long getItemId(int position) {
 // TODO Auto-generated method stub
 return position;
 }
public View getView(int position, View convertView, ViewGroup parent) {
 // TODO Auto-generated method stub
 View row = _inflater.inflate(R.layout.list_notes, parent, false);
 // make/get id's of text view and button views for the items
 _position = position;
TextView txtDate = (TextView) row.findViewById(R.id.txt_datetime);
 TextView txtNote = (TextView) row.findViewById(R.id.txt_note);
 ImageButton btnDelete = (ImageButton) row.findViewById(R.id.btn_del_note);
txtDate.setText(items.get(position).getTimstamp());
 txtNote.setText(items.get(position).getDescription());
 btnDelete.setTag(items.get(position).getId());
btnDelete.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
 Log.e("custom adapter", "on btnDelete click");
 // TODO Auto-generated method stub
 if(v.getId() == R.id.btn_del_note){
 Log.e(
 "Delete a record: ",
 "Item Id: "+v.getTag().toString()+
 " position: "+_position+
 " Item id in the array: "+items.get(_position).getId()
 );
// call the function and delete the note from db
 DBHelper dbhelper = new DBHelper(_context);
 dbhelper.opendb();
 dbhelper.deleteNote(v.getTag().toString());
 dbhelper.closedb();
// notify
 Toast.makeText(_context, "The note has been deleted!", Toast.LENGTH_SHORT).show();
// refresh screen
 int i = 0;
 while(i < items.size()){
 if(items.get(i).getId() == v.getTag().toString()){
 items.remove(i);
 }
 ++i;
 }
 notifyDataSetChanged();
}
 }
 });
 return row;
 }
}

YOUR MAIN ACTIVITY IN WHICH YOU WANT TO DISPLAY THE LIST

package com.ssa.what2do;
import java.util.List;
import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.media.MediaPlayer;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.Display;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.WindowManager;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.Toast;
public class ViewNotes extends Activity implements OnClickListener {
private MediaPlayer click;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 // TODO Auto-generated method stub
 super.onCreate(savedInstanceState);
 setContentView(R.layout.viewnotes);
// set layout according to screen height (and width if needed)
 // get screen height
 // compute pixels
 // set margin
 Display display = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
 int height =  display.getHeight()/2;
Log.e("CenterY: ", String.valueOf(height));
 Log.e("Height: ", String.valueOf(height*2));
ImageView bg_view = (ImageView) findViewById(R.id.bg_view);
 Log.e("Width BOARD: ", String.valueOf(bg_view.getWidth()));
 Log.e("Height BOARD: ", String.valueOf(bg_view.getHeight()));
click = MediaPlayer.create(this, R.raw.btnclick);
ImageView addbtn = (ImageView) findViewById(R.id.addnotebtn);
 addbtn.setOnClickListener(this);
ListView list = (ListView) findViewById(R.id.list);
 try{
 // get all the notes from database
 DBHelper dbhelper = new DBHelper(this);
 dbhelper.opendb();
 List<Note> notes = dbhelper.getAllNotes();
 dbhelper.closedb();
 if(!notes.equals(null)){
 list.setAdapter(new CustomAdapter(this, notes));
 Log.e("Row Item Clicked","before listener");
 list.setOnItemClickListener(new OnItemClickListener() {
 public void onItemClick(AdapterView<?> parentAdapter, View row,    int position, long rowid) {
 Log.e("Row Item Clicked", String.valueOf(position));
 // TODO Auto-generated method stub
 Log.e("OnItemSelect", parentAdapter.getChildAt(position).findViewById(R.id.btn_del_note).getTag().toString());
 ImageButton btnDelete = (ImageButton) row.findViewById(R.id.btn_del_note);
 Intent intent  = new Intent(ViewNotes.this, EditNotes.class);
 intent.putExtra("noteid", (Integer) btnDelete.getTag());
 startActivity(intent);
 finish();
 }
 });
 }
 else{
 notes.clear();
 notes = null;
 }
 }catch (Exception e) {
 // TODO: handle exception
 Toast.makeText(this, "The drectory is empty. Add new Notes", Toast.LENGTH_SHORT ).show();
 }/*finally{
 startActivity(new Intent(ViewNotes.this,MainMenu.class));
 this.finish();
 }*/
 }
public void onClick(View v) {
 click.start();
 // TODO Auto-generated method stub
 if(v.getId() == R.id.addnotebtn){
 startActivity(new Intent(ViewNotes.this, AddNotes.class));
 finish();
 }
 }
@Override
 public void onBackPressed() {
 // TODO Auto-generated method stub
 super.onBackPressed();
 }
 }

YOUR XML FOR CUSTOM ROW OF YOUR (CUSTOM) LISTVIEW

<?xml version="1.0" encoding="utf-8"?>
 <FrameLayout  xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_height="wrap_content"
 android:layout_width="fill_parent"
 android:id="@+id/listrow"
 android:descendantFocusability="blocksDescendants">
<ImageView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:adjustViewBounds="true"
 android:background="@drawable/note_add"
 android:contentDescription="@string/txt_title" android:src="@null" />
<LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="vertical"
 android:layout_gravity="center_horizontal">
<TextView android:id="@+id/txt_datetime" android:layout_width="wrap_content"
 android:layout_height="wrap_content" android:contentDescription="@string/txt_title"
 android:text="@string/txt_title" android:layout_marginRight="30dp"
 android:layout_marginTop="23dp" android:textColor="#000000"
 android:textSize="15sp" android:layout_gravity="right|top" />
<TextView android:id="@+id/txt_note" android:layout_width="200dp" android:textColor="#000000"
 android:layout_height="wrap_content" android:contentDescription="@string/txt_title"
 android:text="@string/txt_title" android:layout_marginLeft="70dp" android:paddingRight="20dp"
 android:textSize="15sp" android:layout_gravity="left|center"
 android:maxLines="2"/>
<ImageButton android:id="@+id/btn_del_note"
 android:layout_width="wrap_content" android:layout_height="wrap_content"
 android:background="@null" android:src="@android:drawable/ic_delete"
 android:contentDescription="@string/btn_delete"
 android:layout_gravity="right|bottom" android:adjustViewBounds="true"
 android:layout_marginRight="30dp"  android:layout_marginTop="5dp"/>
</LinearLayout></FrameLayout>

YOUR MAIN XML TO DISPLAY THAT CUSTOM LISTVIEW

<?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@drawable/bg"
 android:orientation="vertical" >
<ImageView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:layout_centerInParent="true"
 android:id="@+id/bg_view"
 android:contentDescription="@string/txt_title"
 android:src="@drawable/notes_view_background" />
<LinearLayout
 android:id="@+id/layout_viewnotes"
 android:layout_marginTop="15dp"
 android:layout_width="fill_parent"
 android:layout_height="350dp"
 android:orientation="vertical" >
<LinearLayout
 android:id="@+id/menutabs"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginTop="0dp"
 android:gravity="center_horizontal"
 android:orientation="horizontal" >
<ImageView
 android:id="@+id/tab_today"
 android:layout_width="70dp"
 android:layout_height="20dp"
 android:layout_marginTop="6dp"
 android:contentDescription="@string/txt_title"
 android:src="@drawable/today_t" />
<ImageView
 android:id="@+id/tab_notes"
 android:layout_width="90dp"
 android:layout_height="30dp"
 android:contentDescription="@string/txt_title"
 android:src="@drawable/notes_t" />
<ImageView
 android:id="@+id/tab_new"
 android:layout_width="70dp"
 android:layout_height="20dp"
 android:layout_marginTop="6dp"
 android:contentDescription="@string/txt_title"
 android:src="@drawable/add_new_t" />
<ImageView
 android:id="@+id/tab_cal"
 android:layout_width="70dp"
 android:layout_height="20dp"
 android:layout_marginTop="6dp"
 android:contentDescription="@string/txt_title"
 android:src="@drawable/calendar_t" />
 </LinearLayout>
<ImageView
 android:id="@+id/addnotebtn"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:padding="20dp"
 android:contentDescription="@string/txt_title"
 android:src="@drawable/note_btn_add"
 android:layout_gravity="right" />
<ListView
 android:id="@+id/list"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:layout_marginTop="0dp"
 android:padding="20dp"
 android:paddingBottom="0dp"
 android:divider="@null"
 android:headerDividersEnabled="false"
 android:footerDividersEnabled="false"
 android:focusableInTouchMode="false"
 android:focusable="false"
 android:background="@null"
 android:scrollbars="none"
 android:cacheColorHint="#00000000"
 android:smoothScrollbar="true">
 </ListView>
 </LinearLayout></RelativeLayout>
Advertisements

One thought on “Make a Custom ListView row (with clickable buttons in it) selectable using a custom CursorAdapter

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s