伙计我有一个奇怪的问题:
在聊天应用程序中,我有一个ListView和一个适配器来处理它。如果用户从图库发送图像,我将在气泡语音上显示缩略图,并添加onTouchListener以全屏打开此图像。问题是:当我添加事件监听器时,它会添加到我的所有ImageViews!因此,如果我点击最后一个imageView,它会在整个屏幕上显示正确的图像,但之前的所有图像都显示相同的图像。我已经多次查看了代码,但我看不出问题。有人可以帮忙吗?
我的适配器:
public class ConversationArrayAdapter extends ArrayAdapter<Message> {
private TextView messageView;
private TextView timeView;
private TextView confView;
private ImageView imageView;
private LinearLayout timeConfView;
private List<Message> messages = new ArrayList<Message>();
private WindowManager wm;
private Display display;
private RelativeLayout.LayoutParams params;
private Context context;
private Message message;
public ConversationArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
this.context = context;
wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
display = wm.getDefaultDisplay();
}
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.list_item_message, parent, false);
}
message = getItem(position);
messageView = (TextView) row.findViewById(R.id.message);
messageView.setText(message.message);
messageView.setBackgroundResource(message.left ? R.drawable.anonymous : R.drawable.me);
timeView = (TextView) row.findViewById(R.id.time);
timeView.setText(message.time);
confView = (TextView) row.findViewById(R.id.confirmation);
confView.setText(message.conf);
timeConfView = (LinearLayout) row.findViewById(R.id.timeConfWrapper);
imageView = (ImageView) row.findViewById(R.id.imageUploaded);
messageView.setMaxWidth(display.getWidth() - (30*display.getWidth()/100));
imageView.setMaxWidth(display.getWidth() - (30*display.getWidth()/100));
imageView.setMaxHeight(display.getHeight() - (70*display.getHeight()/100));
params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
messageView.setLayoutParams(params);
messageView.setPadding(
(int)(10 * context.getResources().getDisplayMetrics().density),
(int)(5 * context.getResources().getDisplayMetrics().density),
(int)(15 * context.getResources().getDisplayMetrics().density),
(int)(6 * context.getResources().getDisplayMetrics().density));
messageView.requestFocus();
if (!message.image) {
params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.LEFT_OF, R.id.message);
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
timeConfView.setLayoutParams(params);
timeConfView.setPadding(0, 0, (int)(10 * context.getResources().getDisplayMetrics().density), 0);
} else {
imageView.setPadding(
(int)(5 * context.getResources().getDisplayMetrics().density),
(int)(5 * context.getResources().getDisplayMetrics().density),
(int)(10 * context.getResources().getDisplayMetrics().density),
(int)(5 * context.getResources().getDisplayMetrics().density));
imageView.requestFocus();
messageView.setVisibility(TextView.INVISIBLE);
imageView.setVisibility(ImageView.VISIBLE);
params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.LEFT_OF, R.id.imageUploaded);
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
timeConfView.setLayoutParams(params);
timeConfView.setPadding(0, 0, (int)(10 * context.getResources().getDisplayMetrics().density), 0);
imageView.setImageBitmap(message.bitImage);
imageView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Uri imgUri = Uri.parse("file://" + message.imagePath);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setData(imgUri);
intent.setDataAndType(imgUri, "image/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return true;
}
});
confView.setVisibility(TextView.VISIBLE);
}
return row;
}
@Override
public void add(Message object) {
messages.add(object);
super.add(object);
}
我如何在活动中使用它:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// Checking the request for gallery and a lot of stuff and generating a bitmap with the filePath
Message msg = new Message(false, message.getText().toString(), DateFormat.getTimeInstance().format(new Date()).substring(0,5), true, bitmap, filePath);
adapter.add(msg);
}
我的按摩课程:
package br.com.unichat.classes;
import android.graphics.Bitmap;
public class Message {
public boolean left;
public boolean image;
public String message;
public String time;
public String conf;
public String imagePath;
public Bitmap bitImage;
public Message(boolean left, String comment, String time) {
super();
this.left = left;
this.message = comment;
this.time = time;
this.conf = "·";
this.image = false;
this.bitImage = null;
}
public Message(boolean left, String comment, String time, boolean image, Bitmap bitImage, String path) {
super();
this.left = left;
this.message = comment;
this.time = time;
this.conf = "·";
this.image = image;
this.bitImage = bitImage;
this.imagePath = path;
}
}
有什么想法吗?提前致谢
答案 0 :(得分:1)
两个问题: 1)您的OnTouchListener是一个内部类,它访问外部类的message属性,该属性在处理不同的行时不断变化。当您处理触摸事件时,适配器已处理数据的最后一行,并停在那里。它不像JavaScript闭包。每个imageView都需要一个不同的OnTouchListener,它将在触摸时显示正确的项目。您可以通过创建一个OnTouchListener的子类来实现这一点,该子类使用属性进行初始化以保持正确的图像路径显示,或者您可以执行以下简单的hack:在每个imageView上设置标记,并在OnTouchListener中使用该标记找出哪一行被点击并以那种方式查找正确的图像(使用标记作为数组索引,或使用SQLiteCursor光标位置移动到,或者你有什么)。
2)请记住,表格中的行/视图会被重复使用。因此,在您的适配器中,如果您在不应该有侦听器的行的if语句分支中,则需要删除它,以防先前在该行/视图绑定到后备数据中的其他条目时添加它
答案 1 :(得分:1)
初始化imageView.setOnTouchListener(null);
后立即添加imageView
。这将确保只有您想要附加侦听器的行才能拥有它。正如RobP所说,你的观点在屏幕上显示时会被重复使用,因此之前的OnTouchListener
可能仍会被附加。
您还需要跟踪用户点击图片时要使用的消息。为此,您可以使用setTag();
。您生成的代码应如下所示:
imageView.setTag(message);
imageView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Message messageForThisRow = (Message)v.getTag();
Uri imgUri = Uri.parse("file://" + messageForThisRow.imagePath);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setData(imgUri);
intent.setDataAndType(imgUri, "image/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return true;
}
});