如何使用 Android 中的歌曲自动移动 Seekbar?
How to automate Seekbar movement with a song in Android?
我知道以前有人问过类似的问题,但其中 none 可以解决我的问题。我正在制作音乐播放器并希望在播放歌曲时自动执行 Seekbar
。我正在使用 RecyclerView
并且 onBindViewHolder
部分中存在以下代码段。
public class ListViewPopulator extends
RecyclerView.Adapter<ListViewPopulator.ViewHolder>{
List<String> musicName;
List<String> musicAdd;
Context context;
MediaPlayer mediaPlayer;
Button media_play;
Button media_stop;
SeekBar seekBar;
final Handler mhandler=new Handler();
TextView timer;
public ListViewPopulator(Activity context, List<String> musicName, List<String> musicAdd)
{
this.context=context;
this.musicName=musicName;
this.musicAdd=musicAdd;
media_play= (Button)context.findViewById(R.id.play);
media_stop=(Button)context.findViewById(R.id.pause);
seekBar= (SeekBar) context.findViewById(R.id.seekbar);
timer=(TextView) context.findViewById(R.id.timer);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.listview,parent,false);
return new ViewHolder(v);
}
void something(String s)
{
try{mediaPlayer.stop();}catch (NullPointerException e){e.printStackTrace();}
//To fetch the location of audio files on disk
mediaPlayer=MediaPlayer.create(context, Uri.fromFile(new File(s)));
mediaPlayer.start();
//seekBar.setProgress(0);
//seekBar.setMax(mediaPlayer.getDuration());
} int temp=0;
int i=0;
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final String s = musicAdd.get(position);
final String v = musicName.get(position);
holder.data.setText(v);
seeker();
cont_seek();
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
temp = position + 1;
something(s);
seekBar.setProgress(0);
seekBar.setMax(mediaPlayer.getDuration());
// mediaPlayer.reset();
change();
op();
}
});
media_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mediaPlayer.start();
Log.d("click", "Kuch bhi");
} catch (NullPointerException e) {
e.printStackTrace();
}
}
});
media_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mediaPlayer.pause();
Log.d("click2", "Kuch bhi2");
} catch (NullPointerException e) {
e.printStackTrace();
}
}
});
}
void cont_seek(){
Log.d("auto","seek");
Runnable runnable=new Runnable() {
@Override
public void run() {
String time;
if((mediaPlayer != null) && mediaPlayer.isPlaying()){
int progress = mediaPlayer.getCurrentPosition();
int min = (progress / 1000) / 60;
Log.d("auto","seek");
int sec = (progress / 1000) % 60;
if (sec < 10)
time = "0" + sec;
else
time = "" + sec;
String elapsedTime = min + ":" + time + "";
timer.setText(elapsedTime);
seekBar.setMax(mediaPlayer.getDuration());
seekBar.setProgress(progress);
mhandler.postDelayed(this, 1000);
}
}
};
mhandler.postDelayed(runnable,1000);
}
void seeker(){
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int seek_progress;
String time_sec;
@Override
public void onProgressChanged(final SeekBar seekBar, int progress, boolean fromUser) {
seek_progress=progress;
//seek_progress=seek_progress*1000;
new Runnable() {
@Override
public void run() {
int min=(seek_progress/1000)/60;
int sec=(seek_progress/1000)%60;
if(sec<10)
time_sec="0"+sec;
else
time_sec=""+sec;
String elapsedTime=min+":"+time_sec+"";
timer.setText(elapsedTime);
//mediaPlayer.seekTo(seek_progress);
new Handler().postDelayed(this,1000);
}
}.run();
if(fromUser) {
Log.d("blah","blah");
new Runnable() {
@Override
public void run() {
int min=(seek_progress/1000)/60;
int sec=(seek_progress/1000)%60;
if(sec<10)
time_sec="0"+sec;
else
time_sec=""+sec;
String elapsedTime=min+":"+time_sec+"";
timer.setText(elapsedTime);
//mediaPlayer.seekTo(seek_progress);
new Handler().postDelayed(this,1000);
}
}.run();
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if(mediaPlayer!=null){mediaPlayer.seekTo(seek_progress);}
}
});
}
int h=0;
void change(){
try{mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if(temp!=musicAdd.size())
something(musicAdd.get(temp));
temp=temp+1;
seekBar.setProgress(0);
seekBar.setMax(mediaPlayer.getDuration());
change();
}
});
}catch(Throwable throwable){throwable.printStackTrace();}}
void op()
{
Sensey.getInstance().startFlipDetection(new FlipDetector.FlipListener() {
@Override
public void onFaceUp() {
if (i == 0) {
try {
mediaPlayer.start();
i = 1;
h=1;
}catch (NullPointerException e){e.printStackTrace();}
}
}
@Override
public void onFaceDown() {
if (i == 1) {
try {
mediaPlayer.pause();
i = 0;
h=0;
}catch (NullPointerException e){e.printStackTrace();}
}
}
});
Sensey.getInstance().startShakeDetection(15, new ShakeDetector.ShakeListener() {
@Override
public void onShakeDetected() {
try {
if(h==1)
something(musicAdd.get(randomG(musicAdd.size()-1,0)));
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
});
}
int randomG(int max,int min)
{
Random random=new Random();
return random.nextInt((max-min)+1);
}
@Override
public int getItemCount() {
return musicName.size();
}
public class ViewHolder extends RecyclerView.ViewHolder
{
TextView data;
public ViewHolder(View itemView) {
super(itemView);
data=(TextView)itemView.findViewById(R.id.data);
}
}
}
我很确定逻辑是正确的并且检查了日志,代码似乎没有执行。有人可以解释为什么吗?
您需要按如下方式使用您的 Handler
& Runnable
:
final Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
//YOUR CODE GOES HERE
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 0);
在你的回收视图适配器中,你可以使用这样的东西:
@Override
public VoiceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return VoiceViewHolder.createVoiceViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.lecture_voice_item_recycler, parent, false));
}
@Override
public void onBindViewHolder(VoiceViewHolder holder, int position) {
holder.bindHolderToVoice(10000, "your path");
}
public static class VoiceViewHolder extends RecyclerView.ViewHolder {
CardView cardView;
TextView voiceDuration;
ImageView voiceView;
ImageButton mPlayButton;
MediaPlayer mPlayer;
RelativeLayout layoutVoice;
RelativeLayout layoutVoiceNotFound;
boolean isPlaying;
TextView voiceDurationPlayer;
double timeElapsed = 0, finalTime = 0;
Handler durationHandler = new Handler();
Runnable updateSeekBarTime;
SeekBar seekBarDuration;
private VoiceViewHolder(final View itemView) {
super(itemView);
}
public static VoiceViewHolder createVoiceViewHolder(View convertView) {
VoiceViewHolder holder = new VoiceViewHolder(convertView);
holder.voiceDuration = (TextView) convertView.findViewById(R.id.voice_duration);
holder.cardView = (CardView) convertView.findViewById(R.id.card_view);
holder.voiceView = (ImageView) convertView.findViewById(R.id.voiceView);
holder.mPlayButton = (ImageButton) convertView.findViewById(R.id.playButton);
holder.layoutVoice = (RelativeLayout) convertView.findViewById(R.id.layoutVoice);
holder.layoutVoiceNotFound = (RelativeLayout) convertView.findViewById(R.id.layoutVoiceNotFound);
holder.voiceDurationPlayer = (TextView) convertView.findViewById(R.id.voiceDurationPlayer);
holder.seekBarDuration = (SeekBar) convertView.findViewById(R.id.seekBarDuration);
holder.isPlaying = false;
holder.mPlayer = new MediaPlayer();
return holder;
}
public void bindHolderToVoice(final long duration, final String path) {
final Context context = itemView.getContext();
if (duration >= 60000) {
voiceDuration.setText(String.format("%d %s, %d %s", TimeUnit.MILLISECONDS.toMinutes(duration), context.getString(R.string.min),
TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)),
context.getString(R.string.sec)));
} else {
voiceDuration.setText(String.format("%d %s",
TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)),
context.getString(R.string.sec)));
}
finalTime = duration;
seekBarDuration.setMax((int) finalTime);
seekBarDuration.setClickable(false);
seekBarDuration.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mPlayer.isPlaying()) {
SeekBar sb = (SeekBar) v;
mPlayer.seekTo(sb.getProgress());
}
return false;
}
});
updateSeekBarTime = new Runnable() {
public void run() {
if (mPlayer != null) {
if (mPlayer.isPlaying()) {
timeElapsed = mPlayer.getCurrentPosition();
seekBarDuration.setProgress((int) timeElapsed);
voiceDurationPlayer.setText(String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes((long) timeElapsed), TimeUnit.MILLISECONDS.toSeconds((long) timeElapsed) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) timeElapsed))));
durationHandler.postDelayed(this, 100);
} else {
mPlayer.pause();
isPlaying = false;
}
}
}
};
File voiceFile = new File(path);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
isPlaying = false;
}
});
mPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isPlaying) {
isPlaying = true;
try {
mPlayer = new MediaPlayer();
mPlayer.setDataSource(path);
mPlayer.prepare();
} catch (IOException e) {
Log.e("tag", "Start playing prepare() failed");
isPlaying = false;
}
mPlayer.start();
timeElapsed = mPlayer.getCurrentPosition();
seekBarDuration.setProgress((int) timeElapsed);
durationHandler.postDelayed(updateSeekBarTime, 100);
} else {
isPlaying = false;
mPlayer.pause();
}
}
});
}
}
布局lecture_voice_item_recycler.xml是这样的:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lecture_voice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/lecture_voice__margin_card">
<android.support.v7.widget.CardView
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/lecture_voice__margin_card"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/lecture_voice__margin_card"
android:layout_marginBottom="@dimen/lecture_voice__margin_card">
<LinearLayout
android:id="@+id/layoutVoiceInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/grid_annotation_margin"
android:orientation="horizontal">
<TextView
android:id="@+id/voice_duration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<RelativeLayout
android:id="@+id/layoutVoice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/layoutVoiceInfo"
android:gravity="center_vertical"
android:layout_marginLeft="@dimen/activity_horizontal_margin">
<ImageButton
android:id="@+id/playButton"
android:layout_width="@dimen/lecture_voice_icon"
android:layout_height="@dimen/lecture_voice_icon"
android:background="@android:color/transparent"
android:scaleType="fitXY"
android:src="@drawable/ic_play" />
<LinearLayout
android:id="@+id/layoutVoiceSeekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toRightOf="@+id/playButton"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_horizontal_margin">
<SeekBar
android:id="@+id/seekBarDuration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin" />
<TextView
android:id="@+id/voiceDurationPlayer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:layout_gravity="right"
android:layout_marginRight="@dimen/lecture_voice_text_duration_margin_right"/>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/layoutVoiceNotFound"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/layoutVoiceInfo"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:visibility="gone">
<ImageView
android:id="@+id/voiceView"
android:layout_width="@dimen/lecture_voice_icon"
android:layout_height="@dimen/lecture_voice_icon"
android:src="@drawable/voice_not_found"
android:scaleType="fitXY" />
<TextView
android:id="@+id/voiceNotFound"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/voiceView"
android:layout_centerInParent="true"
android:text="@string/voice_not_found"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
strings.xml
<string name="min">min</string>
<string name="sec">sec</string>
注意:示例中可能会丢失一些尺寸或可绘制对象。如果没有编译,你应该使用你自己的维度。
找到解决方案。
Runnable runnable=new Runnable() {
@Override
public void run() {
String time;
Log.d(TAG, "run");
while(mediaPlayer != null && mediaPlayer.isPlaying()){
final int progress = mediaPlayer.getCurrentPosition();
int min = (progress / 1000) / 60;
Log.d("auto","seek");
int sec = (progress / 1000) % 60;
if (sec < 10)
time = "0" + sec;
else
time = "" + sec;
final String elapsedTime = min + ":" + time + "";
context.runOnUiThread(new Runnable() {
@Override
public void run() {
timer.setText(elapsedTime);
seekBar.setMax(mediaPlayer.getDuration());
seekBar.setProgress(progress);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
这里的主要问题是,一旦 mediaplayer.start()
被调用,媒体文件就开始在播放器中加载,然后完成 cont_seek
函数被调用,其条件为
if(mediaplayer!=null && mediaplayer.isplaying())
由于媒体还没有开始播放,条件失败,函数永远不会执行。
已通过 运行 另一个线程中的 runnable
修复了它。
我知道以前有人问过类似的问题,但其中 none 可以解决我的问题。我正在制作音乐播放器并希望在播放歌曲时自动执行 Seekbar
。我正在使用 RecyclerView
并且 onBindViewHolder
部分中存在以下代码段。
public class ListViewPopulator extends
RecyclerView.Adapter<ListViewPopulator.ViewHolder>{
List<String> musicName;
List<String> musicAdd;
Context context;
MediaPlayer mediaPlayer;
Button media_play;
Button media_stop;
SeekBar seekBar;
final Handler mhandler=new Handler();
TextView timer;
public ListViewPopulator(Activity context, List<String> musicName, List<String> musicAdd)
{
this.context=context;
this.musicName=musicName;
this.musicAdd=musicAdd;
media_play= (Button)context.findViewById(R.id.play);
media_stop=(Button)context.findViewById(R.id.pause);
seekBar= (SeekBar) context.findViewById(R.id.seekbar);
timer=(TextView) context.findViewById(R.id.timer);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.listview,parent,false);
return new ViewHolder(v);
}
void something(String s)
{
try{mediaPlayer.stop();}catch (NullPointerException e){e.printStackTrace();}
//To fetch the location of audio files on disk
mediaPlayer=MediaPlayer.create(context, Uri.fromFile(new File(s)));
mediaPlayer.start();
//seekBar.setProgress(0);
//seekBar.setMax(mediaPlayer.getDuration());
} int temp=0;
int i=0;
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final String s = musicAdd.get(position);
final String v = musicName.get(position);
holder.data.setText(v);
seeker();
cont_seek();
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
temp = position + 1;
something(s);
seekBar.setProgress(0);
seekBar.setMax(mediaPlayer.getDuration());
// mediaPlayer.reset();
change();
op();
}
});
media_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mediaPlayer.start();
Log.d("click", "Kuch bhi");
} catch (NullPointerException e) {
e.printStackTrace();
}
}
});
media_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mediaPlayer.pause();
Log.d("click2", "Kuch bhi2");
} catch (NullPointerException e) {
e.printStackTrace();
}
}
});
}
void cont_seek(){
Log.d("auto","seek");
Runnable runnable=new Runnable() {
@Override
public void run() {
String time;
if((mediaPlayer != null) && mediaPlayer.isPlaying()){
int progress = mediaPlayer.getCurrentPosition();
int min = (progress / 1000) / 60;
Log.d("auto","seek");
int sec = (progress / 1000) % 60;
if (sec < 10)
time = "0" + sec;
else
time = "" + sec;
String elapsedTime = min + ":" + time + "";
timer.setText(elapsedTime);
seekBar.setMax(mediaPlayer.getDuration());
seekBar.setProgress(progress);
mhandler.postDelayed(this, 1000);
}
}
};
mhandler.postDelayed(runnable,1000);
}
void seeker(){
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int seek_progress;
String time_sec;
@Override
public void onProgressChanged(final SeekBar seekBar, int progress, boolean fromUser) {
seek_progress=progress;
//seek_progress=seek_progress*1000;
new Runnable() {
@Override
public void run() {
int min=(seek_progress/1000)/60;
int sec=(seek_progress/1000)%60;
if(sec<10)
time_sec="0"+sec;
else
time_sec=""+sec;
String elapsedTime=min+":"+time_sec+"";
timer.setText(elapsedTime);
//mediaPlayer.seekTo(seek_progress);
new Handler().postDelayed(this,1000);
}
}.run();
if(fromUser) {
Log.d("blah","blah");
new Runnable() {
@Override
public void run() {
int min=(seek_progress/1000)/60;
int sec=(seek_progress/1000)%60;
if(sec<10)
time_sec="0"+sec;
else
time_sec=""+sec;
String elapsedTime=min+":"+time_sec+"";
timer.setText(elapsedTime);
//mediaPlayer.seekTo(seek_progress);
new Handler().postDelayed(this,1000);
}
}.run();
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if(mediaPlayer!=null){mediaPlayer.seekTo(seek_progress);}
}
});
}
int h=0;
void change(){
try{mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if(temp!=musicAdd.size())
something(musicAdd.get(temp));
temp=temp+1;
seekBar.setProgress(0);
seekBar.setMax(mediaPlayer.getDuration());
change();
}
});
}catch(Throwable throwable){throwable.printStackTrace();}}
void op()
{
Sensey.getInstance().startFlipDetection(new FlipDetector.FlipListener() {
@Override
public void onFaceUp() {
if (i == 0) {
try {
mediaPlayer.start();
i = 1;
h=1;
}catch (NullPointerException e){e.printStackTrace();}
}
}
@Override
public void onFaceDown() {
if (i == 1) {
try {
mediaPlayer.pause();
i = 0;
h=0;
}catch (NullPointerException e){e.printStackTrace();}
}
}
});
Sensey.getInstance().startShakeDetection(15, new ShakeDetector.ShakeListener() {
@Override
public void onShakeDetected() {
try {
if(h==1)
something(musicAdd.get(randomG(musicAdd.size()-1,0)));
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
});
}
int randomG(int max,int min)
{
Random random=new Random();
return random.nextInt((max-min)+1);
}
@Override
public int getItemCount() {
return musicName.size();
}
public class ViewHolder extends RecyclerView.ViewHolder
{
TextView data;
public ViewHolder(View itemView) {
super(itemView);
data=(TextView)itemView.findViewById(R.id.data);
}
}
}
我很确定逻辑是正确的并且检查了日志,代码似乎没有执行。有人可以解释为什么吗?
您需要按如下方式使用您的 Handler
& Runnable
:
final Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
//YOUR CODE GOES HERE
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 0);
在你的回收视图适配器中,你可以使用这样的东西:
@Override
public VoiceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return VoiceViewHolder.createVoiceViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.lecture_voice_item_recycler, parent, false));
}
@Override
public void onBindViewHolder(VoiceViewHolder holder, int position) {
holder.bindHolderToVoice(10000, "your path");
}
public static class VoiceViewHolder extends RecyclerView.ViewHolder {
CardView cardView;
TextView voiceDuration;
ImageView voiceView;
ImageButton mPlayButton;
MediaPlayer mPlayer;
RelativeLayout layoutVoice;
RelativeLayout layoutVoiceNotFound;
boolean isPlaying;
TextView voiceDurationPlayer;
double timeElapsed = 0, finalTime = 0;
Handler durationHandler = new Handler();
Runnable updateSeekBarTime;
SeekBar seekBarDuration;
private VoiceViewHolder(final View itemView) {
super(itemView);
}
public static VoiceViewHolder createVoiceViewHolder(View convertView) {
VoiceViewHolder holder = new VoiceViewHolder(convertView);
holder.voiceDuration = (TextView) convertView.findViewById(R.id.voice_duration);
holder.cardView = (CardView) convertView.findViewById(R.id.card_view);
holder.voiceView = (ImageView) convertView.findViewById(R.id.voiceView);
holder.mPlayButton = (ImageButton) convertView.findViewById(R.id.playButton);
holder.layoutVoice = (RelativeLayout) convertView.findViewById(R.id.layoutVoice);
holder.layoutVoiceNotFound = (RelativeLayout) convertView.findViewById(R.id.layoutVoiceNotFound);
holder.voiceDurationPlayer = (TextView) convertView.findViewById(R.id.voiceDurationPlayer);
holder.seekBarDuration = (SeekBar) convertView.findViewById(R.id.seekBarDuration);
holder.isPlaying = false;
holder.mPlayer = new MediaPlayer();
return holder;
}
public void bindHolderToVoice(final long duration, final String path) {
final Context context = itemView.getContext();
if (duration >= 60000) {
voiceDuration.setText(String.format("%d %s, %d %s", TimeUnit.MILLISECONDS.toMinutes(duration), context.getString(R.string.min),
TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)),
context.getString(R.string.sec)));
} else {
voiceDuration.setText(String.format("%d %s",
TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)),
context.getString(R.string.sec)));
}
finalTime = duration;
seekBarDuration.setMax((int) finalTime);
seekBarDuration.setClickable(false);
seekBarDuration.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mPlayer.isPlaying()) {
SeekBar sb = (SeekBar) v;
mPlayer.seekTo(sb.getProgress());
}
return false;
}
});
updateSeekBarTime = new Runnable() {
public void run() {
if (mPlayer != null) {
if (mPlayer.isPlaying()) {
timeElapsed = mPlayer.getCurrentPosition();
seekBarDuration.setProgress((int) timeElapsed);
voiceDurationPlayer.setText(String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes((long) timeElapsed), TimeUnit.MILLISECONDS.toSeconds((long) timeElapsed) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) timeElapsed))));
durationHandler.postDelayed(this, 100);
} else {
mPlayer.pause();
isPlaying = false;
}
}
}
};
File voiceFile = new File(path);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
isPlaying = false;
}
});
mPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isPlaying) {
isPlaying = true;
try {
mPlayer = new MediaPlayer();
mPlayer.setDataSource(path);
mPlayer.prepare();
} catch (IOException e) {
Log.e("tag", "Start playing prepare() failed");
isPlaying = false;
}
mPlayer.start();
timeElapsed = mPlayer.getCurrentPosition();
seekBarDuration.setProgress((int) timeElapsed);
durationHandler.postDelayed(updateSeekBarTime, 100);
} else {
isPlaying = false;
mPlayer.pause();
}
}
});
}
}
布局lecture_voice_item_recycler.xml是这样的:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lecture_voice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/lecture_voice__margin_card">
<android.support.v7.widget.CardView
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/lecture_voice__margin_card"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/lecture_voice__margin_card"
android:layout_marginBottom="@dimen/lecture_voice__margin_card">
<LinearLayout
android:id="@+id/layoutVoiceInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/grid_annotation_margin"
android:orientation="horizontal">
<TextView
android:id="@+id/voice_duration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<RelativeLayout
android:id="@+id/layoutVoice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/layoutVoiceInfo"
android:gravity="center_vertical"
android:layout_marginLeft="@dimen/activity_horizontal_margin">
<ImageButton
android:id="@+id/playButton"
android:layout_width="@dimen/lecture_voice_icon"
android:layout_height="@dimen/lecture_voice_icon"
android:background="@android:color/transparent"
android:scaleType="fitXY"
android:src="@drawable/ic_play" />
<LinearLayout
android:id="@+id/layoutVoiceSeekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toRightOf="@+id/playButton"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_horizontal_margin">
<SeekBar
android:id="@+id/seekBarDuration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin" />
<TextView
android:id="@+id/voiceDurationPlayer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:layout_gravity="right"
android:layout_marginRight="@dimen/lecture_voice_text_duration_margin_right"/>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/layoutVoiceNotFound"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/layoutVoiceInfo"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:visibility="gone">
<ImageView
android:id="@+id/voiceView"
android:layout_width="@dimen/lecture_voice_icon"
android:layout_height="@dimen/lecture_voice_icon"
android:src="@drawable/voice_not_found"
android:scaleType="fitXY" />
<TextView
android:id="@+id/voiceNotFound"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/voiceView"
android:layout_centerInParent="true"
android:text="@string/voice_not_found"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
strings.xml
<string name="min">min</string>
<string name="sec">sec</string>
注意:示例中可能会丢失一些尺寸或可绘制对象。如果没有编译,你应该使用你自己的维度。
找到解决方案。
Runnable runnable=new Runnable() {
@Override
public void run() {
String time;
Log.d(TAG, "run");
while(mediaPlayer != null && mediaPlayer.isPlaying()){
final int progress = mediaPlayer.getCurrentPosition();
int min = (progress / 1000) / 60;
Log.d("auto","seek");
int sec = (progress / 1000) % 60;
if (sec < 10)
time = "0" + sec;
else
time = "" + sec;
final String elapsedTime = min + ":" + time + "";
context.runOnUiThread(new Runnable() {
@Override
public void run() {
timer.setText(elapsedTime);
seekBar.setMax(mediaPlayer.getDuration());
seekBar.setProgress(progress);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
这里的主要问题是,一旦 mediaplayer.start()
被调用,媒体文件就开始在播放器中加载,然后完成 cont_seek
函数被调用,其条件为
if(mediaplayer!=null && mediaplayer.isplaying())
由于媒体还没有开始播放,条件失败,函数永远不会执行。
已通过 运行 另一个线程中的 runnable
修复了它。