1

I have a listView where each row consists of a checkBox, TextView and Button. The button is set to GONE. When the user selects the textBox I want the button to become visible. The user will then click this button to remove the row.

I have implemented a listener for the checkBox, which works, but what I cannot work out is how to make sure the appropriate deleteButton is made visible. With my current code a random button is made visible.

What should I do? A point towards a tutorial or a code fragment would be very helpful.

public class DeleteCampaignCustomCursorAdapater extends CursorAdapter {

protected static final String TAG = null;
DatabaseHelper myDbHelper;
protected SQLiteDatabase db;

private final LayoutInflater mInflater;
protected ListView mListView;

TextView merchantNameView;
Button deleteButton;
CheckBox selectForDelete;
//ImageView moveButton;

public DeleteCampaignCustomCursorAdapater(Context context, Cursor c) {
    super(context, c);
    mInflater = LayoutInflater.from(context);
}

@Override
public void bindView(View view, Context context, final Cursor cursor) {

    myDbHelper = new DatabaseHelper(context); //Links to DatabaseHelper class

    merchantNameView = (TextView) view.findViewById(R.id.deleteMerchantNameView);
    deleteButton = (Button) view.findViewById(R.id.deleteButton);
    selectForDelete = (CheckBox) view.findViewById(R.id.deleteCheckBox);
    //moveButton = (ImageView) view.findViewById(R.id.moveButton);

    merchantNameView.setText(cursor.getString(cursor.getColumnIndex("merchantName")));

    final int  rowID = cursor.getInt(cursor.getColumnIndex("_id"));
    //final long rowID = mListView.getSelectedItemId();

    selectForDelete.setOnCheckedChangeListener(new OnCheckedChangeListener()
    {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
        {
            if ( isChecked )
            {
                // perform logic
                deleteButton.setVisibility(0);
            }
            else {
                deleteButton.setVisibility(8);
            }
        }
    });

    //deleteButton.setOnClickListener(new DeleteEntryOnClicklistener(itemID));  
    deleteButton.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {

            if(rowID > 0) {
                //Log.d(TAG, "Button Click. rowID = "+rowID);                   

                myDbHelper.deleteRecordWithID(rowID);
                cursor.requery();
                notifyDataSetChanged();
            }                           
        }
    });     
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    return mInflater.inflate(R.layout.delete_campaign_row_layout, null);
}

}

EDIT

My new code with Barak's advice. The first version worked but once a row was deleted the row below it would be checked once the view refreshed. Now I get a cursorOutOfBoundsException in my getView().

