2

I want to implement a RecyclerView that works similar to Instagram feeds, that contains both Image and Video Items. I have successful implemented the recyclerView to display both image and video items, but I am having issues with pausing the video items when the onScrollListener is on RecyclerView.SCROLL_STATE_DRAGGING I am using ExoPlayer library for the video player"

So, if a video is played and the recyclerView is not pause it keeps on playing that video even if another video is played from the list. Making multiple video playing at the same time.

Below is my implementation Adapter

public class RecyclerAdapter extends RecyclerView.Adapter {

    private ArrayList<ListModel> listModelList;
    private Context context;

    SimpleExoPlayer exoPlayer;

    public RecyclerAdapter(ArrayList<ListModel> listModelList, Context context) {
        this.listModelList = listModelList;
        this.context = context;
    }

    @Override
    public int getItemViewType(int position) {
        if (listModelList.get(position).getDescription().equalsIgnoreCase("video")) {
            return 1;
        } else {
            return 0;
        }
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view;

        if (viewType == 0) {
            view = inflater.inflate(R.layout.recycler_item, parent, false);
            return new AdsViewHolder(view);
        } else {
            view = inflater.inflate(R.layout.video_item, parent, false);
            return new VideoVH(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
        ListModel listModel = listModelList.get(position);

        if (listModel.getDescription().equalsIgnoreCase("video")) {
            VideoVH videoVH = (VideoVH) holder;
            initPlayer(((VideoVH) holder).playerView, listModel.getMedia_url(), ((VideoVH) holder).progressBar);
            ((VideoVH) holder).titleText.setText(listModel.getTitle());
            ((VideoVH) holder).descText.setText(listModel.getDescription());

            //Play video
        } else {
            AdsViewHolder adsViewHolder = (AdsViewHolder) holder;

            ((AdsViewHolder) holder).titleText.setText(listModel.getTitle());
            ((AdsViewHolder) holder).descText.setText(listModel.getDescription());
            Glide.with(context)
                    .load(listModel.getMedia_url())
                    .into(((AdsViewHolder) holder).imageView);
        }
    }

    private void initPlayer(final PlayerView playerView, String uri, final ProgressBar progressBar) {


        TrackSelector trackSelector = new DefaultTrackSelector();

        exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector);

        playerView.setPlayer(exoPlayer);
        exoPlayer.setPlayWhenReady(false);
        DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context, Util.getUserAgent(context, "ExoRecyclerView"));

        MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(uri));

        exoPlayer.prepare(videoSource);

        playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL);
        exoPlayer.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
        exoPlayer.seekTo(500);

        exoPlayer.addListener(new Player.EventListener() {
            @Override
            public void onTimelineChanged(Timeline timeline, @Nullable Object manifest, int reason) {

            }

            @Override
            public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

            }

            @Override
            public void onLoadingChanged(boolean isLoading) {

            }

            @Override
            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {

                switch (playbackState) {

                    case Player.STATE_BUFFERING:
//                        Log.e(TAG, "onPlayerStateChanged: Buffering video.");
                        if (progressBar != null) {
                            progressBar.setVisibility(VISIBLE);
                        }

                        break;
                    case Player.STATE_ENDED:
                        break;
                    case Player.STATE_IDLE:

                        break;
                    case Player.STATE_READY:
//                        Log.e(TAG, "onPlayerStateChanged: Ready to play.");
                        if (progressBar != null) {
                            progressBar.setVisibility(GONE);
                        }
                        break;
                    default:
                        break;
                }

            }

            @Override
            public void onRepeatModeChanged(int repeatMode) {

            }

            @Override
            public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {

            }

            @Override
            public void onPlayerError(ExoPlaybackException error) {

            }

            @Override
            public void onPositionDiscontinuity(int reason) {

            }

            @Override
            public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {

            }

            @Override
            public void onSeekProcessed() {

            }
        });
    }

    @Override
    public int getItemCount() {
        return listModelList.size();
    }

    class AdsViewHolder extends RecyclerView.ViewHolder {

        ImageView imageView;
        TextView titleText, descText;

        public AdsViewHolder(@NonNull View itemView) {
            super(itemView);

            imageView = itemView.findViewById(R.id.thumbnail);
            descText = itemView.findViewById(R.id.desc);
            titleText = itemView.findViewById(R.id.title);
        }
    }

    class VideoVH extends RecyclerView.ViewHolder {


        PlayerView playerView;
        TextView titleText, descText;
        ConstraintLayout VV;
        ProgressBar progressBar;
        ImageView volumeControl;

        public VideoVH(@NonNull View itemView) {
            super(itemView);

            playerView = itemView.findViewById(R.id.playerView);
            descText = itemView.findViewById(R.id.desc);
            titleText = itemView.findViewById(R.id.title);
            volumeControl = itemView.findViewById(R.id.volume_control);
            VV = itemView.findViewById(R.id.parent);
            progressBar = itemView.findViewById(R.id.progressBar);
        }
    }

}

