Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recyclerview viewholder possible to change views at other adapter positions (not current position)?

I have a recyclerview with mediaplayer to play a song on each row. I only have one button for play/stop which changes symbol.

Here is my problem:

Example 1 (This works fine):

(For adapter position 1) the user hits the play symbol and music plays for that adapter position and the symbol changes to a stop symbol, they then hit the stop symbol and the music stops and the symbol changes back to a play symbol ready to start the music again.

Example 2 (This is the problem)

(For adapter position 1) the user hits the play symbol and music plays for that adapter position and the symbol changes to a stop symbol. Without hitting that button again they then hit the play symbol (adapter position 3) so now they are trying to play the song on position 1 and 3 at the same time. I have fixed both songs playing at the same time so that when the the second song is pressed the media played is reset and the source song file is changed to the new song (only one will play at a time).

The problem then becomes even though the media player is behaving as it should. The mediaplayer is controlled in the mainactivity. The play/stop button (imageview) image is changed in the the adapter viewholder and I can't work out a way to change the play/stop symbol when more than one song is clicked at the same time.

This image shows the example both song 1 and song 3 have been pressed. Now only song 3 is playing but the images are still showing as if both songs are playing simultaneously.

enter image description here

This is my view holder where I handle changing the play/stop image and send the song clicked callback:

class AddVideoAudioViewHolder extends RecyclerView.ViewHolder{

    ImageView PlayButton;
    Button AddAudioButton;
    TextView Title;
    public AddVideoAudioViewHolder(View itemView) {
        super(itemView);

        PlayButton = (ImageView) itemView.findViewById(R.id.PlayStopAudioDemo);
        PlayButton.setTag(1);
        PlayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int PlayStopButtonState = (int) PlayButton.getTag();

                if (PlayStopButtonState == 1) {
                    mVideoAudioCallbacks.onClick(100 + getAdapterPosition());
                    PlayButton.setImageResource(R.drawable.playstop);
                    PlayButton.setTag(2);

                } else {

                    mVideoAudioCallbacks.onClick(200 + getAdapterPosition());
                    PlayButton.setImageResource(R.drawable.playarrow);
                    PlayButton.setTag(1);
                }


            }
        });

and this is the method in the main activity where I handle the case of two songs playing:

public void PlaySong (int SongNumber, int ObjectInt){


    if (mp == null) {

        mp = new MediaPlayer();

    }else{
        mp.reset();
    }

    try {
        mp.setDataSource(this, Uri.parse("android.resource://com.example.nick.accountable/" + SongArray[SongNumber]));
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        mp.prepare();
    } catch (IOException e) {
        e.printStackTrace();
    }
    mp.start();



}

So my question can I add some code in the view holder or in the main activity that can change all the other views than the current adapter position. I.e. If song number 3 is clicked to play, set the image for position 1-2 & 4-10 as not playing or is there a better way to do it.

Thanks for your help Nicholas

like image 498
Nicholas Muir Avatar asked Feb 09 '16 09:02

Nicholas Muir


People also ask

What is the role of the ViewHolder in a RecyclerView?

A ViewHolder describes an item view and metadata about its place within the RecyclerView. RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive View.

What is the relationship between RecyclerView adapter and RecyclerView ViewHolder?

ViewHolder is not bound to an item or the given RecyclerView. Adapter is not part of this Adapter (if this Adapter merges other adapters).


1 Answers

In your adapter have an int variable to maintain which position is being played

int mCurrentPlayingPosition = -1; // if -1 nothing is playing

in your play button's on click listener, do this

PlayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int PlayStopButtonState = (int) PlayButton.getTag();

                int previousPosition = mCurrentPlayingPosition;
                if (PlayStopButtonState == 1) {

                    mCurrentPlayingPosition = getAdapterPosition();

                    mVideoAudioCallbacks.onClick(100 + getAdapterPosition());
                    PlayButton.setImageResource(R.drawable.playstop);
                    PlayButton.setTag(2);

                } else {
                    mCurrentPlayingPosition = -1; // nothing wil be played after hitting stop
                    mVideoAudioCallbacks.onClick(200 + getAdapterPosition());
                    PlayButton.setImageResource(R.drawable.playarrow);
                    PlayButton.setTag(1);
                }

                if(previousPosition != -1)
                    notifyItemChanged(previousPosition);

            }
        });

in your onBindViewHolder do the following

@Override
public void onBindViewHolder(AddVideoAudioViewHolder holder, int position) {
    if(mCurrentPlayingPosition == position ){
       // display stop icon
    } else {
       // display play icon
    }
}
like image 175
Much Overflow Avatar answered Oct 26 '22 22:10

Much Overflow