Move automatically to next row in Recyclerview - android

I want the focus to move automatically to next row position in Recyclerview. My Recyclerview contains a videoview. On media completion, I want the next videoview to be played.Videoview is playing next video but only in first position videoview
private static int position= 0;
public static class ViewHolder extends RecyclerView.ViewHolder {
private VideoView videoView;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
position= getAdapterPosition();
//recyclerView.smoothScrollToPosition(position);
Log.d("TAG_LIST", "Element " + position+ " clicked.");
}
});
}
holder.videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//recyclerView.smoothScrollToPosition(position);
Video(holder);
}
});
private void Video(ViewHolder holder) {
if (++position>= items.size()) {
// Last song, just reset position
position= 0;
} else {
// Play next song
recyclerView.smoothScrollToPosition(position);
AsyncTask task = new AsyncTask (items.get(position).getUrl(), holder,position);
task.execute(items.get(position).getUrl());
}
}

You didnt post any code related to your problem but I can suggest you some methods for this.
Find first visible item position on RecyclerView and start video at your VideoView
Listen scroll changes on your RecyclerView and when first visible item index changed, stop your video, and start next RecyclerView item VideoView

Related

AutoPlay music and video in recyclerview adapter

I have 2 recycler view inside a fragment. 1st scroll vertically and 2nd scroll horizontal inside 1st one.(Just like instagram app). And recycler view display one item at a time and I am using PagerSnapHelper to scroll one item at time. In 2nd recycler view, I am displaying an image and playing a song from url. And I want to auto play song after scrolling to next/previous item(horizontal an vertical) both. When user click on image than song stop and if click again than song start again.
I wanted same logic for video player too after completing song playing work.
Here, I am facing issues in auto play song. Sometime song is playing for next item instead of current visible item. Some time song and image both working fine and than after next scroll suddenly song started playing from next item which not visible yet. And if user click on image than song stop and when click again than song is playing properly
I logged and check position number inside onBindViewHolder for 1st recycler view and it is logging 2 times. For current scrolled one and for next item too.
I tried many different ways to fix it like
setting recyclable to false holder.setIsRecyclable(false);
getting position from holder.getLayoutPosition()
using interfaces etc but count's figure it out.
Note: I am passing MediaPlayer from MainActivity to Fregment to 1st
recycler view to 2nd recycler view where song is playing.
This is my main codes structure
FragMent:
homeViewVerticalAdapter = new HomeViewVerticalAdapter(getActivity(), verticalDataModals, mp, ...)
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
infiniteScrollListener = new InfiniteScrollListener(linearLayoutManager, this);
infiniteScrollListener.setLoaded();
recyclerView.setLayoutManager(linearLayoutManager);
SnapHelper snapHelper = new PagerSnapHelper();
recyclerView.setOnFlingListener(null);
snapHelper.attachToRecyclerView(recyclerView);
homeViewVerticalAdapter.setHasStableIds(true);
// to disable caching so auto song play on all items
recyclerView.getRecycledViewPool().clear();
recyclerView.setItemViewCacheSize(0);
recyclerView.setAdapter(homeViewVerticalAdapter);
I logged inside recyclerView.addOnScrollListener and inside public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 2 logs are displaying.
1st recycler view(Vertical Scroll)
#Override
public void onBindViewHolder(#NonNull HomeViewVerticalAdapter.HomeViewHolder holder, int position) {
if (holder instanceof DataViewHolder) {
final VerticalDataModal verticalDataModal = verticalDataModalList.get(position);
HomeViewHorizontalAdapter homeViewHorizontalAdapter = null;
homeViewHorizontalAdapter = new HomeViewHorizontalAdapter(context, postViewItem, mp, ...)
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
SnapHelper snapHelper = new PagerSnapHelper();
holder.recyclerView.setOnFlingListener(null);
snapHelper.attachToRecyclerView(holder.recyclerView);
homeViewHorizontalAdapter.setHasStableIds(true);
holder.recyclerView.setAdapter(null);
holder.recyclerView.getRecycledViewPool().clear();
holder.recyclerView.setItemViewCacheSize(0);
holder.recyclerView.setAdapter(homeViewHorizontalAdapter);
homeViewHorizontalAdapter.notifyDataSetChanged();
......
....
}
}
2st recycler view(Horizontal Scroll)
#Override
public void onBindViewHolder(#NonNull HomeViewHorizontalAdapter.HomeViewHolder holder, int position) {
if (holder instanceof DataViewHolder) {
String musicPath = horizontalData1modal.getMusicUrl();
String imagePath = horizontalData1modal.getImageUrl();
Picasso.get()
.load(imagePath)
.placeholder(R.drawable.influencers)
.error(R.drawable.influencers)
.into(holder.imagePreviewLocal);
// playing fine when click on layout
holder.contentLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
musicPlayer(musicPath, "click", holder);
}
});
// not playing from auto play
musicPlayer(musicPath, "auto", holder);
......
....
}
}
and musing play method inside 2st recycler view(Horizontal Scroll):
Note: Here music playing, loader and hide a layout after some time logic
private void musicPlayer(String musicPath, String playType, #NonNull HomeViewHorizontalAdapter.HomeViewHolder holder) {
try {
Log.d(TAG, "music player detected: "+playType);
holder.contentDataLayout.setVisibility(View.VISIBLE);
if(timerMusicTrack != null){
timerMusicTrack.cancel();
}
if ((!mediaplayer.isPlaying() || playType.equals("auto")) && musicPath != null && !musicPath.equals("")) {
isPlaying = true;
mediaplayer.reset();
mediaplayer.stop();
mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
Uri musicUri = Uri.parse(musicPath);
mediaplayer.setDataSource(context, musicUri);
mediaplayer.prepareAsync();
progressBarLocal.setVisibility(View.VISIBLE);
mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaplayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END){
progressBarLocal.setVisibility(View.GONE);
return true;
} else if(what == MediaPlayer.MEDIA_INFO_BUFFERING_START){
progressBarLocal.setVisibility(View.VISIBLE);
}
return false;
}
});
progressBarLocal.setVisibility(View.GONE);
mediaplayer.start();
timerMusicTrack = new CountDownTimer(delayMillis, 100) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
timerUsed = true;
holder.contentDataLayout.setVisibility(View.GONE);
}
};
timerMusicTrack.start();
}
});
} else {
isPlaying = false;
mediaplayer.reset();
mediaplayer.stop();
progressBarLocal.setVisibility(View.GONE);
}
} catch (IOException e) {
e.printStackTrace();
progressBarLocal.setVisibility(View.GONE);
}
}
How can I auto play song for currently visible item ? Am I missing something ?

