繁体   English   中英

ListView 中与 MediaPlayer 关联的多个 SeekBar

[英]Multiple SeekBars associated with MediaPlayer in ListView

我有一个显示语音消息的ListView (就像 WhatsApp 的),我使用的是BaseAdapter ,我的布局包含一个播放button和一个SeekBar 我想要的是点击播放button播放音频,并更新SeekBar

所以我实现了这个自定义的SeekBar ,它会自我更新。

SelfUpdatingSeekBar.java :

public class SelfUpdatingSeekBar extends SeekBar {

MediaPlayer mp;
boolean mActive;


public void setMediaPlayer(MediaPlayer mp){
    this.mp = mp;
}


Runnable mUpdate = new Runnable() {
    @Override
    public void run() {
        long totalDuration = mp.getDuration();
        long currentDuration = mp.getCurrentPosition();

        // Updating progress bar
        int progress = (int)(getProgressPercentage(currentDuration, totalDuration));
        setProgress(progress);
        postDelayed(this, 100);
    }
} ;

public void setActive(int progress) {
    if (!mActive) {
        mActive = true;
        removeCallbacks(mUpdate);
        setProgress(progress);
        post(mUpdate);
    }
}

public void setInactive(int progress) {
    if (mActive) {
        mActive = false;
        removeCallbacks(mUpdate);
    }
    setProgress(progress);
}



public SelfUpdatingSeekBar(Context context) {
    super(context);
}

public SelfUpdatingSeekBar(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public SelfUpdatingSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

public SelfUpdatingSeekBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}



public int getProgressPercentage(long currentDuration, long totalDuration){
    Double percentage = (double) 0;

    long currentSeconds = (int) (currentDuration / 1000);
    long totalSeconds = (int) (totalDuration / 1000);

    // calculating percentage
    percentage =(((double)currentSeconds)/totalSeconds)*100;

    // return percentage
    return percentage.intValue();
}

}

这是我的getView()样子:

public View getView(final int i, View convertView, ViewGroup viewGroup){

    final ViewHolder viewHolder;



    if(convertView == null){
        LayoutInflater inflater = ((MainActivity) context).getLayoutInflater();
        viewHolder = new ViewHolder();
        convertView = inflater.inflate(R.layout.sent_voice_bubble, viewGroup, false);

        viewHolder.sent_voice_seekbar = (SelfUpdatingSeekBar) convertView.findViewById(R.id.sent_seekbar);
        viewHolder.sent_voice_seekbar.setMediaPlayer(mMediaPlayer);
        viewHolder.sent_voice_play = (ImageView) convertView.findViewById(R.id.sent_playAudio);
        viewHolder.sent_voice_container = convertView.findViewById(R.id.sent_vmessagesection);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(((int)(x * 0.7f)), RelativeLayout.LayoutParams.WRAP_CONTENT);
        params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
        viewHolder.sent_voice_container.setLayoutParams(params);

        convertView.setTag(viewHolder);
    }else{
        viewHolder = (ViewHolder) convertView.getTag();
    }


            viewHolder.sent_voice_play.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                // Check if the Item is currently playing 
                    if(list.get(i).isPlaying()){
                        // Stop audio and save  progress
                        stopItemAudio(list.get(i), viewHolder.sent_voice_seekbar);
                        // Change button's image to Pause ||
                        ((ImageView) v).setImageDrawable(((MainActivity) context).pauseDrawable);

                    }else{
                        // Start audio and update the SeekBar
                        playItemAudio(list.get(i), viewHolder.sent_voice_seekbar);
                        // Change button's image to Play >
                        ((ImageView) v).setImageDrawable(((MainActivity) context).playDrawable);
                    }
                }
            });

            if(list.get(i).isPlaying()){
                viewHolder.sent_voice_seekbar.setActive(list.get(i).seekbar_resume_position);
                viewHolder.sent_voice_play.setImageDrawable(((MainActivity) context).pauseDrawable);
            }else{
                viewHolder.sent_voice_seekbar.setInactive(list.get(i).seekbar_resume_position);
                viewHolder.sent_voice_play.setImageDrawable(((MainActivity) context).playDrawable);
            }


    return convertView;
}




public void stopItemAudio(AudioRow item, SelfUpdatingSeekBar seekBar){

    if(mMediaPlayer == null){
        mMediaPlayer = new MediaPlayer();
    }

    mMediaPlayer.stop();
    item.setPlaying(false);
    int percentage = getProgressPercentage(mMediaPlayer.getCurrentPosition(), mMediaPlayer.getDuration());

    item.setSeekBarResumePosition(percentage);
    item.setMediaPlayerResumePosition(mMediaPlayer.getCurrentPosition());
    seekBar.setInactive(percentage);
    notifyDataSetChanged();

}
public void playItemAudio(final AudioRow item, SelfUpdatingSeekBar seekBar){
    if(mMediaPlayer == null){
        mMediaPlayer = new MediaPlayer();
    }

    try {
        mMediaPlayer.reset();
        mMediaPlayer.setDataSource(item.audioPath);
        mMediaPlayer.prepare();
        mMediaPlayer.seekTo(item.mediaPlayer_resume_position);
        seekBar.setActive(item.seekbar_resume_position); // Starts from where it stopped
        mMediaPlayer.start();

        // declaring Item started to play
        item.setPlaying(true);
        notifyDataSetChanged();

        mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                item.setSeekBarResumePosition(0);
                item.setPlaying(false);
            }
        });
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalStateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }



public int getProgressPercentage(long currentDuration, long totalDuration){
    Double percentage = (double) 0;

    long currentSeconds = (int) (currentDuration / 1000);
    long totalSeconds = (int) (totalDuration / 1000);

    // calculating percentage
    percentage =(((double)currentSeconds)/totalSeconds)*100;

    // return percentage
    return percentage.intValue();
}

}

问题是当我点击Item1 ,它开始播放,并同时点击Item2两个 SeekBars 动画,这是预期的,因为我没有在点击Item2停止Item1

我的问题是:

  • 单击Item2停止先前播放的Item1的正确方法是什么?

您的SeekBar实现不应有自己的MediaPlayer 在您的活动中只有一个MediaPlayer实例。 每次在列表视图中单击“播放”按钮时,您都会执行以下操作:

MediaPlayer mMediaPlayer = ((MainActivity) context).getSingleMediaPlayer();
((MainActivity) context).setCurrentlyPlayingItem(i);
mMediaPlayer.reset();
mMediaPlayer.setDataSource(item.audioPath);
mMediaPlayer.prepare();
notifyDatasetHasChanged()

现在在您的getView()实现上,如果第一个参数: i不等于MainActivity当前播放的项目,则它的SeekBar应该为零。

MainActivity也应该是实现更新 runnable 的那个。 此时您可能只想使用普通的SeekBar 要更新正确的视图,您需要首先确定它是否可见,因为用户可能已经滚动到不同的位置,因此您需要在MainActivity此函数:

public View getVisibleItemView(int position){
        if(listview.getCount() > 0) {
            int start = listview.getFirstVisiblePosition();
            for (int i = start, j = listview.getLastVisiblePosition(); i <= j; i++) {
                if (i == position) {
                    return listview.getChildAt(i - start);
                }
            }
        }
        return null;
    }

此函数返回带有您要更新的SeekBar的视图,但SeekBar是它是可见的,否则返回 null。 在您的更新 runnable 中,您应该调用它,如果结果不为空,则更新SeekBar

此外,您可能需要考虑使用接口而不是将上下文引用转换为适配器中的MainActivity

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM