You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android ListView点击图标后同奇偶项图标异常同步问题求助

Android ListView点击图标播放音频并切换图标异常修复

问题现象

点击ListView项的图标时,对应项图标正常切换,但所有奇数/偶数位置的图标会同步变为相同状态,无法仅保持点击项的状态变化。

问题根源

  1. ListView复用机制:ListView会复用滑出屏幕的View,Adapter中使用的全局状态变量(如flag、first)是共享状态,无法对应单个Item的独立状态。
  2. 状态未绑定数据: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:54:51