列表视图中的音频播放器与android中的搜索栏

时间:2014-03-06 06:13:14

标签: android android-listview android-seekbar

一切正常,但搜索栏正在每个列表视图进行更新,但音频正在播放 正确的方式

public class AudioPLayAdapter extends BaseAdapter implements
        OnCompletionListener, SeekBar.OnSeekBarChangeListener {
    private Activity activity;

    private ArrayList<String> al_fname = new ArrayList<String>();
    private static LayoutInflater inflater = null;
    private boolean flag_play;
    private MediaPlayer mPlayer = null;

    Handler seekHandler = new Handler();

    public AudioPLayAdapter(Activity a, ArrayList<String> al_fname) {
        activity = a;
        mPlayer = new MediaPlayer();
        this.al_fname = al_fname;
        inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    @Override
    public View getView(final int position, final View convertView,
            final ViewGroup parent) {
        View vi = convertView;

        if (convertView == null)
            vi = inflater.inflate(R.layout.audi_rec_lv_layout, null);

        final Button play_btn = (Button) vi.findViewById(R.id.play_stop_button);

        final SeekBar seekBar = (SeekBar) vi.findViewById(R.id.seekbar_play);

        play_btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                if (!flag_play) {
                    play_btn.setText("Stop");
                    startPlaying();

                    flag_play = true;
                } else {
                    play_btn.setText("Play");
                    mPlayer.stop();
                    seekBar.setProgress(0);
                    flag_play = false;
                }

            }

            private void startPlaying() {
                // TODO Auto-generated method stub

                try {

                    mPlayer.reset();
                    FileInputStream rawFile = new FileInputStream(al_fname
                            .get(position));
                    Log.e("filename", al_fname.get(position));
                    mPlayer.setDataSource(rawFile.getFD());
                    // mPlayer.setDataSource(mFileName);
                    mPlayer.prepare();
                    mPlayer.start();
                    // set Progress bar values

                    seekBar.setProgress(0);
                    seekBar.setMax(100);

                    // seekHandler.postDelayed(updateSeek, 100);
                    // Updating progress bar

                    updateProgressBar();

                } catch (IOException e) {
                    Log.e("preparefailed", "prepare() failed");
                }

            }

            private void updateProgressBar() {
                // TODO Auto-generated method stub

                seekHandler.postDelayed(mUpdateTimeTask, 100);
            }

            private Runnable mUpdateTimeTask = new Runnable() {
                public void run() {
                    long totalDuration = mPlayer.getDuration();
                    long currentDuration = mPlayer.getCurrentPosition();
                    String str1 = new String();
                    // holder.timer_tv.setText(str1.valueOf(currentDuration));
                    // Updating progress bar
                    int progress = (int) (getProgressPercentage(
                            currentDuration, totalDuration));
                    // Log.d("Progress", ""+progress);
                    // if(position==holder.seekBar.getId())
                    // seekBar.setTag(position);
                    seekBar.setProgress(progress);

                    // Running this thread after 100 milliseconds
                    seekHandler.postDelayed(this, 100);
                    if (!mPlayer.isPlaying()) {
                        play_btn.setText("Play");

                        flag_play = false;
                    }
                    if (!flag_play)
                        seekBar.setProgress(0);

                }

                private int getProgressPercentage(long currentDuration,
                        long totalDuration) {
                    // TODO Auto-generated method stub
                    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();
                }
            };

        });
        return vi;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return al_fname.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress,
            boolean fromUser) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        // TODO Auto-generated method stub

    }

}

1 个答案:

答案 0 :(得分:4)

每次调用getView时,都会创建一个新的OnClickListener并添加到该行视图的play_btn

这些匿名OnClickListener中的每一个都有一个字段Runnable mUpdateTimeTask。这个runnable被发布到处理程序,然后它一次又一次地发布自己。

当一个新行开始播放时,现在有两个Runnable张贴自己并更新可能不同的搜索栏。每次单击播放时,都会添加一个新的附加runnable。

您想要的是跟踪正在播放的项目,并在不再需要时停止发布可运行的项目。一次最多只能运行1次。甚至可能寻找更好的方式来定期更新搜索栏(如果存在)。

getView中如果视图被回收(即它来自convertView参数),则必须检查视图现在是否用于其他position,如果它是不同的位置,然后停止更新此行的seekbar

所以你需要这样的东西(有些细节仍然缺失,例如歌曲结束时的处理,或者如何停止播放,留作练习):( https://github.com/curobosqui/PlaybackInList/tree/StackoverfllowAnswer的完整演示项目)

public class ListWithSongsActivity extends ListActivity {
    private static final int NOT_PLAYING = -1;

    private static final String TAG = "SongList";

    List<String> mSongs = new ArrayList<String>(50);
    private ArrayAdapter<String> mAdapter = null;
    private final MediaPlayer mPlayer = new MediaPlayer();
    private int mPlayingPosition = NOT_PLAYING;
    private Handler mHandler = new Handler();

    private PlaybackUpdater mProgressUpdater = new PlaybackUpdater();

    public ListWithSongsActivity() {
        //add list of songs in your device for sample
        mSongs.addAll(Arrays.asList(new String[]{
            "/sdcard/Download/B00G2ID7FE_(disc_1)_01_-_Play_Me_(Version).mp3",
            "/sdcard/Download/The Slip/10 Demon Seed.mp3"
        }));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_list_with_songs);
        mAdapter = new ArrayAdapter<String>(this, R.layout.list_item, android.R.id.text1, mSongs) {

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View v = super.getView(position, convertView, parent);
                ProgressBar pb = (ProgressBar) v.findViewById(R.id.progressBar1);   //Cast
                if (position == mPlayingPosition) {
                    //pb.setVisibility(View.VISIBLE);
                    mProgressUpdater.mBarToUpdate = pb;
                    mHandler.postDelayed(mProgressUpdater, 100);
                } else {
                    //pb.setVisibility(View.GONE);
                    pb.setProgress(0);
                    if (mProgressUpdater.mBarToUpdate == pb) {
                        //this progress would be updated, but this is the wrong position
                        mProgressUpdater.mBarToUpdate = null;
                    }
                }
                return v;
            }
        };
        setListAdapter(mAdapter);
    }

    private void stopPlayback()
    {
        mPlayingPosition = NOT_PLAYING;
        mProgressUpdater.mBarToUpdate = null;
        mPlayer.stop();
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        //start playing item at position
        try {
            mPlayer.reset();
            mPlayer.setDataSource(mSongs.get(position));
            mPlayer.prepare();
            mPlayer.start();
            mPlayingPosition = position;

            mHandler.postDelayed(mProgressUpdater, 500);

            //trigger list refresh, this will make progressbar start updating if visible
            mAdapter.notifyDataSetChanged();
        } catch (IOException e) {
            Log.e(TAG, "unable to play: " + mSongs.get(position));
            e.printStackTrace();
            stopPlayback();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.list_with_songs, menu);
        return true;
    }

    @Override
    protected void onStop() {
        super.onStop();
        mPlayer.stop();
    }

    private class PlaybackUpdater implements Runnable {
        public ProgressBar mBarToUpdate = null;

        @Override
        public void run() {
            if ((mPlayingPosition != NOT_PLAYING) && (null != mBarToUpdate)) {
                mBarToUpdate.setProgress( (100*mPlayer.getCurrentPosition() / mPlayer.getDuration()) );    //Cast
                mHandler.postDelayed(this, 500);
            } else {
                //not playing so stop updating
            }
        }
    }
}

使用简单的行布局list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView" />

    <ProgressBar
        android:id="@+id/progressBar1"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>