Android的名单适配器返回getView错误的位置 [英] Android, List Adapter returns wrong position in getView
问题描述
我发现了一个神秘的问题,可能是一个错误! 我在我的片段列表。每一行都有一个按钮。名单应该不会响应单击但按钮是可以点击的。
I have found a mysterious problem that may be a bug! I have a list in my fragment. Each row has a button. List shouldn't respond to click however buttons are clickable.
为了获得哪个按钮点击我创建了一个监听器,并在我的片段实现它。这是我的适配器的code。
In order to get which button has clicked I have created a listener and implement it in my fragment. This is the code of my 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;
}
}
当我运行的应用程序,我可以看到我行不过因为我的名单很长,拥有超过200项,当我转到列表中,单击某个项目,然后返回的位置是错误的(这有点像7,有时4等)。
When I run the app, I can see my rows however since my list is long and has over 200 items when i goto middle of list and click an item then returned position is wrong (it's something like 7, sometimes 4 and etc.).
现在有什么奥秘? 如果我主动从我的片段清单项目监听器和行则点击正确的行位置将在该行显示而如果我按一下按钮,然后错误的位置将被显示出来。
Now what is the mystery? If I active on item listener of list from my fragment and click on row then correct row position will be displayed while on that row if I click on button then wrong position will be displayed.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.e(TAG, "item " + position + " clicked.");
}
});
在logcat的结果:
Result 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
任何建议将AP preciated。谢谢
Any suggestion would be appreciated. Thanks
推荐答案
由于该 convertView
和持有人将被回收利用,将您的 setOnClickListener
出的if else语句:
Because the convertView
and holder will be recycled to use, move your setOnClickListener
out of the if else statement:
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);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
Log.e(TAG, "Item: " + position);
listener.OnAddUserClicked(userList.get(position));
}
});
这不是最好的解决办法,因为会有一些性能问题。我建议你创建一个地图的视图,并为您的项目就用每个视图相对视图的新观点。
It is not the best solution for that,because there will be some performance issue. I suggest you create a Map for your view and create a new view for your item then just use the relative view for each view.
我认为这将是一个更好的解决方案与最佳的性能:
I think it will be a better solution with best performance:
@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) {
Integer pos = (Integer)v.getTag();
Log.e(TAG, "Item: " + pos);
listener.OnAddUserClicked(userList.get(pos));
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvUserName.setText(userList.get(position).getName());
imageDownloader.displayImage(holder.ivPicture, userList.get(position).getPhotoUrl());
holder.btnAdd.setTag(position);
return convertView;
}
您也可以管理您的视图自己。创建您的项目每一个独特的看法,不要循环使用视图。
You can also manage your view by yourself. Create every unique view for your item, don't recycle view.
//member various
private Map<Integer, View> myViews = new HashMap<Integer, View>();
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View view = myViews.get(position);
if (view == null) {
view = myInflater.inflate(R.layout.list_add_friends_row, null);
//don't need use the holder anymore.
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) {
Integer pos = (Integer)v.getTag();
Log.e(TAG, "Item: " + pos);
listener.OnAddUserClicked(userList.get(pos));
}
});
holder.tvUserName.setText(userList.get(position).getName());
imageDownloader.displayImage(holder.ivPicture,
userList.get(position).getPhotoUrl());
myViews.put(position, view);
}
return view;
}
这篇关于Android的名单适配器返回getView错误的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!