Reputation: 8509
In my activity I am displaying a list of data, each row has an edit and delete button. The listeners for these buttons are defined inside the listviews adapter.
I have implemented a custom array adapter:
public class SalesArrayAdapter extends ArrayAdapter<SaleModel> {
private Context context;
private int altColour;
private SaleModel sale;
private int position;
private ArrayList<SaleModel> sales;
private static class ViewHolder{
RelativeLayout container;
TextView tvId;
TextView tvDate;
TextView tvBusNo;
TextView tvDriver;
TextView tvNoOfTrips;
TextView tvTotalExpenditure;
TextView tvTotal;
TextView tvAmountReceived;
TextView tvStatus;
TextView tvReceiptCode;
ImageButton btnEdit;
ImageButton btnRemove;
}
public SalesArrayAdapter(@NonNull Context context, @NonNull ArrayList<SaleModel> sales) {
super(context, R.layout.row_sales, sales);
//this.getContext() = getContext();
//this.sales = sales;
}
@NonNull
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
// Get the data item for this position
sale = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
// If there's no view to re-use, inflate a brand new view for row
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.row_sales, parent, false);
viewHolder.container = (RelativeLayout) convertView.findViewById(R.id.row_sales_ll_container);
viewHolder.tvId = (TextView) convertView.findViewById(R.id.row_sales_tv_id);
viewHolder.tvDate = (TextView) convertView.findViewById(R.id.row_sales_tv_date);
viewHolder.tvDriver = (TextView) convertView.findViewById(R.id.row_sales_tv_driver);
viewHolder.tvNoOfTrips = (TextView) convertView.findViewById(R.id.row_sales_tv_total_no_of_trips);
viewHolder.tvTotalExpenditure = (TextView) convertView.findViewById(R.id.row_sales_tv_total_expenditure);
viewHolder.tvTotal = (TextView) convertView.findViewById(R.id.row_sales_tv_total);
viewHolder.tvAmountReceived = (TextView) convertView.findViewById(R.id.row_sales_tv_amount_received);
viewHolder.tvStatus = (TextView) convertView.findViewById(R.id.row_sales_tv_status);
viewHolder.tvReceiptCode = (TextView) convertView.findViewById(R.id.row_sales_tv_receipt_code);
viewHolder.btnEdit = (ImageButton) convertView.findViewById(R.id.row_sales_btn_edit);
viewHolder.btnRemove = (ImageButton) convertView.findViewById(R.id.row_sales_btn_trash);
// Cache the viewHolder object inside the fresh view
convertView.setTag(viewHolder);
} else {
// View is being recycled, retrieve the viewHolder object from tag
viewHolder = (ViewHolder) convertView.getTag();
}
// Populate the data from the data object via the viewHolder object
// into the template view.
if (altColour == 0) {
viewHolder.container.setBackgroundColor(Color.parseColor("#FFFFFF"));
altColour = 1;
} else {
viewHolder.container.setBackgroundColor(Color.parseColor("#EFEFEF"));
altColour = 0;
}
viewHolder.tvId.setText(String.valueOf(sale.getId()));
viewHolder.tvDate.setText(sale.getDate());
viewHolder.tvDriver.setText(sale.getDriver());
double totalTripsAmount = 0;
for(int c = 0; c < sale.getTrips().length(); c++) {
try {
totalTripsAmount += sale.getTrips().getJSONObject(c).getDouble("trip_amount");
} catch (JSONException e) {
e.printStackTrace();
}
}
viewHolder.tvNoOfTrips.setText("GHS "+totalTripsAmount);
double totalExpenditureAmount = 0;
for(int c = 0; c < sale.getExpenditure().length(); c++) {
try {
totalExpenditureAmount += sale.getExpenditure().getJSONObject(c).getDouble("amount");
} catch (JSONException e) {
e.printStackTrace();
}
}
viewHolder.tvTotalExpenditure.setText("GHS "+totalExpenditureAmount);
viewHolder.tvTotal.setText("GHS "+sale.getTotal());
viewHolder.tvAmountReceived.setText("GHS "+sale.getAmountReceived());
viewHolder.tvStatus.setText(sale.getIsPending() == 1 ? "Pending" : "Complete");
viewHolder.tvReceiptCode.setText(sale.getReceiptCode());
viewHolder.btnEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent editSaleIntent = new Intent(getContext(), EditSaleActivity.class);
editSaleIntent.putExtra("sale", sale.toJson().toString());
((Activity) getContext()).startActivityForResult(editSaleIntent, 800);
}
});
viewHolder.btnRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = new Integer(getPosition(sale));
removeSale(pos);
}
});
// Return the completed view to render on screen
return convertView;
}
private void removeSale(final int position) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Confirm");
builder.setMessage("Are you sure you want to delete?");
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//Log.i("btnYes", "works");
SalesRequest salesRequest = new SalesRequest(getContext());
remove(getItem(position));
notifyDataSetChanged();
salesRequest.remove(getItem(position).getId(), mTrashOnSuccessListener, mTrashOnErrorListener);
}
});
builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Do nothing
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
private Response.Listener<JSONObject> mTrashOnSuccessListener = new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
//
}
};
Response.ErrorListener mTrashOnErrorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Utils.showNetworkResponse(getContext(), error);
}
};
}
Now my issue is when I click the delete or edit button for any item being displayed it always picks the position or id of the last item being display in the listview.
For example if I wanted to delete the second item in the listview with a position of 1 it would pick the last item being displayed with a position of 10.
I've tried soo many things and made soo many changes but nothing has worked so far, this is my final code.
Upvotes: 1
Views: 1864
Reputation: 1672
Try to set the tag for the buttons at each position in the following way, so that when ever a button is clicked you can get back the position using the tag.
@NonNull
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
// Get the data item for this position
sale = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
// If there's no view to re-use, inflate a brand new view for row
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.row_sales, parent, false);
//Fetch other views here .....
viewHolder.btnEdit = (ImageButton) convertView.findViewById(R.id.row_sales_btn_edit);
viewHolder.btnRemove = (ImageButton) convertView.findViewById(R.id.row_sales_btn_trash);
// Cache the viewHolder object inside the fresh view
convertView.setTag(viewHolder);
} else {
// View is being recycled, retrieve the viewHolder object from tag
viewHolder = (ViewHolder) convertView.getTag();
}
//Setting the position as the tag for both buttons
viewHolder.btnRemove.setTag(position);
viewHolder.btnEdit.setTag(position);
Now in click listener..
viewHolder.btnRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Remove the below line
int pos = new Integer(getPosition(sale));
//Use this
int pos = (int)v.getTag();
removeSale(pos);
}
});
Hope, am helpful.
Upvotes: 1
Reputation: 12
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (fileDataVo.isPdf()) {
Intent intent = new Intent(context, PdfActivity.class);
intent.putExtra("position", position);
context.startActivity(intent);
} else if (fileDataVo.isExcel()) {
Intent intent = new Intent(context, ExcelFileActivity.class);
intent.putExtra("position", position);
context.startActivity(intent);
}
else if (fileDataVo.isPpt()) {
Intent intent = new Intent(context, PptActivity.class);
intent.putExtra("position", position);
context.startActivity(intent);
}
}
Upvotes: 0
Reputation: 768
Set the position of each ViewHolder
object as a tag to the buttons and retrieve it using getTag()
when they are clicked.
Something like this needs to be done:
viewHolder.btnEdit.setTag(position)
And inside onClick()
, retrieve the position as viewHolder.btnEdit.getTag()
For using the viewHolder
object inside onClick()
, it must be declared final so you can copy the object as final ViewHolder finalHolder = viewHolder
and do the above with finalHolder
object
Upvotes: 1
Reputation: 4678
You can add a tag in a button. Tag the current position to the button when getView method is called every time. When the button is clicked get the tage of the button and it will return the updated value/position of the button. And do what you want to do with that current position in call back of that button click. Hope that helps Adding more information you have this line of code
viewHolder.btnEdit
this is the edit button . Now you should add a tag to this button using below code. You need to use below code after else clause of Viewholder object initialization.
viewHolder.btnEdit.setTag(position);
And in call back of onclick use below code
button.getTag()
Upvotes: 1