1

I'm trying to delete an item from a listview, but there is a problem..i'm using a fragment and I don't know how to get the "delete image button" to add a onClickListener... That's my xml of the delete button which is in payment_list_view.xml :

<ImageButton
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/trash_icon"
            android:padding="10dp"
            android:id="@+id/delete_payment_btn"
            android:background="@android:color/white" />

Then, I have my PaymentFragment which contains my listview:

 package com.nicola.baccillieri.splitpayment;




public class PaymentFragment extends Fragment {

private String descString;
private int price;
private String payedBy;
private ArrayList<String> descPayArray;
private ArrayList<Integer> priceArray;
private ArrayList<String> payedByArray;
int trash;
PaymentAdapter customAdapter;
private final static String SHARED_PREFS = "sharedPrefs";
FirebaseFirestore db;



@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    db = FirebaseFirestore.getInstance();
    trash = (R.drawable.trash_icon);
    descPayArray = new ArrayList<>();
    priceArray = new ArrayList<>();
    payedByArray = new ArrayList<>();


}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {


    final View rootView=inflater.inflate(R.layout.payments_fragment,container,false);

    ProgressBar detailsPb = rootView.findViewById(R.id.details_pb);
    detailsPb.getIndeterminateDrawable().setColorFilter(0XFF3F51B5,
            PorterDuff.Mode.MULTIPLY);
    detailsPb.setVisibility(View.VISIBLE);

    final ListView listView = rootView.findViewById(R.id.paymentLv);
    String email = getEmail();
    String groupName = getActivity().getIntent().getStringExtra("title");

    DocumentReference docRef = db.collection("users").document(email).collection("Group").document(groupName);

    docRef.collection("Payments")
            .get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                    for (QueryDocumentSnapshot document : queryDocumentSnapshots) {

                        //Extracting payment description from each document

                        descString = document.getId();
                        descPayArray.add(descString);

                        //Extracting cost and who payed from each document

                        price = document.getLong("cost").intValue();
                        priceArray.add(price);

                        payedBy = document.getString("payed by");
                        payedByArray.add(payedBy);
                        trash = R.drawable.trash_icon;
                        customAdapter = new PaymentAdapter(getActivity(), descPayArray, payedByArray, priceArray, trash);
                        listView.setAdapter(customAdapter);
                        ProgressBar detailsPb =  rootView.findViewById(R.id.details_pb);
                        detailsPb.setVisibility(View.GONE);
  // That's the line that cause the error
                        ImageButton deleteBtn = rootView.findViewById(R.id.delete_payment_btn);
                        deleteBtn.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                String groupName = getActivity().getIntent().getStringExtra("title");
                                int positionToRemove = (int) v.getTag();
                                String email = getEmail();
                                String paymentToRemove = descPayArray.get(positionToRemove);
                                DocumentReference docRef = db.collection("users").document(email).collection("Group").document(groupName).collection("Payments").document(paymentToRemove);
                                docRef.delete();

                                descPayArray.remove(positionToRemove);
                                customAdapter.notifyDataSetChanged();
                            }
                        });

                    }
                    // If there isn't any payment display a blank activity
                    ProgressBar detailsPb =  rootView.findViewById(R.id.details_pb);
                    detailsPb.setVisibility(View.GONE);


                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    ProgressBar detailsPb =  rootView.findViewById(R.id.details_pb);
                    detailsPb.setVisibility(View.GONE);
                    Toast.makeText(getContext(), "Failed to load payments", Toast.LENGTH_LONG).show();
                }
            });



    return rootView;

}


public String getEmail() {

    SharedPreferences sharedPreferences = this.getActivity().getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
    String email = (sharedPreferences.getString("email", ""));
    return email;
}}

and finally the file group_detail_activity.xml contains my 2 fragment with a tab layout. Now, the app crash when It has to show the PaymentFragment, because ImageButton deleteBtn = rootView.findViewById(R.id.delete_payment_btn); says