public class DeleteCampaignCustomCursorAdapater extends CursorAdapter {

protected static final String TAG = null;
DatabaseHelper myDbHelper;
protected SQLiteDatabase db;
private final Activity context;

private LayoutInflater mInflater;
protected ListView mListView;

private static Cursor c;
public static int[] checked;

TextView merchantNameView;
Button deleteButton;
CheckBox selectForDelete;
//ImageView moveButton;

public DeleteCampaignCustomCursorAdapater(Context context, Cursor c) {
    super(context, c);
    this.context = (Activity) context;
    mInflater = LayoutInflater.from(context);
    DeleteCampaignCustomCursorAdapater.c = c;
    initializeChecked();
}

@Override
public void bindView(View view, Context context, final Cursor cursor) {

    /*myDbHelper = new DatabaseHelper(context); //Links to DatabaseHelper class

    merchantNameView = (TextView) view.findViewById(R.id.deleteMerchantNameView);
    deleteButton = (Button) view.findViewById(R.id.deleteButton);
    //selectForDelete = (CheckBox) view.findViewById(R.id.deleteCheckBox);
    //moveButton = (ImageView) view.findViewById(R.id.moveButton);

    merchantNameView.setText(cursor.getString(cursor.getColumnIndex("merchantName")));

    final int  rowID = cursor.getInt(cursor.getColumnIndex("_id"));     
    //final long rowID = mListView.getSelectedItemId();

    if (checked[rowID] == 0) {
        selectForDelete.setChecked(false);
    } else {
        selectForDelete.setChecked(true);
    }


    selectForDelete.setOnCheckedChangeListener(new OnCheckedChangeListener()
    {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
        {
            if ( isChecked )
            {
               // Make deleteButton appear 
               RelativeLayout ll = (RelativeLayout) buttonView.getParent();
               deleteButton = (Button) ll.findViewById(R.id.deleteButton);
               checked[rowID] = 1;
               deleteButton.setVisibility(0);
            }
            else {
                //Hide deleteButton
                RelativeLayout ll = (RelativeLayout) buttonView.getParent();
                deleteButton = (Button) ll.findViewById(R.id.deleteButton);
                checked[rowID] = 1;
                deleteButton.setVisibility(8);
            }
        }
    });

    deleteButton.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {

            if(rowID > 0) {
                //Log.d(TAG, "Button Click. rowID = "+rowID);                   

                myDbHelper.deleteRecordWithID(rowID);
                cursor.requery();
                notifyDataSetChanged();
                initializeChecked();  // re-set the checked array
            }                           
        }
    }); */
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    return mInflater.inflate(R.layout.delete_campaign_row_layout, null);
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    myDbHelper = new DatabaseHelper(context); //Links to DatabaseHelper class

    if (convertView == null) {
        mInflater = context.getLayoutInflater();
        convertView = mInflater.inflate(R.layout.delete_campaign_row_layout, null);
    }       

    merchantNameView = (TextView) convertView.findViewById(R.id.deleteMerchantNameView);
    deleteButton = (Button) convertView.findViewById(R.id.deleteButton);
    selectForDelete = (CheckBox) convertView.findViewById(R.id.deleteCheckBox);     

    merchantNameView.setText(c.getString(c.getColumnIndex("merchantName")));

    final int  rowID = c.getInt(c.getColumnIndex("_id"));       
    //final long rowID = mListView.getSelectedItemId();

    if (checked[position] == 0) {
        selectForDelete.setChecked(false);
    } else {
        selectForDelete.setChecked(true);
    }

    selectForDelete.setOnCheckedChangeListener(new OnCheckedChangeListener()
    {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
        {
            if ( isChecked )
            {
               // Make deleteButton appear 
               RelativeLayout ll = (RelativeLayout) buttonView.getParent();
               deleteButton = (Button) ll.findViewById(R.id.deleteButton);
               checked[position] = 1;
               deleteButton.setVisibility(0);
            }
            else {
                //Hide deleteButton
                RelativeLayout ll = (RelativeLayout) buttonView.getParent();
                deleteButton = (Button) ll.findViewById(R.id.deleteButton);
                checked[position] = 1;
                deleteButton.setVisibility(8);
            }
        }
    });

    deleteButton.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {

            if(rowID > 0) {
                //Log.d(TAG, "Button Click. rowID = "+rowID);                   

                myDbHelper.deleteRecordWithID(rowID);
                c.requery();
                notifyDataSetChanged();
                initializeChecked();  // re-set the checked array
            }                           
        }
    });

    return convertView;     
}

public static void initializeChecked() {
    checked = new int[c.getCount()];
    int i = 0;
    while (i < c.getCount()) {
        checked[i] = 0;
        i++;
    }
}

}

Roardog
  • 139
  • 2
  • 11
  • Are you trying to delete the each row individually using the button inside them or delete multiple rows using a common button ? – darsh May 10 '12 at 11:45
  • Delete each row individually from the button inside the row – Roardog May 10 '12 at 22:04
  • This is getting too long, and it's a new issue, and I'm getting confused. How about posting a new question? – Barak May 11 '12 at 14:22
  • New question posted here http://stackoverflow.com/questions/10553389/get-correct-cursor-in-customcursor-adapater-getview – Roardog May 11 '12 at 14:32

2 Answers2

1

You could do this:

selectForDelete.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
    {
        if ( isChecked )
        {
           // perform logic 
           LinearLayout ll = (LinearLayout) buttonView.getparent();
           Button b = (Button) ll.findViewById(R.id.deleteButton)
           b.setVisibility(0);
        }
        else {
           LinearLayout ll = (LinearLayout) buttonView.getparent();
           Button b = (Button) ll.findViewById(R.id.deleteButton)
           b.setVisibility(8);
        }
    }
});

You've checked the box, so you know the row, get the parent of the checkbox (which should be the LinearLayout of the row), then get the button id for that row and use that to set the delete button visibility for that specific row/view.

Hope this helps.

EDIT

To fix your issues on delete you need to do something like follows.

In the custom adapter set an array:

private Cursor c;
public static int[] checked;

In your constructor set your cursor to the local var and call a method:

CursorAdapter_EditText.c = c;
initializeChecked();

The method:

public static void initializeChecked() {
    checked = new int[c.getCount()];
    int i = 0;
    while (i < c.getCount()) {
        checked[i] = 0;
        i++;
    }
}

In your bindview, re-arrange and add a couple lines:

