我有一个列表视图(聊天)。我得到一些奇怪的行为。它发生在我向上滚动,然后一些项目开始搞乱,当我回到底部时,项目也搞砸了。我唯一能想到的是每次滚动都会调用我的getView几次。有谁知道我怎么能解决这个问题?
我看到这篇文章:Custom ListView adapter, strange ImageView behavior 但是在创建之后,他不会在列表中添加项目。
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="@+id/right_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="@+id/right_profilePic"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="20dp"
android:autoLink="all"
/>
<ImageView
android:id="@+id/left_profilePic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
/>
<TextView
android:id="@+id/left_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/left_profilePic"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="20dp"
android:autoLink="all"
/>
<ImageView
android:id="@+id/right_profilePic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
/>
<TextView
android:id="@+id/left_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="70dp"
android:layout_toRightOf="@+id/left_profilePic"
android:textColor="@color/Gray"
/>
<TextView
android:id="@+id/right_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginRight="70dp"
android:layout_toLeftOf="@+id/right_profilePic"
android:textColor="@color/Gray"
/>
<ImageView
android:id="@+id/left_image_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/left_profilePic"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="20dp"
/>
<ImageView
android:id="@+id/right_image_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="@+id/right_profilePic"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="20dp"
/>
更新
我必须在聊天中加载图片和谷歌静态地图,我想这对于列表视图来说很重要。
这是getView方法:
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d("getView", "getview called");
ViewHolder holder;
if(convertView==null)
{
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.chat_item, null);
holder.right_profilePic = (ImageView) convertView.findViewById(R.id.right_profilePic);
holder.right_message = (TextView) convertView.findViewById(R.id.right_message);
holder.left_profilePic = (ImageView) convertView.findViewById(R.id.left_profilePic);
holder.left_message = (TextView) convertView.findViewById(R.id.left_message);
holder.right_time = (TextView) convertView.findViewById(R.id.right_time);
holder.left_time = (TextView) convertView.findViewById(R.id.left_time);
holder.right_image_message = (ImageView) convertView.findViewById(R.id.right_image_message);
holder.left_image_message = (ImageView) convertView.findViewById(R.id.left_image_message);
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
Log.d("holder", bean.getId() + " | " + GlobalData.myId);
if (bean.getId().equals(GlobalData.myId)) {
Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.right_profilePic);
if (bean.getType().equals("1")) {
Picasso.with(context).load(init_link + bean.getMessage()).into(holder.right_image_message);
holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
//holder.right_image_message.setPadding(0, 0, 0, 20);
} else if (bean.getType().equals("2")) {
StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
String first = tokens.nextToken();
String second = tokens.nextToken();
String url = "http://maps.google.com/maps/api/staticmap?center=" +
first + "," + second + "&zoom=15&size=200x200&sensor=false";
Picasso.with(context).load(url).into(holder.right_image_message);
holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
} else {
holder.right_message.setText(bean.getMessage());
holder.right_message.setBackgroundResource(R.drawable.chat_background_right);
}
holder.right_time.setText(bean.getTime());
} else {
Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.left_profilePic);
if (bean.getType().equals("1")) {
Picasso.with(context).load(init_link + bean.getMessage()).into(holder.left_image_message);
holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
holder.left_image_message.setPadding(0, 10, 0, 30);
} else if (bean.getType().equals("2")) {
StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
String first = tokens.nextToken();
String second = tokens.nextToken();
String url = "http://maps.google.com/maps/api/staticmap?center=" +
first + "," + second + "&zoom=15&size=200x200&sensor=false";
Picasso.with(context).load(url).into(holder.left_image_message);
holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
} else {
holder.left_message.setText(bean.getMessage());
holder.left_message.setBackgroundResource(R.drawable.chat_background_left);
}
holder.left_time.setText(bean.getTime());
}
return convertView;
}public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d("getView", "getview called");
ViewHolder holder;
if(convertView==null)
{
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.chat_item, null);
holder.right_profilePic = (ImageView) convertView.findViewById(R.id.right_profilePic);
holder.right_message = (TextView) convertView.findViewById(R.id.right_message);
holder.left_profilePic = (ImageView) convertView.findViewById(R.id.left_profilePic);
holder.left_message = (TextView) convertView.findViewById(R.id.left_message);
holder.right_time = (TextView) convertView.findViewById(R.id.right_time);
holder.left_time = (TextView) convertView.findViewById(R.id.left_time);
holder.right_image_message = (ImageView) convertView.findViewById(R.id.right_image_message);
holder.left_image_message = (ImageView) convertView.findViewById(R.id.left_image_message);
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
Log.d("holder", bean.getId() + " | " + GlobalData.myId);
if (bean.getId().equals(GlobalData.myId)) {
Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.right_profilePic);
if (bean.getType().equals("1")) {
Picasso.with(context).load(init_link + bean.getMessage()).into(holder.right_image_message);
holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
//holder.right_image_message.setPadding(0, 0, 0, 20);
} else if (bean.getType().equals("2")) {
StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
String first = tokens.nextToken();
String second = tokens.nextToken();
String url = "http://maps.google.com/maps/api/staticmap?center=" +
first + "," + second + "&zoom=15&size=200x200&sensor=false";
Picasso.with(context).load(url).into(holder.right_image_message);
holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
} else {
holder.right_message.setText(bean.getMessage());
holder.right_message.setBackgroundResource(R.drawable.chat_background_right);
}
holder.right_time.setText(bean.getTime());
} else {
Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.left_profilePic);
if (bean.getType().equals("1")) {
Picasso.with(context).load(init_link + bean.getMessage()).into(holder.left_image_message);
holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
holder.left_image_message.setPadding(0, 10, 0, 30);
} else if (bean.getType().equals("2")) {
StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
String first = tokens.nextToken();
String second = tokens.nextToken();
String url = "http://maps.google.com/maps/api/staticmap?center=" +
first + "," + second + "&zoom=15&size=200x200&sensor=false";
Picasso.with(context).load(url).into(holder.left_image_message);
holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
} else {
holder.left_message.setText(bean.getMessage());
holder.left_message.setBackgroundResource(R.drawable.chat_background_left);
}
holder.left_time.setText(bean.getTime());
}
return convertView;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d("getView", "getview called");
ViewHolder holder;
if(convertView==null)
{
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.chat_item, null);
holder.right_profilePic = (ImageView) convertView.findViewById(R.id.right_profilePic);
holder.right_message = (TextView) convertView.findViewById(R.id.right_message);
holder.left_profilePic = (ImageView) convertView.findViewById(R.id.left_profilePic);
holder.left_message = (TextView) convertView.findViewById(R.id.left_message);
holder.right_time = (TextView) convertView.findViewById(R.id.right_time);
holder.left_time = (TextView) convertView.findViewById(R.id.left_time);
holder.right_image_message = (ImageView) convertView.findViewById(R.id.right_image_message);
holder.left_image_message = (ImageView) convertView.findViewById(R.id.left_image_message);
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
Log.d("holder", bean.getId() + " | " + GlobalData.myId);
if (bean.getId().equals(GlobalData.myId)) {
Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.right_profilePic);
if (bean.getType().equals("1")) {
Picasso.with(context).load(init_link + bean.getMessage()).into(holder.right_image_message);
holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
//holder.right_image_message.setPadding(0, 0, 0, 20);
} else if (bean.getType().equals("2")) {
StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
String first = tokens.nextToken();
String second = tokens.nextToken();
String url = "http://maps.google.com/maps/api/staticmap?center=" +
first + "," + second + "&zoom=15&size=200x200&sensor=false";
Picasso.with(context).load(url).into(holder.right_image_message);
holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
} else {
holder.right_message.setText(bean.getMessage());
holder.right_message.setBackgroundResource(R.drawable.chat_background_right);
}
holder.right_time.setText(bean.getTime());
} else {
Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.left_profilePic);
if (bean.getType().equals("1")) {
Picasso.with(context).load(init_link + bean.getMessage()).into(holder.left_image_message);
holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
holder.left_image_message.setPadding(0, 10, 0, 30);
} else if (bean.getType().equals("2")) {
StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
String first = tokens.nextToken();
String second = tokens.nextToken();
String url = "http://maps.google.com/maps/api/staticmap?center=" +
first + "," + second + "&zoom=15&size=200x200&sensor=false";
Picasso.with(context).load(url).into(holder.left_image_message);
holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
} else {
holder.left_message.setText(bean.getMessage());
holder.left_message.setBackgroundResource(R.drawable.chat_background_left);
}
holder.left_time.setText(bean.getTime());
}
return convertView;
}
更新
这里我尝试使用两种不同的布局:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d("getView", "getview called");
ViewHolder holder;
ChatItemBean checkBean = (ChatItemBean) chatItemList.get(position);
if (checkBean.getId().equals(GlobalData.myId)) {
if(convertView==null)
{
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.chat_item_right, null);
holder.right_profilePic = (ImageView) convertView.findViewById(R.id.right_profilePic);
holder.right_message = (TextView) convertView.findViewById(R.id.right_message);
holder.right_time = (TextView) convertView.findViewById(R.id.right_time);
holder.right_image_message = (ImageView) convertView.findViewById(R.id.right_image_message);
convertView.setTag(holder);
} else
holder=(ViewHolder)convertView.getTag();
ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
Log.d("holder", bean.getId() + " | " + GlobalData.myId);
Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.right_profilePic);
if (bean.getType().equals("1")) {
Picasso.with(context).load(init_link + bean.getMessage()).into(holder.right_image_message);
holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
//holder.right_image_message.setPadding(0, 0, 0, 20);
} else if (bean.getType().equals("2")) {
StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
String first = tokens.nextToken();
String second = tokens.nextToken();
String url = "http://maps.google.com/maps/api/staticmap?center=" +
first + "," + second + "&zoom=15&size=200x200&sensor=false";
Picasso.with(context).load(url).into(holder.right_image_message);
holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
} else {
holder.right_message.setText(bean.getMessage());
holder.right_message.setBackgroundResource(R.drawable.chat_background_right);
}
holder.right_time.setText(bean.getTime());
} else {
if(convertView==null)
{
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.chat_item, null);
holder.left_profilePic = (ImageView) convertView.findViewById(R.id.left_profilePic);
holder.left_message = (TextView) convertView.findViewById(R.id.left_message);
holder.left_time = (TextView) convertView.findViewById(R.id.left_time);
holder.left_image_message = (ImageView) convertView.findViewById(R.id.left_image_message);
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
Log.d("holder", bean.getId() + " | " + GlobalData.myId);
Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.left_profilePic);
if (bean.getType().equals("1")) {
Picasso.with(context).load(init_link + bean.getMessage()).into(holder.left_image_message);
holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
holder.left_image_message.setPadding(0, 10, 0, 30);
} else if (bean.getType().equals("2")) {
StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
String first = tokens.nextToken();
String second = tokens.nextToken();
String url = "http://maps.google.com/maps/api/staticmap?center=" +
first + "," + second + "&zoom=15&size=200x200&sensor=false";
Picasso.with(context).load(url).into(holder.left_image_message);
holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
} else {
holder.left_message.setText(bean.getMessage());
holder.left_message.setBackgroundResource(R.drawable.chat_background_left);
}
holder.left_time.setText(bean.getTime());
}
return convertView;
}
但是我的应用程序崩溃了,当我滚动一点,就像它试图搞砸的那一刻,我得到的目标不能为空。第124行使用毕加索加载配置文件。
12-01 21:14:40.442: E/AndroidRuntime(21764): java.lang.IllegalArgumentException: Target must not be null.
12-01 21:14:40.442: E/AndroidRuntime(21764): at com.squareup.picasso.RequestCreator.into(RequestCreator.java:333)
12-01 21:14:40.442: E/AndroidRuntime(21764): at com.squareup.picasso.RequestCreator.into(RequestCreator.java:319)
12-01 21:14:40.442: E/AndroidRuntime(21764): at com.petcial.petopen.custom.ChatCustomAdapter.getView(ChatCustomAdapter.java:124)
答案 0 :(得分:1)
使用两个布局文件最终会丢失一些convertView可重用性能的东西。但是会帮助你拥有可以解决这个烂摊子的清洁用品。确定哪个文件用于哪个项目。
2。使用一个布局文件。
可以/(需要付出努力)干净地定义一个文件的布局,以便为所有类型的列表项正确使用它们。使用相对布局并将一个x1放在另一个x2之上。并根据类型简单地在getView中使x1或x2可见或不可见。 确保在getView中没有繁重的操作。其中x1和x2是您的一个项目类型的布局。
试试这个。但您肯定可以发布您的代码以获得更多帮助。但建议首先尝试清理。
更新: 转到选项2.使用一个RelativeLayout并在其中添加两个LinearLayout。 一个在另一个之上并在第一个LinearLayout中定义一个项类型,在第二个中定义另一个。 使这些容器(LL)在getView
中可见或不可见希望这个建议有所帮助
答案 1 :(得分:1)
This教程令人惊叹。我强烈推荐使用它。在没有看到您的JAva代码的情况下,我可以说您需要为列表条目提供两种不同的布局XML。一个用于左侧图像,另一个用于右侧图像。然后,在适配器中,为会话的那一部分充气。
这是正确的方法。我认为发生在你身上的是你在回收的ViewGroup中添加了内容,这些内容传递给了getView而没有删除旧的内容,所以你的新东西被添加到旧的东西之上。使用新流程,您需要确保循环视图是正确的“方向”,然后删除旧内容并添加新内容。
以下是我在上面链接的Vogella文章中的部分。
在
getView()
方法中,您将扩展基于XML的布局,然后根据此行的Java对象设置各个视图的内容。要扩展XML布局文件,您可以使用系统服务LayoutInflator
。可以通过活动或context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
方法调用访问此服务。可以通过顶级视图上的
findViewById()
方法调用找到布局中的各个元素。
顺便说一句,getView()在滚动期间被多次调用,并且调用的顺序是不可预测的。因此,不要在getView方法中做任何过于密集的事情,否则减速将非常明显。
答案 2 :(得分:0)
这是常见问题,已在StackOverflow中提出过。但是,首先检查一下android工程师RomainGuy所说的getView()方法调用
这不是问题,订单绝对没有保证 getView()将被调用多少次。
因此,您可以正确处理re-using the existing views(行布局)。
或者只需在适配器类中添加这行代码。
@Override
public int getViewTypeCount() {
if (getCount() != 0)
return getCount();
return 1;
}
答案 3 :(得分:0)
我有确切的问题,我通过不使用convertView来解决它。
基本上,我所做的是:
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = inflater.inflate(R.layout.your_layout, parent, false);
//Do what you intend to do, populate the TextView, or set the ImageViews, but do them with respect to rowView, not convertView.
ImageView imageView = (ImageView) rowView.findViewById(R.id.my_picture);
imageView.setImageResources(R.drawable.sample_picture);
return rowView;
}
无论您使用1个布局还是2个列表项,这都很有用,希望这会有所帮助: - )