在 Android 的 ListView 中滚动时,Listitems 会改变位置
Listitems change position when scrolling in ListView in Android
我是 Android 的新手,我正在使用 customlistitems 开发 ListView
,其中包含图像和一些文本,我发现了一个问题滚动up/down 列表视图,列表项的位置正在改变。那么有人可以帮助我吗?我在这里发布我的适配器以供您参考。希望你能帮我弄清楚。
OfferAdapter
public class OfferAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Offer> OfferList;
public OfferAdapter(Context c, ArrayList<Offer> OfferList) {
mContext = c;
this.OfferList = OfferList;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return OfferList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.raw_offer, null);
TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
tv_ofr_desc.setText(OfferList.get(position).getDescription());
tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
Date from = new Date();
Date to = new Date();
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
try {
from = input.parse(OfferList.get(position).getStart_date());
to = input.parse(OfferList.get(position).getEnd_date()); // parse input
} catch (ParseException e) {
e.printStackTrace();
}
tv_date.setText(output.format(from) + " TO " + output.format(to));
Picasso.with(mContext)
.load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
.placeholder(R.drawable.ic_no_img)
.error(R.drawable.ic_no_img)
.into(iv_pic);
} else {
grid = (View) convertView;
}
return grid;
}
}
您需要修改您的getView()方法如下-
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View grid = convertView;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (grid == null) {
grid = inflater.inflate(R.layout.raw_offer, parent, false);
}
TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
tv_ofr_desc.setText(OfferList.get(position).getDescription());
tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
Date from = new Date();
Date to = new Date();
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
try {
from = input.parse(OfferList.get(position).getStart_date());
to = input.parse(OfferList.get(position).getEnd_date()); // parse input
} catch (ParseException e) {
e.printStackTrace();
}
tv_date.setText(output.format(from) + " TO " + output.format(to));
Picasso.with(mContext)
.load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
.placeholder(R.drawable.ic_no_img)
.error(R.drawable.ic_no_img)
.into(iv_pic);
return grid;
}
而且你还需要覆盖这两个方法 -
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
更改您的一些适配器方法,例如 -
@Override
public Offer getItem(int position) {
// TODO Auto-generated method stub
return OfferList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
因此您的适配器将是 -
public class OfferAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Offer> OfferList;
public OfferAdapter(Context c, ArrayList<Offer> OfferList) {
mContext = c;
this.OfferList = OfferList;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return OfferList.size();
}
@Override
public Offer getItem(int position) {
// TODO Auto-generated method stub
return OfferList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.raw_offer, null);
TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
tv_ofr_desc.setText(OfferList.get(position).getDescription());
tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
Date from = new Date();
Date to = new Date();
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
try {
from = input.parse(OfferList.get(position).getStart_date());
to = input.parse(OfferList.get(position).getEnd_date()); // parse input
} catch (ParseException e) {
e.printStackTrace();
}
tv_date.setText(output.format(from) + " TO " + output.format(to));
Picasso.with(mContext)
.load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
.placeholder(R.drawable.ic_no_img)
.error(R.drawable.ic_no_img)
.into(iv_pic);
} else {
grid = (View) convertView;
}
return grid;
}
}
您的问题出在您的 getView()
实现中,并且是由于对方法参数的作用以及此方法如何填充 ListView
的误解。这是完全可以理解的; ListView
有点复杂。
要理解的重要部分是 ListView
将建立 "pool" 视图,然后 回收 它们,这样它们就不需要了每次滚动列表时都会重新创建。您之前创建并从 getView()
返回的视图可以作为 convertView
参数传入;在这些情况下,您需要做的就是更新该视图的 UI。
考虑到这一点,您可以按如下方式重写 getView()
:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View grid;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
grid = inflater.inflate(R.layout.raw_offer, parent, false);
} else {
grid = convertView;
}
TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
tv_ofr_desc.setText(OfferList.get(position).getDescription());
tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
Date from = new Date();
Date to = new Date();
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
try {
from = input.parse(OfferList.get(position).getStart_date());
to = input.parse(OfferList.get(position).getEnd_date()); // parse input
} catch (ParseException e) {
e.printStackTrace();
}
tv_date.setText(output.format(from) + " TO " + output.format(to));
Picasso.with(mContext)
.load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
.placeholder(R.drawable.ic_no_img)
.error(R.drawable.ic_no_img)
.into(iv_pic);
return grid;
}
您还可以进行其他优化。最简单的就是去掉 View grid
变量;你可以直接使用 convertView
。更复杂的是使用 "view holder" 模式来缓存各种 findViewById()
调用的结果。
存在多个问题:
1. 而不是
@Override
public Object getItem(int position) {
return null;
}
你应该写
@Override
public Object getItem(int position) {
return OfferList.get(position);
}
2. 而不是
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.raw_offer, null);
// [all that initializing stuff]
} else {
grid = (View) convertView;
}
return grid;
}
你应该写
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View grid;
if (convertView == null) {
grid = inflater.inflate(R.layout.raw_offer, parent, false);
} else {
grid = convertView;
}
// [all that initializing stuff]
return grid;
}
您还可以查看 ViewHolder 概念以提高列表的性能:
我是 Android 的新手,我正在使用 customlistitems 开发 ListView
,其中包含图像和一些文本,我发现了一个问题滚动up/down 列表视图,列表项的位置正在改变。那么有人可以帮助我吗?我在这里发布我的适配器以供您参考。希望你能帮我弄清楚。
OfferAdapter
public class OfferAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Offer> OfferList;
public OfferAdapter(Context c, ArrayList<Offer> OfferList) {
mContext = c;
this.OfferList = OfferList;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return OfferList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.raw_offer, null);
TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
tv_ofr_desc.setText(OfferList.get(position).getDescription());
tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
Date from = new Date();
Date to = new Date();
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
try {
from = input.parse(OfferList.get(position).getStart_date());
to = input.parse(OfferList.get(position).getEnd_date()); // parse input
} catch (ParseException e) {
e.printStackTrace();
}
tv_date.setText(output.format(from) + " TO " + output.format(to));
Picasso.with(mContext)
.load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
.placeholder(R.drawable.ic_no_img)
.error(R.drawable.ic_no_img)
.into(iv_pic);
} else {
grid = (View) convertView;
}
return grid;
}
}
您需要修改您的getView()方法如下-
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View grid = convertView;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (grid == null) {
grid = inflater.inflate(R.layout.raw_offer, parent, false);
}
TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
tv_ofr_desc.setText(OfferList.get(position).getDescription());
tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
Date from = new Date();
Date to = new Date();
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
try {
from = input.parse(OfferList.get(position).getStart_date());
to = input.parse(OfferList.get(position).getEnd_date()); // parse input
} catch (ParseException e) {
e.printStackTrace();
}
tv_date.setText(output.format(from) + " TO " + output.format(to));
Picasso.with(mContext)
.load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
.placeholder(R.drawable.ic_no_img)
.error(R.drawable.ic_no_img)
.into(iv_pic);
return grid;
}
而且你还需要覆盖这两个方法 -
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
更改您的一些适配器方法,例如 -
@Override
public Offer getItem(int position) {
// TODO Auto-generated method stub
return OfferList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
因此您的适配器将是 -
public class OfferAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Offer> OfferList;
public OfferAdapter(Context c, ArrayList<Offer> OfferList) {
mContext = c;
this.OfferList = OfferList;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return OfferList.size();
}
@Override
public Offer getItem(int position) {
// TODO Auto-generated method stub
return OfferList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.raw_offer, null);
TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
tv_ofr_desc.setText(OfferList.get(position).getDescription());
tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
Date from = new Date();
Date to = new Date();
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
try {
from = input.parse(OfferList.get(position).getStart_date());
to = input.parse(OfferList.get(position).getEnd_date()); // parse input
} catch (ParseException e) {
e.printStackTrace();
}
tv_date.setText(output.format(from) + " TO " + output.format(to));
Picasso.with(mContext)
.load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
.placeholder(R.drawable.ic_no_img)
.error(R.drawable.ic_no_img)
.into(iv_pic);
} else {
grid = (View) convertView;
}
return grid;
}
}
您的问题出在您的 getView()
实现中,并且是由于对方法参数的作用以及此方法如何填充 ListView
的误解。这是完全可以理解的; ListView
有点复杂。
要理解的重要部分是 ListView
将建立 "pool" 视图,然后 回收 它们,这样它们就不需要了每次滚动列表时都会重新创建。您之前创建并从 getView()
返回的视图可以作为 convertView
参数传入;在这些情况下,您需要做的就是更新该视图的 UI。
考虑到这一点,您可以按如下方式重写 getView()
:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View grid;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
grid = inflater.inflate(R.layout.raw_offer, parent, false);
} else {
grid = convertView;
}
TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
tv_ofr_desc.setText(OfferList.get(position).getDescription());
tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
Date from = new Date();
Date to = new Date();
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
try {
from = input.parse(OfferList.get(position).getStart_date());
to = input.parse(OfferList.get(position).getEnd_date()); // parse input
} catch (ParseException e) {
e.printStackTrace();
}
tv_date.setText(output.format(from) + " TO " + output.format(to));
Picasso.with(mContext)
.load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
.placeholder(R.drawable.ic_no_img)
.error(R.drawable.ic_no_img)
.into(iv_pic);
return grid;
}
您还可以进行其他优化。最简单的就是去掉 View grid
变量;你可以直接使用 convertView
。更复杂的是使用 "view holder" 模式来缓存各种 findViewById()
调用的结果。
存在多个问题:
1. 而不是
@Override
public Object getItem(int position) {
return null;
}
你应该写
@Override
public Object getItem(int position) {
return OfferList.get(position);
}
2. 而不是
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.raw_offer, null);
// [all that initializing stuff]
} else {
grid = (View) convertView;
}
return grid;
}
你应该写
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View grid;
if (convertView == null) {
grid = inflater.inflate(R.layout.raw_offer, parent, false);
} else {
grid = convertView;
}
// [all that initializing stuff]
return grid;
}
您还可以查看 ViewHolder 概念以提高列表的性能: