我需要在我的应用程序中将我的SeekBar
与我的MediaPlayer
连接起来。
我通过xml设置SeekBar,如下所示:
<SeekBar
android:id="@+id/song_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"/>
并遵循这个SO答案来实现它。
这是我的代码:
public class Song_main extends AppCompatActivity {
private final int SONG_REQUEST_CODE = 1;
private Uri song;
private TextView selectSong;
private SeekBar seekBar;
private Handler handler;
private MediaPlayer mediaPlayer;
private boolean repeatPressedTwice = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_bar_song_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.song_main_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
seekBar = (SeekBar) findViewById(R.id.song_seekbar);
handler = new Handler();
notSelected();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.song, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.song_plus) {
Intent selectIntent = new Intent(Intent.ACTION_GET_CONTENT);
selectIntent.setType("audio/*");
startActivityForResult(selectIntent, SONG_REQUEST_CODE);
}
return true;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SONG_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
if ((data != null) && (data.getData()!=null)) {
song = data.getData();
setup();
}
}
}
private void notSelected() {
selectSong = (TextView) findViewById(R.id.select_song_textview);
selectSong.setText(getResources().getString(R.string.song_not_selected));
}
public void onPlayButtonClicked(View v) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
pb.setImageResource(R.drawable.pause);
updateSeekBar();
} else {
mediaPlayer.pause();
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
}
public void onControlsClicked(View v) {
if (v.getId() == R.id.fast_forward) {
int pos = mediaPlayer.getCurrentPosition();
pos += 1500;
mediaPlayer.seekTo(pos);
}
else if (v.getId() == R.id.fast_backward) {
int pos = mediaPlayer.getCurrentPosition();
pos -= 1500;
mediaPlayer.seekTo(pos);
}
else if (v.getId() == R.id.skip_backward) {
mediaPlayer.seekTo(0);
}
}
public void onRepeatClicked(View v) {
if (!repeatPressedTwice) {
// TODO: change visual color of repeat button
mediaPlayer.setLooping(true);
Toast.makeText(this, "repeat enabled", Toast.LENGTH_SHORT).show();
repeatPressedTwice = true;
} else {
mediaPlayer.setLooping(false);
}
}
private void setup() {
/* the song has been select setup the interface */
/* displays song name in title */
TextView titleView = (TextView) findViewById(R.id.song_appbar_title);
String songName;
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(song, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
songName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
titleView.setText(songName);
}
/* removes the notSelected String */
selectSong.setVisibility(View.GONE);
/* setup media player */
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(getApplicationContext(), song);
mediaPlayer.prepareAsync();
} catch (IOException e) {
Toast.makeText(this, "file not found", Toast.LENGTH_SHORT).show();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
/* show media player layout */
RelativeLayout mpl = (RelativeLayout) findViewById(R.id.media_player_layout);
mpl.setVisibility(View.VISIBLE);
mediaPlayer.start();
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.pause);
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
});
seekBar = (SeekBar) findViewById(R.id.song_seekbar);
seekBar.setMax(mediaPlayer.getDuration());
updateSeekBar();
}
private void updateSeekBar() {
seekBar.setProgress(mediaPlayer.getCurrentPosition()/1000);
handler.postDelayed(runnable, 1000);
}
Runnable runnable = new Runnable() {
@Override
public void run() {
updateSeekBar();
}
};
@Override
public void onStop() {
super.onStop();
if (mediaPlayer!=null)
mediaPlayer.stop();
}
}
该过程从onOptionsItemSelected
方法开始。
seekBar操作正常,每秒递增一次。现在的问题是,它在歌曲结束之前就结束了。
我试着加上
seekBar.setMax(mediaPlayer.getDuration());
在set
方法中,但这会导致条根本不移动。
您已经实现了OnSeekBarChangeListener
,并且在oncreate()
中添加以下行:-
seekBar = (SeekBar) findViewById(R.id.seekBar);
并重写onProgressChanged()
方法,在该方法中,您可以使用以下行在seekbar中设置进度:
mPlayer.seekTo(progress);
seekBar.setProgress(progress);
或者
初始化MediaPlayer并按下play(播放)按钮后,您应该创建一个处理程序,并将其设置为post runnable(可运行),以便使用MediaPlayer的当前位置更新SeekBar(在UI线程中),如下所示:
private Handler mHandler = new Handler();
//Make sure you update Seekbar on UI thread
MainActivity.this.runOnUiThread(new Runnable(){
@Override
public void run() {
if(mMediaPlayer != null){
int mCurrentPosition = mMediaPlayer.getCurrentPosition() / 1000;
mSeekBar.setProgress(mCurrentPosition);
}
mHandler.postDelayed(this, 1000);
}
});
并每秒更新该值。
如果您需要在用户拖动搜索杆时更新MediaPlayer的位置,您应该在搜索杆上添加onseekbarchaneglistener
,并在那里进行操作:
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(mMediaPlayer != null && fromUser){
mMediaPlayer.seekTo(progress * 1000);
}
}
});
当您播放歌曲时,您需要更新您的Seek栏
public void updateProgressBar() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mHandler.postDelayed(mUpdateTimeTask, 100);
}
});
}
下面的Runnable方法更新搜索栏
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
if (MusicService.isRunning()) {
duration = MusicService.getDur();
long currSongPosition = MusicService.getPosn();
totTime.setText(Utility.milliSecondsToTimer(duration));
fromTime.setText(Utility.milliSecondsToTimer(currSongPosition));
int progress = Utility.getProgressPercentage(currSongPosition, duration);
songProgressBar.setProgress(progress);
updateProgressBar();
}
}
};
使用下面的函数,您可以从歌曲当前位置和歌曲持续时间获得进度百分比
public static int getProgressPercentage(long currentDuration, long totalDuration) {
Double percentage;
long currentSeconds = (int) (currentDuration / 1000);
long totalSeconds = (int) (totalDuration / 1000);
percentage = (((double) currentSeconds) / totalSeconds) * 100;
return percentage.intValue();
}
您需要定义单独的Runnable
,并在MediaPlayer
启动后每x毫秒(取决于您)触发一次。
定义一个函数updateSeekbar
,
private void updateSeekBar() {
audioSeek.setProgress(player.getCurrentPosition());
txtCurrentTime.setText(milliSecondsToTimer(player.getCurrentPosition()));
seekHandler.postDelayed(runnable, 50);
}
和Runnable
Runnable runnable = new Runnable() {
@Override
public void run() {
updateSeekBar();
}
};
现在你只需要在播放开始时调用一次updateSeekbar。就你而言:
public void onPlayButtonClicked(View v) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
pb.setImageResource(R.drawable.pause);
updateSeekBar();
} else {
mediaPlayer.pause();
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
}
供参考
函数millissecondstotimer
的工作原理如下
private String milliSecondsToTimer(long milliseconds) {
String finalTimerString = "";
String secondsString = "";
// Convert total duration into time
int hours = (int) (milliseconds / (1000 * 60 * 60));
int minutes = (int) (milliseconds % (1000 * 60 * 60)) / (1000 * 60);
int seconds = (int) ((milliseconds % (1000 * 60 * 60)) % (1000 * 60) / 1000);
// Add hours if there
if (hours > 0) {
finalTimerString = hours + ":";
}
// Prepending 0 to seconds if it is one digit
if (seconds < 10) {
secondsString = "0" + seconds;
} else {
secondsString = "" + seconds;
}
finalTimerString = finalTimerString + minutes + ":" + secondsString;
// return timer string
return finalTimerString;
}
更新
您在错误的地方调用了setMax
。更新以下函数
private void setup() {
/* the song has been select setup the interface */
/* displays song name in title */
TextView titleView = (TextView) findViewById(R.id.song_appbar_title);
String songName;
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(song, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
songName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
titleView.setText(songName);
}
/* removes the notSelected String */
selectSong.setVisibility(View.GONE);
/* setup media player */
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(getApplicationContext(), song);
mediaPlayer.prepareAsync();
} catch (IOException e) {
Toast.makeText(this, "file not found", Toast.LENGTH_SHORT).show();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
/* show media player layout */
seekBar.setMax(mediaPlayer.getDuration());
RelativeLayout mpl = (RelativeLayout) findViewById(R.id.media_player_layout);
mpl.setVisibility(View.VISIBLE);
mediaPlayer.start();
updateSeekBar();
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.pause);
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
});
}
问题内容: 如何定义SeekBar的最小值?这是在XML布局中完成的还是我需要以编程方式定义它? 基本上我需要将最小值从0更改为0.2 问题答案: 如何定义SeekBar的最小值? 您无法定义最小值。是的。 基本上我需要将最小值从0更改为0.2 获得值后,将其添加。
这一节要学的控件是 ProgressBar 的升级版,对于 ProgressBar 而言只能展示进度,而不能与用户互动,也就是没有接收用户输入的能力。而本节要学习的 SeekBar 是一种可以“Seek”的 ProgressBar,用户不但可以通过 SeekBar 观察到进度,还可以随时手动修改进度,相信对此场景你一定不会陌生。没错,在视频播放的场景用 SeekBar 实现在合适不过。 1. Se
我有一个简单的播放器和录音机。一切都很好,但都有一个问题。我想添加搜索栏来查看播放记录的进度,并使用此搜索栏设置玩家应该播放的位置。我有进步,但没有效果。这是代码: 你知道如何使用seek bar来查看进度和设置记录的位置吗?
本文向大家介绍Android中SeekBar和RatingBar用法实例分析,包括了Android中SeekBar和RatingBar用法实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android中SeekBar和RatingBar用法。分享给大家供大家参考,具体如下: 什么是SeekBar? 可以拖动的进度条(在播放器中使用最常见) 1、在布局文件中声明 2、定义一个OnSe
项目的问题形象: 嗨。我想知道这两个按钮的问题。首先,我强调了两个按钮。左键是减少按钮,右键是增加按钮。问题是...如果所有值都是最大值。单击增加按钮不会改变值。但是,如果我点击增加按钮两三次,然后点击减少按钮再次减少值,值不会改变。要减少值,我必须按增加按钮一样多的减少按钮。:( 当我第一次遇到这个问题时,我认为它是由OnClickListener的重叠调用引起的。因此,如果值为最大值,我试图避
目前,我正在开发一个媒体播放器,我需要seekBar一起工作,目前,一切都好!但是,当我触摸搜索栏的确定位置时,媒体播放器必须跟随并将歌曲设置到这个确定的位置,但歌曲和搜索栏回到了开始,我不知道为什么会发生这种情况。 谢谢你。