`java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageButton.setOnClickListener(android.view.View$OnClickListener)' on a null object reference".

That's because my rootView contains payment_fragment.xml, and not the payment_list_view.xml. So It doesn't find the button. I've tryed to add final View rootListView=inflater.inflate(R.layout.payment_list_view,container,false); and then it shows the list view, but when I click on the delete button, it doesn't do anything. What should I do?

That's the fragment with the listview:

That's my PaymentAdapter:

package com.nicola.baccillieri.splitpayment;


public class PaymentAdapter extends BaseAdapter {

private Context context;
private ArrayList<String> payDesc;
private ArrayList<String> payedBy;
private ArrayList<Integer> price;
private int trash;
LayoutInflater inflater;


public PaymentAdapter(Context context, ArrayList<String> payDesc, ArrayList<String> payedBy, ArrayList<Integer> price, int trash) {
    this.context = context;
    this.payDesc = payDesc;
    this.payedBy = payedBy;
    this.price = price;
    this.trash = trash;
    inflater = (LayoutInflater.from(context));
}

@Override
public int getCount() {
    return payDesc.size();
}

@Override
public Object getItem(int position) {
    return payDesc.get(position);
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    convertView = inflater.inflate(R.layout.payment_list_view, null);

    TextView paymentDesc = convertView.findViewById(R.id.payedDescTv);
    TextView payedByTv = convertView.findViewById(R.id.payedByTv);
    TextView priceTv = convertView.findViewById(R.id.priceTv);
    ImageButton trashIcon = convertView.findViewById(R.id.delete_payment_btn);

    paymentDesc.setText(payDesc.get(position));
    payedByTv.setText("Payed by " + payedBy.get(position));
    priceTv.setText(String.valueOf(price.get(position)) + "€");
    trashIcon.setImageResource(trash);
    trashIcon.setTag(position);

    return convertView;
}}

The problem is that I need to delete the item both from the listview and from firebase...so I need the getEmail() method e the getExtra which is in PaymentFragment..If i put the listener on the adapter, how can I delete o Firebase?

Nicola
  • 301
  • 3
  • 20
  • is your `delete_payment_btn` in a fragment? – Vladyslav Matviienko Dec 03 '18 at 10:27
  • The listview which contains the delete_payment_btn is in the fragment – Nicola Dec 03 '18 at 10:30
  • you can't delete this way. you have to click on list item (the item you want to delete) – Ali Ahmed Dec 03 '18 at 10:31
  • Can you attach the display of the UI? or send the complete XML file of the fragment? – Abdul-Aziz-Niazi Dec 03 '18 at 10:32
  • if the button is in the listVIew, then add the listener in the ListView Adapter – Vladyslav Matviienko Dec 03 '18 at 10:32
  • @VladyslavMatviienko can you tell me how to do that? – Nicola Dec 03 '18 at 10:36
  • Possible duplicate of [Android RecyclerView addition & removal of items](https://stackoverflow.com/questions/26076965/android-recyclerview-addition-removal-of-items) – Muahmmad Tayyib Dec 03 '18 at 10:37
  • in your `PaymentAdapter` 's `getView` method – Vladyslav Matviienko Dec 03 '18 at 10:38
  • I've added a picture of my fragment – Nicola Dec 03 '18 at 10:38
  • by your code what i've realized is that you might be referencing/initiating your button at wrong place... your delete button layout is inflated in your CustomAdapter, but what you are referencing here is ImageButton deleteBtn = rootView.findViewById(R.id.delete_payment_btn); that is referencing that view is on the fragment layout... that's why you are getting Null pointer Execption – Muahmmad Tayyib Dec 03 '18 at 10:59
  • POST your adapter code. – Ali Ahmed Dec 03 '18 at 10:59
  • I add my adapter code – Nicola Dec 03 '18 at 12:27
  • @MuahmmadTayyib yes, infact I need to get the Id of the button wich is in another xml file..How can I do that? – Nicola Dec 03 '18 at 13:03
  • @VladyslavMatviienko I've tried your method and it works..the problem is that after I delete the list item, I need also to delete the item on my firebase db. And I can call any method from the adapter which is inside the PaymentFragment..Is there anyway to "import" the listview into the PaymentFragment, so I can get the delete button? My view inside Payment adapter is " View rootView=inflater.inflate(R.layout.payments_fragment,container,false);"...so I use payments_fragment.xml. How can I use payment_list_view.xml to get the delete button? The list view obviously is inside the fragment – Nicola Dec 03 '18 at 14:08
  • you should not manipulate a fragment from the adapter directly. You can create your own interface, which will be implemented in Fragment, and you will pass it to the adapter, where yyou will call it when you need to delete something from firebase. And in fragment the implemented interface will delete it – Vladyslav Matviienko Dec 03 '18 at 15:35

4 Answers4

0

Try this way. On list clicked you can delete item

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

            payedByArray.remove(position);
            adapter.notifyItemRemoved(position);

        }
    });

Other way is to put the Delete Button in your payment_list_view and then in Adapter you can get position on that button click and delete it

Ali Ahmed
  • 2,130
  • 1
  • 13
  • 19
  • And I want't to delete the item only if I click on the delete button, not on the entire listview – Nicola Dec 03 '18 at 10:40
0

From Custom_adapater's viewholder get the view id , and you can easily delete the item by using

payedByArray.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, payedByArray.size());

How to delete list item ,a SO's question already answered.. Have a look... that might solve your problem.

Muahmmad Tayyib
  • 689
  • 11
  • 28
0

You can set a listener to link the delete image button action to your fragment. Then can the button is click you trigger the listener and do what your want in your fragment. Yo can send the position to remove the good element

0

Your adapter don't know that list is being modified. you need to provide latest list to adapter after deletion of item.

Make your payedByArray list public in adapter code.

This activity code.

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        payedByArray.remove(position);
        //payedByArray is activity list;
        adapter.payedByArray = payedByArray;
        adapter.notifyItemRemoved(position);
    }
});
Ashish Kudale
  • 1,230
  • 1
  • 27
  • 51