Reputation: 8702
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.
################################# SOLUTIONIf someone is looking for the solution, here it is. Many thanks to user936414!.
Replace (line 6):
if (convertView == null) convertView = inflater.inflate(R.layout.phonebook_adapter_layout, parent, false);
By:
convertView = inflater.inflate(R.layout.phonebook_adapter_layout, parent, false);
Before:
return convertView;
Add:
if (selectedAvailabilities.get(position).booleanValue())
{
availability.setBackgroundColor(Color.RED);
}
if (selectedLocations.get(position).booleanValue())
{
location.setBackgroundColor(Color.RED);
}
Upvotes: 1
Views: 341
Reputation: 7634
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.
Upvotes: 4