Android ListView点击图标后同奇偶项图标异常同步问题求助
Android ListView点击图标播放音频并切换图标异常修复
问题现象
点击ListView项的图标时,对应项图标正常切换,但所有奇数/偶数位置的图标会同步变为相同状态,无法仅保持点击项的状态变化。
问题根源
- ListView复用机制:ListView会复用滑出屏幕的View,Adapter中使用的全局状态变量(如
flag、first)是共享状态,无法对应单个Item的独立状态。 - 状态未绑定数据:
getView方法中仅在点击时修改图标,未根据当前Item的实际播放状态初始化图标,复用View时会继承错误状态。
修复方案
1. 给数据类添加独立状态字段
在VerseData中添加isPlaying字段,记录每个Item的播放状态:
public class VerseData { // 原有字段 private String number; private String arabic; private String english; private int audio; // 新增播放状态字段 private boolean isPlaying; // 构造方法 public VerseData(String number, String arabic, String english, int audio) { this.number = number; this.arabic = arabic; this.english = english; this.audio = audio; this.isPlaying = false; // 默认未播放 } // Getter & Setter public boolean isPlaying() { return isPlaying; } public void setPlaying(boolean playing) { isPlaying = playing; } // 其他原有Getter方法 public String getNumber() { return number; } public String getArabic() { return arabic; } public String getEnglish() { return english; } public int getAudio() { return audio; } }
2. 修改Adapter代码,绑定状态到数据
移除全局共享状态变量,将播放状态与每个Item的数据绑定,确保getView每次绘制时根据数据状态设置图标:
public class AllAudioAdapter extends BaseAdapter { private Context context; private int layout; private ArrayList<VerseData> arrayList; private MediaPlayer mediaPlayer; private int currentPlayingPosition = -1; // 记录当前播放位置 public AllAudioAdapter(Context context, int layout, ArrayList<VerseData> arrayList) { this.context = context; this.layout = layout; this.arrayList = arrayList; } @Override public int getCount() { return arrayList.size(); } @Override public Object getItem(int position) { return arrayList.get(position); } @Override public long getItemId(int position) { return position; } public static class ViewHolder { public TextView number, eng_text, arabic_text; public ImageView ivPlay; public RelativeLayout relativeLayout; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { viewHolder = new ViewHolder(); LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = layoutInflater.inflate(layout, parent, false); viewHolder.number = convertView.findViewById(R.id.number); viewHolder.arabic_text = convertView.findViewById(R.id.arabic_text); viewHolder.eng_text = convertView.findViewById(R.id.eng_text); viewHolder.ivPlay = convertView.findViewById(R.id.play_pic); viewHolder.relativeLayout = convertView.findViewById(R.id.relative); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } VerseData verseData = arrayList.get(position); // 设置文本内容 viewHolder.number.setText(verseData.getNumber()); viewHolder.arabic_text.setText(verseData.getArabic()); viewHolder.eng_text.setText(verseData.getEnglish()); // 根据Item的播放状态设置图标 if (verseData.isPlaying()) { viewHolder.ivPlay.setImageResource(R.drawable.play); } else { viewHolder.ivPlay.setImageResource(R.drawable.stop); } // 点击事件处理 viewHolder.ivPlay.setOnClickListener(v -> { if (currentPlayingPosition == position) { // 点击当前播放项:切换播放/暂停 if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); verseData.setPlaying(false); viewHolder.ivPlay.setImageResource(R.drawable.stop); } else { mediaPlayer.start(); verseData.setPlaying(true); viewHolder.ivPlay.setImageResource(R.drawable.play); } } else { // 点击新项:停止之前的播放,启动新播放 stopCurrentPlaying(); mediaPlayer = MediaPlayer.create(context, verseData.getAudio()); mediaPlayer.start(); verseData.setPlaying(true); // 更新之前播放项的状态 if (currentPlayingPosition != -1) { arrayList.get(currentPlayingPosition).setPlaying(false); } currentPlayingPosition = position; // 刷新列表,同步所有Item状态 notifyDataSetChanged(); } }); return convertView; } // 停止当前播放并释放资源 private void stopCurrentPlaying() { if (mediaPlayer != null) { if (mediaPlayer.isPlaying()) mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer = null; } } // 外部调用:页面销毁时释放资源 public void releaseMediaPlayer() { stopCurrentPlaying(); } }
关键修改说明
- 每个Item的播放状态存储在
VerseData对象中,避免全局变量导致的状态混乱。 getView方法每次绘制Item时,都会根据verseData.isPlaying()设置正确图标,解决View复用的状态继承问题。- 用
currentPlayingPosition跟踪当前播放项,切换时更新旧项状态并刷新列表,确保界面状态同步。 - 添加
releaseMediaPlayer()方法,建议在Activity/Fragment的onDestroy中调用,避免MediaPlayer内存泄漏。
内容的提问来源于stack exchange,提问作者FA20-BSE-017 SYED ALI HAIDER S
相关产品推荐
相关产品推荐

