簡體   English   中英

ListView 中與 MediaPlayer 關聯的多個 SeekBar

[英]Multiple SeekBars associated with MediaPlayer in ListView

我有一個顯示語音消息的ListView (就像 WhatsApp 的),我使用的是BaseAdapter ,我的布局包含一個播放button和一個SeekBar 我想要的是點擊播放button播放音頻,並更新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 在您的活動中只有一個MediaPlayer實例。 每次在列表視圖中單擊“播放”按鈕時,您都會執行以下操作:

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

現在在您的getView()實現上,如果第一個參數: i不等於MainActivity當前播放的項目,則它的SeekBar應該為零。

MainActivity也應該是實現更新 runnable 的那個。 此時您可能只想使用普通的SeekBar 要更新正確的視圖,您需要首先確定它是否可見,因為用戶可能已經滾動到不同的位置,因此您需要在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的視圖,但SeekBar是它是可見的,否則返回 null。 在您的更新 runnable 中,您應該調用它,如果結果不為空,則更新SeekBar

此外,您可能需要考慮使用接口而不是將上下文引用轉換為適配器中的MainActivity

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM