3

I'm dynamically adding/deleting rows, each row has several buttons including a button to delete the row.

Each row represents an item of an ArrayList (I have an ArrayList which is being used to store the list of row data).

When adding each row, I add an onClickListener for the delete button:

private ArrayList<item> ItemList = new ArrayList<>();

void AddRow(item item, int index){
    ItemList.add(item);
    LinearLayout llItem = findViewById(R.id.llItem);
    View rowview = inflater.inflate(R.layout.cardrow, null);
    ImageButton btnDelete = rowview.findViewById(R.id.btnDelete);
    btnDelete.setOnClickListener(new View.OnClickListener(){
        @Override public void onClick(View v){
            list.remove(index); // <--- This is the problem, it is not dynamic
            llItem.removeView((View) v.getParent());
        }
    });
    llItem.addView(rowview, llItem.getChildCount());
}

The list.remove(index) shifts the indices of the lower rows, so that their onClickListeners may not be accurate. For example: if I add 3 rows, click the delete button of the 1st row, then the last row points to an index that is now outofbounds.

What is the best way to fix this and make it dynamic?

Is there some way I can do something like v.getIndex(), to get the real index of the row in the view?

  • Your method name is `AddRow()` but you are removing items. Please show more codes and `listView` adapter code too. – tahsinRupam Apr 22 '18 at 09:44
  • It is not removing any items. Each time AddRow() is called it adds 1 row which can remove itself. The removal code is within the OnClickListener for the delete button of that row. It is working now (adding and removing rows), the only problem is the index mismatch as described which can lead to outofbounds exceptions. –  Apr 22 '18 at 09:49
  • If you are adding views with `linearLayout` why do you need `listView`? What does `listView` contain? It's very confusing. Please show more detailed code. – tahsinRupam Apr 22 '18 at 09:55
  • It will be better if you will use RecyclerView instead of LinearLayout. It will be a lot easier https://stackoverflow.com/questions/26076965/android-recyclerview-addition-removal-of-items?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa – Igor Staszewski Apr 22 '18 at 09:55
  • I don't have any listView, I am using an ExpandableRecyclerView. Each row is dynamic so I am storing the properties of each row in an ArrayList. When the fragment is hidden and shown again, I am using the ArrayList to rebuild all of the rows. My only problem is that I can't keep track of the row index within the OnClickListener. –  Apr 22 '18 at 09:59
  • I think you may have some problem sharing the entire code. Otherwise this piece of code is creating more confusion. I know this seemed to be working until the array Index OutofboundException, but your procedure seems not to be efficient. You can add/delete item from your `recyclerView` adapter. Why are you intended to add views with layout is still a mystry. – tahsinRupam Apr 22 '18 at 10:27
  • The RecyclerViewAdapter seems irrelevant. All it does is call this AddRow() function for each item in the row when the fragment rebuilds the views. I solved the problem by rebuilding the views after each row deletion (and thereby rebuilding the OnClickListeners for each delete button with accurate indices), see my answer. –  Apr 22 '18 at 10:44

1 Answers1

0

Rather than matching the dynamic indices (which seems difficult or impossible from within a static OnClickListener), I remove and rebuild the views when the delete button is clicked. Thus, accurate indices are regenerated immediately after each row deletion.

private ArrayList<item> ItemList = new ArrayList<>();

void AddRow(item item, int index){
    ItemList.add(item);
    LinearLayout llItem = findViewById(R.id.llItem);
    View rowview = inflater.inflate(R.layout.cardrow, null);
    ImageButton btnDelete = rowview.findViewById(R.id.btnDelete);
    btnDelete.setOnClickListener(new View.OnClickListener(){
        @Override public void onClick(View v){
            list.remove(index);
            llItem.removeAllViews(); // <-- remove the views
            for(int i=0;i<item.getSize();i++){ // <-- add the rows again
                AddRow(item, i); // <-- rebuild accurate indices
            }
        }
    });
    llItem.addView(rowview, llItem.getChildCount());
}