Java 如何从getView设置正确SeekBar的进度?
我有一个带有自定义列表项的列表视图,每个列表项中都有一个按钮和一个SeekBar。现在,当点击一个按钮时,音频开始播放,我想为点击按钮的地方设置SeekBar的进度。使用我的代码,正确的搜索杆开始移动,但当我上下滚动几次时,另一个搜索杆开始移动。我试过很多东西,这是我最后一次:Java 如何从getView设置正确SeekBar的进度?,java,android,listview,seekbar,listitem,Java,Android,Listview,Seekbar,Listitem,我有一个带有自定义列表项的列表视图,每个列表项中都有一个按钮和一个SeekBar。现在,当点击一个按钮时,音频开始播放,我想为点击按钮的地方设置SeekBar的进度。使用我的代码,正确的搜索杆开始移动,但当我上下滚动几次时,另一个搜索杆开始移动。我试过很多东西,这是我最后一次: import android.app.Activity; import android.content.Context; import android.media.AudioManager; import android
import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
public class MyListAdapter extends ArrayAdapter<Audio> {
ArrayList<Audio> audios;
Context context;
int resource;
private static MediaPlayer mediaPlayer;
public Handler mHandler = new Handler();
TextView totalTime;
TextView playingTime;
private MyListAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull ArrayList<Audio> audios) {
super(context, resource, audios);
Collections.reverse(audios);
this.audios = audios;
this. context = context;
this.resource = resource;
}
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
final ViewHolder viewHolder;
View row;
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.audio_cell, parent, false);
viewHolder = new ViewHolder();
viewHolder.playButton = (ImageButton) row.findViewById(R.id.playButton);
viewHolder.seekBar = (SeekBar) row.findViewById(R.id.seekBar);
viewHolder.playButton.setTag(position);
viewHolder.seekBar.setTag(position);
row.setTag(viewHolder);
} else {
row = convertView;
viewHolder = (ViewHolder) row.getTag();
}
viewHolder.seekBar.setProgress(0);
//I get the audio url here
final Audio audio = getItem(position);
assert audio != null;
String theURL = audio.getURL();
//Button Click
viewHolder.playButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//here I call the method to play the audio and after that I want
//to update the SeekBar
playAudio(theURL);
updateSeekBar(viewHolder.seekBar);
}
});
return row;
}
private void updateSeekBar(final SeekBar sb) {
Runnable mUpdateTimeTask = new Runnable() {
@Override
public void run() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
int mCurrentPosition = mediaPlayer.getCurrentPosition() / 1000;
mHandler.postDelayed(this, 100);
sb.setProgress(mCurrentPosition);
}
}
};
mHandler.postDelayed(mUpdateTimeTask, 100);
}
}
正如我所说,我已经尝试了很多东西,但似乎没有任何效果,我想我尝试过的东西都是一样的,因为我每次都得到相同的结果。只要我上下滚动几次,它就会在不同的搜索栏上设置进度。感谢您的帮助 你可以像下面那样写
private MediaPlayer mediaPlayer;
private double startTime = 0;
private double finalTime = 0;
public int oneTimeOnly = 0;
viewHolder.playButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Being...
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(theURL);
try {
// Log.e("ddd***",tv_directory.getText().toString());
if(mediaPlayer.isPlaying()){
Log.e("isplaying**",mediaPlayer.isPlaying()+"");
mediaPlayer.pause();
finalTime = mediaPlayer.getDuration();
startTime = mediaPlayer.getCurrentPosition();
if (oneTimeOnly == 0) {
seekBar.setMax((int) finalTime);
oneTimeOnly = 1;
}
}else{
// Log.e("isplaying**",mediaPlayer.isPlaying()+"");
mediaPlayer.prepare();
//mediaPlayer.start();
mediaPlayer.start();
finalTime = mediaPlayer.getDuration();
startTime = mediaPlayer.getCurrentPosition();
if (oneTimeOnly == 0) {
seekBar.setMax((int) finalTime);
oneTimeOnly = 1;
}
}
} catch (Exception e) {
Log.e("err***",e.toString());
}
myHandler.postDelayed(new Runnable(){
public void run() {
startTime = mediaPlayer.getCurrentPosition();
tv_start_time.setText(String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes((long) startTime),
TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
toMinutes((long) startTime)))
);
seekBar.setProgress((int) startTime);
myHandler.postDelayed(this, 100);
}
}, 100);
} catch (Exception e) {
Log.e("err***",e.toString());
}
//End....
}
});
列表视图在getView()中循环使用视图,因为您使用的是getTag()和setTAg()。因此,当单击项目时,它会反映在其他位置,并且歌曲也会在其他位置播放,因为它正在重用视图 解决这个问题。创建一个全局int值,用于存储单击项的位置
private int mSelectedItem = -1;
每当单击播放按钮时,将该位置添加到mSelectedItem
viewHolder.playButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Store the position here
mSelectedItem=position;
//here I call the method to play the audio and after that I want
//to update the SeekBar
playAudio(theURL);
updateSeekBar(viewHolder.seekBar);
}
});
然后像这样更新seekBar
调用方法时传递位置
updateSeekBar(viewHolder.seekBar,position);
检查位置是否与您单击的位置相同,并更新seekbar
private void updateSeekBar(final SeekBar sb,int position) {
final Runnable mUpdateTimeTask=null;
if(mSelectedItem==position){
mUpdateTimeTask = new Runnable() {
@Override
public void run() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
int mCurrentPosition = mediaPlayer.getCurrentPosition() / 1000;
mHandler.postDelayed(this, 100);
sb.setProgress(mCurrentPosition);
}
}
};
mHandler.postDelayed(mUpdateTimeTask, 100);
}else{
mHandler.removeCallbacks(mUpdateTimeTask);
sb.setProgress(0);
}
}
好吧,我发现了问题,因为
if(convertView == null)
仅适用于屏幕上显示的第一个项目。这解释了为什么会发生这种情况。对我来说,答案是有效的。这不是最好的方法,但对于ListView,它只适用于少数项目。为什么不在适配器中使用“开始”按钮?适配器中是否有音频路径?将seekbar添加到音频中start@EnamulHaque是,音频路径在适配器中。我用更多的细节更新了答案。我不明白“将seekbar添加到音频开始”是什么意思?好的。你会给我一个适配器吗?现在请检查seekBar的OK,我是否必须说“viewHolder.seekBar”?因为它无法解析符号“seekBar”。现在我导入了seekBar,但我无法对其设置max或setProgress。添加完全适配器我添加了完全适配器类。(如果这是你的意思)这在一开始也是有效的,但当我向下滚动时,它也会更新不同的seekBar。我无法从mUpdateTimeTask中删除回调,因为它在if语句中声明。但是我不需要在onClick()方法之外调用updateSeekBar()吗??所以每次我滚动时都会调用它?您需要在if语句外部添加可运行引用。是的,您应该在onclick外部调用它,以便每次滚动时都调用它。请参阅更新的codemUpdateTimeTask可能尚未在else语句中初始化。但是我在getView meyhod中尝试了if(mSelectedItem==position){updateseeEkbar(viewHolder.seekBar,position;}我认为这也是一样的,但仍然不起作用。
if(convertView == null)