适配器视图内部的 OnClickListener

OnClickListener Inside Adapter View

在我的 activity 中,我显示了一个数据列表,每一行都有一个编辑和删除按钮。这些按钮的侦听器在列表视图适配器中定义。

我已经实现了自定义数组适配器:

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);
        }
    };

}

现在我的问题是,当我点击任何正在显示的项目的删除或编辑按钮时,它总是选择列表视图中显示的最后一个项目的位置或 ID。

例如,如果我想删除列表视图中位置为 1 的第二个项目,它将选择显示的最后一个位置为 10 的项目。

我尝试了很多东西并做了很多更改,但到目前为止没有任何效果,这是我的最终代码。

您可以在按钮中添加标签。每次调用 getView 方法时,将当前位置标记到按钮上。单击按钮时获取按钮的标签,它将 return 更新后的 value/position 按钮。并在该按钮单击的回调中对当前位置执行您想执行的操作。希望有帮助 添加更多信息 你有这行代码

 viewHolder.btnEdit 

这是编辑按钮。现在你应该使用下面的代码向这个按钮添加一个标签。您需要在 Viewholder 对象初始化的 else 子句之后使用以下代码。

viewHolder.btnEdit.setTag(位置);

并在 onclick 的回调中使用下面的代码

button.getTag()

将每个 ViewHolder 对象的位置设置为按钮的标签,并在单击按钮时使用 getTag() 检索它。 需要做这样的事情: viewHolder.btnEdit.setTag(position)

并在 onClick() 中检索位置 viewHolder.btnEdit.getTag()

要在 onClick() 中使用 viewHolder 对象,必须将其声明为最终对象,以便您可以将对象复制为 final ViewHolder finalHolder = viewHolder 并使用 finalHolder 对象执行上述操作

  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);
                }
            }

尝试按以下方式为每个位置的按钮设置标签,以便在单击按钮时可以使用标签返回位置。

@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);

现在在点击监听器中..

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);
            }

    });

希望,对你有帮助。