MainActivity imoplementation

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    ArrayList<ListModel> listModelList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRecyclerView = findViewById(R.id.recyclerView);

        ListModel listModel = new ListModel();
        listModelList.add(new ListModel("One test",
                "https://res.cloudinary.com/dqrs5xew4/image/upload/v1591991924/sample.jpg", "image"));
        listModelList.add(new ListModel("One test",
                "https://res.cloudinary.com/dqrs5xew4/video/upload/v1595538345/HNG/b5bc3f170b7d5c388410bcca0a501ecd_lnhzwn.mp4", "video"));
        listModelList.add(new ListModel("One test",
                "https://res.cloudinary.com/dqrs5xew4/image/upload/v1591991924/sample.jpg", "image"));
        listModelList.add(new ListModel("One test",
                "https://res.cloudinary.com/dqrs5xew4/video/upload/v1595538331/HNG/VID-20180713-WA0009_esbmff.mp4", "video"));
        listModelList.add(new ListModel("One test",
                "https://res.cloudinary.com/dqrs5xew4/image/upload/v1591991924/sample.jpg", "image"));
        initRecyclerView();
    }

    private void initRecyclerView() {
        // use a linear layout manager
        LinearLayoutManager layoutManager =
                new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        mRecyclerView.setLayoutManager(layoutManager);

        RecyclerAdapter mAdapter = new RecyclerAdapter(listModelList, MainActivity.this);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.notifyDataSetChanged();
    }
}

Model Class

public class ListModel {

    private String title;
    private String media_url;
    private String description;

    public ListModel(String title, String media_url, String description) {
        this.title = title;
        this.media_url = media_url;
        this.description = description;
    }

    public ListModel() {
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getMedia_url() {
        return media_url;
    }

    public void setMedia_url(String media_url) {
        this.media_url = media_url;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

I have gone through several question here and on youtube, But they all implemeted just a single view type in the recyclerView.

Any suggestion how I could control the Video Player when the recyclerView is been scrolled? Or a better way I could implement the Instagram feeds like RecyclerView

steveOS
  • 125
  • 1
  • 12
  • https://androidwave.com/exoplayer-in-recyclerview-in-android/ – Askar Jul 24 '20 at 21:52
  • @Askar I've gone through that post, A custom RecyclerView was built there. He implemented same thing with https://codingwithmitch.com/blog/playing-video-recyclerview-exoplayer-android/ But my own case I have both two type of view (image and video) How do I make a custom view that accommodates both view? – steveOS Jul 24 '20 at 22:18
  • @steveOS have you found any solution about it. i also face same issue but could not found solution.. – Adnan haider Feb 24 '21 at 04:36
  • @Adnanhaider No , I didn't get a solution yet. I just created a method to check items being displayed and pause the all items not being displayed on the recyclerView – steveOS Feb 24 '21 at 20:55
  • @steveOS can your share to me plzz.. i have another show still facing which is when i stop my app in recyclerview it stop last video but other still contitnue in background audio i dont know what i can do about it . – Adnan haider Feb 25 '21 at 04:49
  • 1
    @steveOS is there any solution find for this? – Naveen Kumar M Jun 13 '22 at 14:03
  • @NaveenKumarM if you have EventBus on project you can use it by sending event in onStop/onDestroy method – AlexS Jun 13 '22 at 18:34

0 Answers0