Is it possible to get the position of views inside ViewHolder for the RecyclerView?

The ViewHolder I have contains views that are needed for each item of my RecycleView, which are two TextViews, PlayPauseView, and AppCompatSeekBar. In the constructor I have initialized them to their ids of my layout, and is ready for my Adapter class to extend it. The problem is I have this PlayPauseView that needs to be toggled at the correct position for it to function right, because if I press the view at another position, the previous position is still toggled. Here's an image for better understanding.
The yellow means that it is currently playing, but two cannot play at the same time so I was hoping to get the position of the view inside the RecyclerView item.
This is from the Holder class
TextView mInstrumentalName, mProducer;
PlayPauseView mPlayButton; // Need to add pause/stop
AppCompatSeekBar mMusicSeekbar;
ItemClickListener itemClickListener;
public TrackHolder(View itemView) {
super(itemView);
mInstrumentalName = (TextView) itemView.findViewById(R.id.instrumental_name);
mProducer = (TextView) itemView.findViewById(R.id.producer);
mPlayButton = (PlayPauseView) itemView.findViewById(R.id.play_pause);
mMusicSeekbar = (AppCompatSeekBar) itemView.findViewById(R.id.music_seekbar);
itemView.setOnClickListener(this);
}
This is from the Adapter class
#Override
public void onBindViewHolder(#NonNull final TrackHolder holder, final int position) {
holder.mInstrumentalName.setText(tracks.get(position).getInstrumentalName());
holder.mProducer.setText(tracks.get(position).getProducer());
holder.mPlayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
holder.mPlayButton.toggle();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
if (mediaPlayer.isPlaying()) {
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(tracks.get(position).getMusicLink());
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
mediaPlayer.prepareAsync();
} else {
try {
mediaPlayer.setDataSource(tracks.get(position).getMusicLink());
previous_link = tracks.get(position).getMusicLink();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
mediaPlayer.prepareAsync();
}
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.release();
}
});
holder.setItemClickListener(new ItemClickListener() {
#Override
public void onItemClick(View v, int pos) {
Toast.makeText(context, Integer.toString(tracks.size()), Toast.LENGTH_SHORT).show();
}
});
}
If you want to get position in your view holder class then you can call getAdapterPosition() inside your class. this will return you the clicked position in view holder class
I finally found a solution. So what I did instead of focusing on the views inside of the ViewHolder, I refreshed/updated the whole item in the RecyclerView, meaning it will refresh the toggle state of the previous item. Here's a code snipped if anyone in the future has any trouble on the same question.
private int start_notifying = 0;
private int previous_pos = -1;
So start notifying is at 0 because you don't want to refresh the item until you toggled the play button at least once, and set the current position to become the previous position when you want to press a different list item. You then increment so you can start refreshing items on the next item pressed. Using notifyItemChanged(previous_pos) refreshed the item of the previous position that was pressed, making the play button go back to its normal state.
if (start_notifying > 0) {
notifyItemChanged(previous_pos);
previous_pos = position;
} else {
previous_pos = holder.getAdapterPosition();
Log.d("previous_pos", Integer.toString(holder.getAdapterPosition()));
start_notifying++;
}

