问题描述
我在我的 Android 应用程序中为 ListView 设置了一个 BaseAdapter。每次我单击 ListView 时,单击操作都可以正常工作。但是我点击的元素总是在ListView的顶部。
当我点击 ListView 时,如何让点击的项目保持原位?
这个问题会不会是 BaseAdapter 造成的?
public class TrackAdapter extends BaseAdapter {
private final Context context;
private List<Track> tracks;
public TrackAdapter(List<Track> tracks,Context context) {
this.tracks = tracks;
this.context = context;
}
@Override
public int getCount() {
return tracks.size();
}
@Override
public Object getItem(int position) {
return tracks.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
public void updateAdapter(List<Track> list) {
tracks = list;
this.notifyDataSetChanged();
}
@Override
public View getView(int position,View convertView,ViewGroup parent) {
convertView = LayoutInflater.from(context).inflate(R.layout.track_list_layout,parent,false);
convertView.setBackgroundResource(R.drawable.listview_background);
TextView name = convertView.findViewById(R.id.track_name);
name.setText(tracks.get(position).getName());
TextView bpm = convertView.findViewById(R.id.track_bpm);
bpm.setText(BPMHelper.Combine(tracks.get(position).getMinBpm(),tracks.get(position).getMaxBpm()));
TextView type = convertView.findViewById(R.id.track_type);
type.setText(tracks.get(position).getType());
TextView size = convertView.findViewById(R.id.track_size);
size.setText(tracks.get(position).getSize());
return convertView;
}
}
和
trackList = (ListView) findViewById(R.id.listView);
trackList.setAdapter(trackAdapter);
trackList.setonItemClickListener(new AdapterView.OnItemClickListener() {
// @SuppressLint("ResourceAsColor")
TextView prevIoUsView = null; // to hold the prevIoUs clicked view
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onItemClick(AdapterView<?> parent,View view,int position,long id) {
TextView textView = view.findViewById(R.id.track_name);
if (prevIoUsView != null) {
// revert the prevIoUs view when a new item is clicked
prevIoUsView.setTextColor(Color.YELLOW);
}
prevIoUsView = textView;
textView.setTextColor(Color.RED);
}
});
我在 CoordinatorLayout 中的 ListView
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="587dp"
android:layout_margin="10dp"
android:divider="@color/grey"
android:dividerHeight="10.0sp"
android:scrollbars="none" />
解决方法
首先:阅读 recycling pattern 的工作原理,理解这一点在这里至关重要。不要通过 convertView
行
convertView = LayoutInflater.from(context)...
之后:你不应该改变View
里面的onItemClick
,适配器负责那个,所以你应该通知它一些项目应该用不同的颜色绘制:
public void onItemClick(AdapterView<?> parent,View view,int position,long id) {
trackAdapter.setLastPickedItem(position);
trackAdapter.notifyDataSetChanged(); // force redraw
}
现在你需要在你的适配器中使用 setLastPickedItem
方法,它将存储这个位置以供进一步使用(当重绘发生时)
private int pickedPosition = -1;
public void setLastPickedItem(int position){
pickedPosition = position;
}
在调用 notifyDataSetChanged
后,适配器最终会为每个可见的 getView
再次调用 position
方法,所以在这里你应该检查当前正在绘制的项目 postion
被标记为最后按下
@Override
public View getView(int position,View convertView,ViewGroup parent) {
// current code in here
if(position == pickedPosition) name.setTextColor(Color.RED);
else name.setTextColor(Color.BLUE);
return convertView;
}
由于回收模式始终绘制整个当前状态(在您的情况下始终设置文本颜色),因为先前绘制的项目(回收)可能处于任何其他状态,其外观可能会保持
如果你想保留之前点击过的项目的一些历史记录,那么只需调整 setLastPickedItem
方法,将之前点击过的存储在另一个变量(或所有点击过的数组)中,不要忘记在 { 中检查和绘制这个状态{1}}
在与适配器位置关联的项目点击侦听器上的 Touchlistener 上实现