Android, List Adapter gibt falsche Position in getView zurück
Ich habe ein mysteriöses problem, das möglicherweise ein bug!
Ich habe eine Liste in meinem fragment. Jede Zeile ist ein button. Liste sollte nicht Antworten zu klicken, jedoch sind die Schaltflächen anklickbar.
In Ordnung zu bekommen, auf welche Schaltfläche geklickt hat, habe ich einen listener und umsetzen in mein fragment. Dies ist der code von meinem adapter.
public class AddFriendsAdapter extends BaseAdapter {
public interface OnAddFriendsListener {
public void OnAddUserClicked(MutualFriends user);
}
private final String TAG = "*** AddFriendsAdapter ***";
private Context context;
private OnAddFriendsListener listener;
private LayoutInflater myInflater;
private ImageDownloader imageDownloader;
private List<MutualFriends> userList;
public AddFriendsAdapter(Context context) {
this.context = context;
myInflater = LayoutInflater.from(context);
imageDownloader = ImageDownloader.getInstance(context);
}
public void setData(List<MutualFriends> userList) {
this.userList = userList;
Log.i(TAG, "List passed to the adapter.");
}
@Override
public int getCount() {
try {
return userList.size();
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
holder = new ViewHolder();
Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/ITCAvantGardeStd-Demi.ttf");
holder.tvUserName = (TextView) convertView.findViewById(R.id.tvUserName);
holder.tvUserName.setTypeface(font);
holder.ivPicture = (ImageView) convertView.findViewById(R.id.ivPicture);
holder.btnAdd = (Button) convertView.findViewById(R.id.btnAdd);
holder.btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "Item: " + position);
listener.OnAddUserClicked(userList.get(position));
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvUserName.setText(userList.get(position).getName());
imageDownloader.displayImage(holder.ivPicture, userList.get(position).getPhotoUrl());
return convertView;
}
public void setOnAddClickedListener(OnAddFriendsListener listener) {
this.listener = listener;
}
static class ViewHolder {
TextView tvUserName;
ImageView ivPicture;
Button btnAdd;
}
}
Wenn ich die app starte, kann ich sehen, wie meine Zeilen, aber da meine Liste ist lang und hat über 200 Elemente, wenn ich gehe mitten in der Liste und klicken Sie auf ein Element dann wieder position falsch ist (es ist so etwas wie das 7, mal 4 und etc.).
Nun, was ist das Geheimnis?
Wenn ich aktiv auf item listener der Liste von meinem fragment, und klicken Sie auf Zeile dann das korrekte Zeile die position angezeigt, während auf die Zeile wenn ich auf den button klicken, dann falschen position angezeigt werden.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.e(TAG, "item " + position + " clicked.");
}
});
Ergebnis in logcat:
05-09 10:22:25.228: E/AddFriendsFragment(20296): item 109 clicked.
05-09 10:22:34.453: E/*** AddFriendsAdapter ***(20296): Item: 0
Jeder Vorschlag würde geschätzt werden. Dank
InformationsquelleAutor der Frage Hesam | 2013-05-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
Weil die
convertView
und Halter recycelt werden zu verwenden, bewegen Sie IhresetOnClickListener
aus der if-else-Anweisung:Ist es nicht die beste Lösung,da gibt es einige performance-Problem. Ich schlage vor, Sie erstellen eine Karte für die Ansicht ein und erstellen Sie eine neue Ansicht für Ihren Artikel, dann nutzen Sie einfach die relative Ansicht für jede Ansicht.
Ich denke, es wird eine bessere Lösung mit der besten performance:
Können Sie auch verwalten Sie Ihre anzeigen selbst. Erstellen, jeden einzigartigen view für Ihr Element, nicht recycle-Ansicht.
InformationsquelleAutor der Antwort buptcoder
Hast du versucht, etwas wie das zu tun:
Und dann abrufen, welche Zeile geklickt wurde, in der callback für die Schaltfläche, wie diese:
InformationsquelleAutor der Antwort Daniel Conde Marin
Anderen Ansatz fand ich nützlich (wenn Sie mit dem ViewHolder pattern natürlich), ist der index auf einem separaten Attribut, wenn getView() aufgerufen wird, dann in Ihrem onClickListener Sie müssen nur Referenz Ihr Halter die position Attribut, so etwas wie dieses:
InformationsquelleAutor der Antwort Alan Poggetti