Change every image view resources inside listview with one click

I have a list view of songs with play and pause button in every row..
I can't have two pause Icon(two playing song) in my list view So I need to first reset all of them to play Icon then set the selected view to pause Icon..
How can I do this ? Or can you offer a better solution for this ?
This is my code :
In model class ( Product ) :
public int currentPosition= -1;
in Adapter:
public interface PlayPauseClick {
void playPauseOnClick(int position);
}
private PlayPauseClick callback;
public void setPlayPauseClickListener(PlayPauseClick listener) {
this.callback = listener;
}
.
.
.
holder.playPauseHive.setImageResource(product.getPlayPauseId());
holder.playPauseHive.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (callback != null) {
callback.playPauseOnClick(position);
if (position == product.currentPosition) {
product.setPlayPauseId(R.drawable.ic_pause);
//set the image to pause icon
}else{
//set the image to play icon
product.setPlayPauseId(R.drawable.ic_play);
}
notifyDataSetChanged();
}
}
});
my Callback inside my Activity:
#Override
public void playPauseOnClick(int position) {
final Product product = songList.get(position);
if(product.currentPosition == position){
product.currentPosition = -1; //pause the currently playing item
}else{
product.currentPosition = position; //play the item
}
this.adapter.notifyDataSetChanged();
}
For my case I use a variable to store the current playing item position. Let say
int x = -1; //-1 can indicate nothing was currently playing
So in the playPauseOnClick() you can do something like this
#Override
public void playPauseOnClick(int position) {
if(x == position){
x = -1; //pause the currently playing item
}else{
x = position; //play the item
}
this.adapter.notifyDataSetChanged();
}
The reason i remove product.setPlayPauseId() is because you really don't need them. You just need to set the play or pause icon based on your x varible which I created earlier. Do Something like this in your getView()
Product product = songList.get(position);
if (position == x) {
//set the image to pause icon
}else{
//set the image to play icon
}
So once you call adapter.notifyDataSetChanged() your adapter will do all the work for you. Whenever the x variable having the value -1 none of the icon will be display the pause icon, this can also make sure only one position will showing the pause icon as well.
Hope it help you.

how to implement mediaplayer autoplay feature in recyclerview

I have multiple songs in recyclerview. I have to implement autoplay feature like normal media player when one song completes the next must play on next position in recyclerview.
Thanks for any help.
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
focusedItem = getLayoutPosition();
Log.d("TAG_LIST", "Element " + focusedItem + " clicked.");
}
});

Listview recycles and shows duplicated images

I have created a listview which consists of list of tracks and play and pause image.When clicked on play image, pause image becomes visible and clicking on pause ,play image will become visible.Issue is that when i click on play and scrolls down i see another list item showing pause image and when i scroll down more another list item showing pause image.It is because list recylces an shows duplicated images.On studying the issue i think i need to place if-else statement in the getView method but i failed to implement correct code to resolve this issue..plzz help me with code in tht..
Create a new boolean variable in your SoundCloud class by the name isPlaying. Create getter setters for it, like you have done for other variables.
Get the object from SoundCloudList like this:
SoundCloug soundCloud = (SoundCloud) getItem(position);
This object can be used everywhere you are using soundcloudList.get(position), so that makes it easy to because we don't have to fetch object everytime.
Then in your getView use isPlaying to show play/pause button on every position like below:
if(soundCloud.isPlaying()){
holder.img1.setVisibility(View.VISIBLE);
holder.img2.setVisibility(View.GONE);
}
else{
holder.img1.setVisibility(View.GONE);
holder.img2.setVisibility(View.VISIBLE);
}
and then in your onClickListeners, set values for isPlaying like this:
holder.img1.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(final View v) {
soundCloud.setPlaying(true);
try {
notifyDataSetChanged();
holder.img1.setVisibility(View.INVISIBLE);
holder.img2.setVisibility(View.VISIBLE);
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource("http://api.soundcloud.com/tracks/" + soundcloudList.get(position).getId() + "/stream?client_id=e13865f9debacb5f96375fdd96b7fa1b");
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
mp.start();
}
});
mMediaPlayer.setOnCompletionListener(
new MediaPlayer.OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
mMediaPlayer.release();
mMediaPlayer = null;
holder.img1.setVisibility(View.VISIBLE);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
});
holder.img2.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(final View v)
{
soundCloud.setPlaying(false);
notifyDataSetChanged();
holder.img1.setVisibility(View.VISIBLE);
holder.img2.setVisibility(View.INVISIBLE);
if(mMediaPlayer!=null)
{
mMediaPlayer.release();
mMediaPlayer = null;
}
}
});
This code will not show the play/pause button duplicated on multiple rows, because now, we are checking the play/pause of audio for every row in getView and only then setting the buttons visibility.

Categories

Resources