gpt4 book ai didi

android - ListView 中与 MediaPlayer 关联的多个 SeekBar

转载 作者:行者123 更新时间:2023-11-30 01:25:25 24 4
gpt4 key购买 nike

我有一个显示语音消息的 ListView(就像 WhatsApp 的一样),我正在使用 BaseAdapter,我的布局包含一个播放 按钮 和一个 SeekBar。我想要的是在点击播放 按钮 时播放音频,并更新 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。在您的 Activity 中只有一个 MediaPlayer 实例。每次在 ListView 中单击“播放”按钮时,您都会执行以下操作:

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

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

MainActivity 也应该是实现可运行更新的那个。此时您可能只想使用普通的 SeekBar。要更新正确的 View ,您需要先确定它是否可见,因为用户可能已经滚动到不同的位置,所以您需要在 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 的 View ,但前提是它可见,否则返回 null。在你的 update runnable 中你应该调用它,如果结果不为空,你更新 SeekBar

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

关于android - ListView 中与 MediaPlayer 关联的多个 SeekBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36485647/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com