滚动时带有 ImageView 位置的 Listview 乱七八糟
Listview with ImageView position is messed up when scrolling
我有一个有 12 行的 ListView。每个行项目包含一个 ImageView 和两个 TextView。 ImageViews 的可见性都设置为 INVISIBLE。当我单击一行时,我将 ImageView 的可见性更改为 VISIBLE。
所以,我点击第一行,它的ImageView就可见了,这很好。但是,当我滚动 ListView 时,我发现其他行的 ImageView 也变得可见。我做了很多搜索,发现这是由于我使用 ViewHolder 模式后回收视图造成的。
我查看了以下链接
Solution 1
Solution 2
但是一直无法在我的代码中实现它。老实说,我不知道该怎么做。下面是我的相关代码
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;
}
}
我想我需要修改我的 ListViewItem.java 和我的适配器,但在实施我查看的解决方案时遇到了问题。
编辑
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 方法更改
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()函数变化
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;
因为你有一个boolean visible
来记录状态,所以没有必要这样做:
if(position==ListViewDemoFragment.getSelectedPosition())
{
if(item.getVisible()==true) {
viewHolder.ivIcon.setVisibility(View.VISIBLE);
}
}
让数据决定 ImageView
的可见性。将下面的代码写入您的 getView
ListViewItem item = getItem(position);
if (item.getVisible()) {
viewHolder.ivIcon.setVisibility(View.VISIBLE);
} else {
viewHolder.ivIcon.setVisibility(View.INVISIBLE);
}
我有一个有 12 行的 ListView。每个行项目包含一个 ImageView 和两个 TextView。 ImageViews 的可见性都设置为 INVISIBLE。当我单击一行时,我将 ImageView 的可见性更改为 VISIBLE。
所以,我点击第一行,它的ImageView就可见了,这很好。但是,当我滚动 ListView 时,我发现其他行的 ImageView 也变得可见。我做了很多搜索,发现这是由于我使用 ViewHolder 模式后回收视图造成的。
我查看了以下链接
Solution 1
Solution 2
但是一直无法在我的代码中实现它。老实说,我不知道该怎么做。下面是我的相关代码
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;
}
}
我想我需要修改我的 ListViewItem.java 和我的适配器,但在实施我查看的解决方案时遇到了问题。
编辑
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 方法更改
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()函数变化
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;
因为你有一个boolean visible
来记录状态,所以没有必要这样做:
if(position==ListViewDemoFragment.getSelectedPosition())
{
if(item.getVisible()==true) {
viewHolder.ivIcon.setVisibility(View.VISIBLE);
}
}
让数据决定 ImageView
的可见性。将下面的代码写入您的 getView
ListViewItem item = getItem(position);
if (item.getVisible()) {
viewHolder.ivIcon.setVisibility(View.VISIBLE);
} else {
viewHolder.ivIcon.setVisibility(View.INVISIBLE);
}