I have a ListView that has 12 rows. Each row item contains an ImageView and two TextViews. The ImageViews' visibility are all set to INVISIBLE. When I click on a row, I change the visibility of the ImageView to VISIBLE.
So, I click on the first row, and it's ImageView becomes visibile, which is good. However, when I scroll the ListView, I find that other rows' ImageViews become visible as well. I have done a lot of searching and found out that is due to recycling views since I'm using ViewHolder pattern.
I've looked at the following links
But have not been able to implement it in my code. I honestly don't know how. Below is my pertinent code
listview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center_vertical"
android:background="@color/frame_background"
android:padding="5dp"
>
<!-- the innner view - provides the white rectangle -->
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/frame" >
<!-- the icon view -->
<ImageView android:id="@+id/ivIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:scaleType="fitXY"
android:layout_alignParentLeft="true"
android:visibility="invisible"
/>
<!-- the container view for the title and description -->
<RelativeLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/ivIcon"
android:layout_centerVertical="true"
>
<!-- the title view -->
<TextView android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Medium" />
<!-- the description view -->
<TextView android:id="@+id/tvDescription"
android:layout_below="@id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Small" />
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
ListViewItem.java
public class ListViewItem {
public final String title; // the text for the ListView item title
public final String description; // the text for the ListView item description
public final int drawableRef; //Ref to drawable so Picassco can load it
public boolean visible;
public ListViewItem(int drawableRef, String title, String description) {
this.drawableRef=drawableRef;
this.title = title;
this.description = description;
}
public void setVisible(boolean value)
{
visible = value;
}
public boolean getVisible()
{
return visible;
}
}
ListViewDemoAdapter.java
public class ListViewDemoAdapter extends ArrayAdapter<ListViewItem> {
public ListViewDemoAdapter(Context context, List<ListViewItem> items) {
super(context, R.layout.listview_item,items);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null) {
// inflate the GridView item layout
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.listview_item, parent, false);
// initialize the view holder
viewHolder = new ViewHolder();
viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.ivIcon);
//viewHolder.ivIcon.setVisibility(View.INVISIBLE);
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
viewHolder.tvDescription = (TextView) convertView.findViewById(R.id.tvDescription);
convertView.setTag(viewHolder);
} else {
// recycle the already inflated view
viewHolder = (ViewHolder) convertView.getTag();
}
if(position==ListViewDemoFragment.getSelectedPosition())
{
viewHolder.ivIcon.setVisibility(View.VISIBLE);
}
// update the item view
ListViewItem item = getItem(position);
//viewHolder.ivIcon.setImageDrawable(item.icon);
Picasso.with(getContext()).load(item.drawableRef).into(viewHolder.ivIcon);
viewHolder.tvTitle.setText(item.title);
viewHolder.tvDescription.setText(item.description);
return convertView;
}
private static class ViewHolder {
ImageView ivIcon;
TextView tvTitle;
TextView tvDescription;
}
}
ListViewDemoFragment.java
public class ListViewDemoFragment extends ListFragment {
private static List<ListViewItem> mItems; // ListView items list
private static int mSelectedItem=-1;
private static ListViewDemoAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// initialize the items list
mItems = new ArrayList<ListViewItem>();
Resources resources = getResources();
mItems.add(new ListViewItem(R.drawable.harley1, "TITLE 1", "DESCRIPTION 1"));
mItems.add(new ListViewItem(R.drawable.harley2, "TITLE 2", "DESCRIPTION 2"));
mItems.add(new ListViewItem(R.drawable.harley3, "TITLE 3", "DESCRIPTION 3"));
mItems.add(new ListViewItem(R.drawable.harley4, "TITLE 4", "DESCRIPTION 4"));
mItems.add(new ListViewItem(R.drawable.harley5, "TITLE 5", "DESCRIPTION 5"));
mItems.add(new ListViewItem(R.drawable.harley6, "TITLE 6", "DESCRIPTION 6"));
mItems.add(new ListViewItem(R.drawable.harley7, "TITLE 7", "DESCRIPTION 7"));
mItems.add(new ListViewItem(R.drawable.harley8, "TITLE 8", "DESCRIPTION 8"));
mItems.add(new ListViewItem(R.drawable.harley9, "TITLE 9", "DESCRIPTION 9"));
mItems.add(new ListViewItem(R.drawable.harley10, "TITLE 10", "DESCRIPTION 10"));
mItems.add(new ListViewItem(R.drawable.harley11, "TITLE 11", "DESCRIPTION 11"));
mItems.add(new ListViewItem(R.drawable.harley12, "TITLE 12", "DESCRIPTION 12"));
// initialize and set the list adapter
adapter = new ListViewDemoAdapter(getActivity(), mItems);
setListAdapter(adapter);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// remove the dividers from the ListView of the ListFragment
getListView().setDivider(null);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// retrieve theListView item
ListViewItem item = mItems.get(position);
mSelectedItem = position;
adapter.notifyDataSetChanged();
// do something
Toast.makeText(getActivity(), item.title, Toast.LENGTH_SHORT).show();
}
public static int getSelectedPosition()
{
return mSelectedItem;
}
public static List<ListViewItem> getList()
{
return mItems;
}
public static ListViewDemoAdapter getAdapter()
{
return adapter;
}
}
I think I need to modify my ListViewItem.java and my adapter, but am having trouble implementing the solutions I looked at.
EDIT
ListViewItem.java
public boolean visible = false;
public ListViewItem(int drawableRef, String title, String description) {
//this.icon = Resources.getSystem().getDrawable(drawableRef);
//this.icon = icon;
this.drawableRef=drawableRef;
this.title = title;
this.description = description;
}
public void setVisible(boolean value)
{
visible = value;
}
public boolean getVisible()
{
return visible;
}
ListViewDemoFragment onClick method change
public void onListItemClick(ListView l, View v, int position, long id) {
// retrieve theListView item
ListViewItem item = mItems.get(position);
mSelectedItem = position;
item.setVisible(true);
adapter.notifyDataSetChanged();
// do something
Toast.makeText(getActivity(), item.title, Toast.LENGTH_SHORT).show();
}
getView() function change
else {
// recycle the already inflated view
viewHolder = (ViewHolder) convertView.getTag();
}
ListViewItem item = getItem(position);
if(position==ListViewDemoFragment.getSelectedPosition())
{
if(item.getVisible()==true) {
viewHolder.ivIcon.setVisibility(View.VISIBLE);
}
}
// update the item view
//viewHolder.ivIcon.setImageDrawable(item.icon);
Picasso.with(getContext()).load(item.drawableRef).into(viewHolder.ivIcon);
viewHolder.tvTitle.setText(item.title);
viewHolder.tvDescription.setText(item.description);
return convertView;