final int  rowID = cursor.getInt(cursor.getColumnIndex("_id"));
selectForDelete = (CheckBox) view.findViewById(R.id.deleteCheckBox);
if (checked(rowID) == 0) {
    selectForDelete.setChecked(false);
} else {
    selectForDelete.setChecked(true);
}

Then in modify my original answer onCheckedChanged like so::

selectForDelete.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
    {
        if ( isChecked )
        {
           // perform logic 
           LinearLayout ll = (LinearLayout) buttonView.getparent();
           Button b = (Button) ll.findViewById(R.id.deleteButton);
           checked[posSelected] = 1;
           b.setVisibility(0);
        }
        else {
           LinearLayout ll = (LinearLayout) buttonView.getparent();
           Button b = (Button) ll.findViewById(R.id.deleteButton);
           checked[posSelected] = 1;
           b.setVisibility(8);
        }
    }
});

Finally in your delete button listener:

deleteButton.setOnClickListener(new OnClickListener(){
    @Override
    public void onClick(View v) {

        if(rowID > 0) {
            //Log.d(TAG, "Button Click. rowID = "+rowID);                   

            myDbHelper.deleteRecordWithID(rowID);
            cursor.requery();
            notifyDataSetChanged();
            initializeChecked();  // re-set the checked array
        }                           
    }
}); 
Barak
  • 16,318
  • 9
  • 52
  • 84
  • Thanks! That worked really well and I didn't have to create a getView() method, just put that in my bindView(). – Roardog May 11 '12 at 07:31
  • Thanks! That worked really well and I didn't have to create a getView() method, just put that in my bindView(). Slight glitch, when a row is deleted and the view refreshes, the row below the delete one now has it's check box ticked and delete button showing. – Roardog May 11 '12 at 08:58
  • Updated my answer to help you handle the after delete issue. – Barak May 11 '12 at 12:13
  • Thanks Barak, but a couple of questions... 1. What is `CursorAdapter_EditText.c = c;`, it gives me an error in my code but I'm not sure what it's name is supposed to be 2. In my checkBox checked listener, where do I get `posSelected` from? – Roardog May 11 '12 at 12:59
  • Doh, sorry, I was copying pasting from another answer I gave. The first one should be `DeleteCampaignCustomCursorAdapater.c = c;` and `posSelected` should be `rowID` if I've got my head on right. – Barak May 11 '12 at 13:07
  • Thanks for clearing that up Barak. When I run the code however I get an ArrayIndexOutOfBoundsException at `if (checked[rowID] == 0) {`. New code posted above. – Roardog May 11 '12 at 13:10
  • Ugh... I wasn't paying close enough attention... that's the **DB** rowID and has no relation to the adapter position! What you need in there is the position in the adapter for the current row... – Barak May 11 '12 at 13:23
  • I think it has to do with the fact that rowID is an auto incremented row identifier imported from the database and does not necessarily match the position of the row that was clicked. i.e. the rowID of the campaign in position 1 in the list might not be 1, it could be 2 or 3, etc, if the user deleted the previous campaigns that occupied row's 1, 2, etc in the database – Roardog May 11 '12 at 13:24
  • Should I shift all this to a getView() method as it provides the `position`? – Roardog May 11 '12 at 13:29
  • I've been looking around the next and tried a couple of experiments, and I believe that switching to getView() would be the best option. – Barak May 11 '12 at 13:38
  • Should I move everything from my `bindView()` to a `getView()`? – Roardog May 11 '12 at 13:50
  • I believe so, and don't forget to change those `checked[rowID]` to `checked[position]`. – Barak May 11 '12 at 14:00
  • Have changed to a `getView()` but can't get the right cursor. Keep getting _cursorOutOfBoundsExceptions_. Have updated my code above. – Roardog May 11 '12 at 14:21
0

check this link what you have to do is you have to save your buttons state in an arraylist and then display your buttons from that arraylist instead of directly setting it as visible if you are unable to understand the code on link then i will try to write code for you let me know you have understand or not...

How to implement a button that gets all checkbox's state and adds the value of checked item into arraylist?

I dont know exactly but it should work if problem is similar..

Community
  • 1
  • 1
Bharat Sharma
  • 3,926
  • 2
  • 17
  • 29
  • Thanks for the link. My first question though is you get position from getView(). Can I have this alongside my bindView() or should it replace it? – Roardog May 10 '12 at 12:20
  • it will be better if you place your click listener in getView() so that you need not to manage position of buttons in someother way. It is callback function so it can work anywhere... – Bharat Sharma May 10 '12 at 12:32