简体   繁体   中英

Android - Issue with a ListView

As a french developper, I apologize about my English.

So, my aim is to create a phone book for my android application. This phone book is made of a ListView. I've populated my ListView with a custom adapter which allows the user to select some TextViews in each rows. I presume a picture is better than thousand words, so here it is:

在此输入图像描述

As you can see the red parts are the TextViews that I have selected. The issue I have to face is the following:

When I select a TextView from a row, the row that is 4 places under has its TextView that gets selected too! Is that a common issue or is it due to my code?

I've added a log on the click listener, for each TextView I click, I receive only one log, so I don't think the problem comes from my work.

For example and if some of you don't understand what I said; I select the TextView with the drawableLeft picture in the second row. The logcat returns me the following entry: "Select: 1" (as defined in my code). If I scroll down my ListView, I can see that my second row (ie. my TextView) is selected as expected but also my 6th row, which is not expected at all!

Here is the code I use in order to color or not a row:

public View getView(final int position, View convertView, ViewGroup parent)
{
    selectedLocations.add(new Boolean(false));
    selectedAvailabilities.add(new Boolean(false));

    if (convertView == null) convertView = inflater.inflate(R.layout.phonebook_adapter_layout, parent, false);

    final LinearLayout root = (LinearLayout) convertView.findViewById(R.id.phonebook_adapter_root);
    final ImageView photo = (ImageView) convertView.findViewById(R.id.phonebook_adapter_image);
    final TextView firstname = (TextView) convertView.findViewById(R.id.phonebook_adapter_firstname);
    final TextView lastname = (TextView) convertView.findViewById(R.id.phonebook_adapter_lastname);
    final TextView location = (TextView) convertView.findViewById(R.id.phonebook_adapter_location);
    final TextView availability = (TextView) convertView.findViewById(R.id.phonebook_adapter_availability);

    Bitmap mBitmap = null;
    try
    {
        mBitmap = Media.getBitmap(context.getContentResolver(), Uri.parse(relations.get(position).getPhoto()));
        photo.setImageBitmap(mBitmap);
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

    firstname.setText(relations.get(position).getFirstName());
    lastname.setText(relations.get(position).getLastName());

    DBStatus dbStatus = new DBStatus(KramerApplication.getInstance());
    Status status = dbStatus.getWithRelation(relations.get(position));
    dbStatus.close();

    if (status != null)
    {           
        location.setText( status.getLocation() );
        availability.setText( status.getAvailability() );

        if ( status.getDisplayedAvailability(2).equals("Busy") )
            availability.setCompoundDrawablesWithIntrinsicBounds(R.drawable.availability_busy, 0, 0, 0);
        else if ( status.getDisplayedAvailability(2).equals("Occupied") )
            availability.setCompoundDrawablesWithIntrinsicBounds(R.drawable.availability_busy, 0, 0, 0);
        else if ( status.getDisplayedAvailability(2).equals("Free") )
            availability.setCompoundDrawablesWithIntrinsicBounds(R.drawable.availability_on, 0, 0, 0);
        else
            availability.setCompoundDrawablesWithIntrinsicBounds(R.drawable.availability_off, 0, 0, 0);
    }

    root.setOnClickListener(new OnClickListener() {
        public void onClick(View v)
        {
            Intent intent = new Intent(context, ContactDetailsActivity.class);
            intent.putExtra("contact_id", relations.get(position).getId());
            context.startActivity(intent);
        }
    });

    location.setOnClickListener(new OnClickListener() {
        public void onClick(View v)
        {
            if (selectedLocations.get(position).booleanValue())
            {
                selectedLocations.set(position, new Boolean(false));
                location.setBackgroundColor(Color.TRANSPARENT);
            }
            else
            {
                selectedLocations.set(position, new Boolean(true));
                location.setBackgroundColor(Color.RED);
            }
        }
    });
    availability.setOnClickListener(new OnClickListener() {
        public void onClick(View v)
        {
            if (selectedAvailabilities.get(position).booleanValue())
            {
                selectedAvailabilities.set(position, new Boolean(false));
                availability.setBackgroundColor(Color.TRANSPARENT);
            }
            else
            {
                selectedAvailabilities.set(position, new Boolean(true));
                availability.setBackgroundColor(Color.RED);
            }
        }
    });

    return convertView;
}

The ArrayLists "selectedAvailabilities" and "selectedLocations" have been properly initialized in the constructor and do their jobs when I use them in another activity (Read only).

I hope you'll be able to help me.

Regards.

V.

################################# SOLUTION

If someone is looking for the solution, here it is. Many thanks to user936414 !.

Replace (line 6):

convertView = inflater.inflate(R.layout.phonebook_adapter_layout, parent, false);

By:

return convertView;

Before:

if (selectedAvailabilities.get(position).booleanValue())
{
    availability.setBackgroundColor(Color.RED);
}
if (selectedLocations.get(position).booleanValue())
{
    location.setBackgroundColor(Color.RED);
}

Add:

 if (selectedAvailabilities.get(position).booleanValue()) { availability.setBackgroundColor(Color.RED); } if (selectedLocations.get(position).booleanValue()) { location.setBackgroundColor(Color.RED); } 

The reason for this behavior is the use of convertview. To solve this, have a HashSet and put all the positions selected in the HashSet. In getView check contains of Hashset and setSelected for the TextView. Hope this helps.

Add

 if (selectedLocations.get(position).booleanValue())
 {
           location.setBackgroundColor(Color.RED);
 }
 else
 {

            location.setBackgroundColor(Color.TRANSPARENT);
 }

outside the onClickListener also to ensure convertView does not affect your requirement.

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