简体   繁体   中英

Buttons in ListView each item layout

I have a listview and I am populating that list view from a ArrayList of custom objects. This is the custom adapter code.

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        final int a=position;


        FileHolder holder=null;
        View row = convertView;
        if(row==null)
        {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            row = inflater.inflate(textViewResourceId, parent, false);
            holder=new FileHolder();

            holder.file=files.get(position);
            holder.deleteButton=(ImageButton) row.findViewById(R.id.deleteButton);
            holder.downloadButton=(ImageButton) row.findViewById(R.id.downloadButton);

            holder.deleteButton.setTag(holder.file);
            holder.downloadButton.setTag(holder.file);


            holder.fileName= (TextView) row.findViewById(R.id.fileName);



            holder.fileName.setText(holder.file.getFileName());

        }
        else
        {
            holder=(FileHolder) row.getTag();
        }
        fPOJO=holder.file;
        final AsyncCall call=new AsyncCall();

        holder.downloadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                MODE=0;
                //call.execute(MODE);

            }
        });

        holder.deleteButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Toast.makeText(getContext(), "Delete File "+(String.valueOf(a))+"  "+fPOJO.getFileName(), Toast.LENGTH_LONG).show();
                MODE=1;
                //call.execute(MODE);

            }
        });


        return row;
    }

    public static class FileHolder{
    FilesPOJO file;
    TextView fileName;
    ImageButton downloadButton;
    ImageButton deleteButton;
}

There are two buttons one for file delete and other for file download. I have implemented on click listeners for these two buttons. The problem is when I click any button the fileName in the Toast message is different from the file name that I see on the screen display. For ex: I have 5 files with names

delete.png
upload.png
share.png
referesh.png
copy.png

and now when I click delete button corresponding to referesh.png file the toast pop ups and in that the file name is different than referesh.png.

how to resolve this issue.

EDITS:

This is how I set up this adapter

             FilesAdapter adapter=new FilesAdapter(rootView.getContext(), R.layout.file_list_view_item_row, Application.files);
            View header = (View) View.inflate(rootView.getContext(), R.layout.files_list_view_header_row, null);
            fileListHeading.inflate(rootView.getContext(), R.layout.files_list_view_header_row, null);
            filesListView.addHeaderView(header);
            filesListView.setAdapter(adapter);

I think the problem is with your fPOJO variable when onClick is called it may have different value because after every getView you're changing it's value.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    final int a=position;


    final FileHolder holder;
    View row = convertView;
    if(row==null)
    {
        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        row = inflater.inflate(textViewResourceId, parent, false);
        holder=new FileHolder();

        holder.file=files.get(position);
        holder.deleteButton=(ImageButton) row.findViewById(R.id.deleteButton);
        holder.downloadButton=(ImageButton) row.findViewById(R.id.downloadButton);

        holder.deleteButton.setTag(holder.file);
        holder.downloadButton.setTag(holder.file);


        holder.fileName= (TextView) row.findViewById(R.id.fileName);



        holder.fileName.setText(holder.file.getFileName());

    }
    else
    {
        holder=(FileHolder) row.getTag();
    }

    final AsyncCall call=new AsyncCall();

    holder.downloadButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            MODE=0;
            //call.execute(MODE);

        }
    });

    holder.deleteButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Toast.makeText(getContext(), "Delete File "+(String.valueOf(a))+"  "+holder.fileName, Toast.LENGTH_LONG).show();
            MODE=1;
            //call.execute(MODE);

        }
    });


    return row;
}

Just make holder final and get you're file name from it.

You store your list item in holder, this is your problem, ListView adapter creates as much convertViews as needed to fill the screen so if you have list of 10+ elements, only few will be added to row.

First of all don't store your list element in holder, you gave adapter method called getItem(positoin) to get it.

In your holder view store only references to layout views (TextView, Buttons etc) and (if(row == null) call findViewById on them and setTag.

Then set text, listeners outside the if statement, like so:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    final int a=position;


    FileHolder holder=null;
    View row = convertView;
    if(row==null)
    {
        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        row = inflater.inflate(textViewResourceId, parent, false);
        holder=new FileHolder();

        holder.deleteButton=(ImageButton) row.findViewById(R.id.deleteButton);
        holder.downloadButton=(ImageButton) row.findViewById(R.id.downloadButton);

        holder.fileName= (TextView) row.findViewById(R.id.fileName);

        row.setTag(holder);

    }
    else
    {
        holder=(FileHolder) row.getTag();
    }

    fPOJO= getItem(position);

    final AsyncCall call=new AsyncCall();

    holder.downloadButton.setOnClickListener(null);
    holder.downloadButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            MODE=0;
            //call.execute(MODE);

        }
    });

    holder.deleteButton.setOnClickListener(null);
    holder.deleteButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Toast.makeText(getContext(), "Delete File "+(String.valueOf(a))+"  "+fPOJO.getFileName(), Toast.LENGTH_LONG).show();
            MODE=1;
            //call.execute(MODE);

        }
    });


    return row;
}

public static class FileHolder{
    TextView fileName;
    ImageButton downloadButton;
    ImageButton deleteButton;
}

Also you can do some code optimalization, for example don't initialize LayoutInflater in getView() method, you can do it in adapter Constructor

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM