Search code examples
androidkotlinandroid-recyclerviewexoplayerexoplayer2.x

How to handle exo players in recycler view?


How can we use multiple exo player in a recycler view? I saw many posts and videos like this and this but that all use a custom recycler view class. I could continue with that. But, I wanted to make a complete Insta clone where I can send gif and image and videos. Now, when I use the custom recycler view class, I dont have any idea of how to play the video with the gif and images. This is my recycler view item code:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_margin="10dp"
    app:cardCornerRadius="6dp"
    app:cardElevation="1dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="10dp">


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <com.sambhav2358.facebookclone.customviews.RoundedImageView
                android:id="@+id/senderImage"
                android:layout_width="50dp"
                android:layout_height="50dp"
                app:cornerRadius="100dp"
                android:src="@color/primary"/>

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:orientation="vertical"
                android:layout_marginStart="10dp">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:id="@+id/senderName"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:text="Sender name"
                        android:ellipsize="end"
                        android:textStyle="bold"
                        android:textColor="@color/black"
                        android:layout_weight="1"/>

                    <TextView
                        android:id="@+id/dateAdded"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Date added"
                        android:ellipsize="end"
                        android:layout_marginStart="10dp"/>

                </LinearLayout>

                <TextView
                    android:id="@+id/senderUserName"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Sender user name"
                    android:ellipsize="end"
                    android:textColor="@color/black"
                    android:layout_weight="1"/>

            </LinearLayout>

            <ImageView
                android:id="@+id/more"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/more"
                android:layout_marginStart="5dp"
                android:padding="4dp"
                android:background="?selectableItemBackgroundBorderless"/>

        </LinearLayout>

        <TextView
            android:id="@+id/body"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Body\nOf\nThe\nPost"
            android:layout_margin="10dp"/>

        <androidx.cardview.widget.CardView
            android:id="@+id/postExtra"
            android:layout_width="fill_parent"
            android:layout_height="200dp"
            android:layout_margin="5dp"
            app:cardCornerRadius="6dp"
            app:cardElevation="0dp">

            <com.google.android.exoplayer2.ui.PlayerView
                android:id="@+id/videoView"
                android:layout_width="match_parent"
                android:layout_height="200dp" />

            <ImageView
                android:id="@+id/imageVIew"
                android:layout_width="match_parent"
                android:layout_height="200dp" />

            <com.giphy.sdk.ui.views.GifView
                android:id="@+id/gifView"
                android:layout_width="match_parent"
                android:layout_height="200dp"/>

        </androidx.cardview.widget.CardView>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                app:cardCornerRadius="50dp"
                android:backgroundTint="@color/primary">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:paddingHorizontal="10dp"
                    android:paddingVertical="5dp"
                    android:gravity="center">

                    <ImageView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:src="@drawable/like"
                        app:tint="@android:color/white" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Like"
                        android:textColor="@color/white"
                        android:layout_gravity="center"
                        android:layout_marginStart="10dp"/>

                </LinearLayout>

            </androidx.cardview.widget.CardView>

            <View
                android:layout_width="10dp"
                android:layout_height="0dp"/>

            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                app:cardCornerRadius="50dp"
                android:backgroundTint="@color/primary">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:paddingHorizontal="10dp"
                    android:paddingVertical="5dp"
                    android:gravity="center">

                    <ImageView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:src="@drawable/share"
                        app:tint="@color/white" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Share"
                        android:textColor="@color/white"
                        android:layout_gravity="center"
                        android:layout_marginStart="10dp"/>

                </LinearLayout>

            </androidx.cardview.widget.CardView>

            <View
                android:layout_width="10dp"
                android:layout_height="0dp" />

            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                app:cardCornerRadius="50dp"
                android:backgroundTint="@color/primary">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:paddingHorizontal="10dp"
                    android:paddingVertical="5dp"
                    android:gravity="center">

                    <ImageView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:src="@drawable/comment"
                        app:tint="@android:color/white" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Comment"
                        android:textColor="@color/white"
                        android:layout_gravity="center_vertical"
                        android:layout_marginStart="10dp"/>

                </LinearLayout>

            </androidx.cardview.widget.CardView>
        </LinearLayout>


    </LinearLayout>

</androidx.cardview.widget.CardView>

Solution

  • I got it. I just made a class where I created an static var? of ExoPlayer class which looked like this:

    import android.annotation.SuppressLint
    import com.google.android.exoplayer2.ExoPlayer
    
    @SuppressLint("StaticFieldLeak", "Deprecation")
    class ExoPlayerPlaybackHelper {
        companion object{
            var playerView : ExoPlayer? = null
        }
    }
    

    Then, I used this in my model(data class) to create an object of ExoPlayer with a play function in it and in the end, my model looked like this:

    import com.google.android.exoplayer2.ExoPlayer
    import com.sambhav2358.facebookclone.utils.ExoPlayerPlaybackHelper
    
    data class Post(my params, var playerView: ExoPlayer?){
        fun playVideo(playerView : ExoPlayer) {
            ExoPlayerPlaybackHelper.playerView?.pause()
    
            ExoPlayerPlaybackHelper.playerView = playerView
    
            playerView.play()
        }
    
        constructor() : this(my params, null) //passing the ExoPlayer object null for now
    }
    

    Now, in the adapter, I pass my exo player to my data class's object like this:

    post.playerView = binding.videoView.player as ExoPlayer
    

    The last task was to stop and play the video according to the scroll position using the OnScrollListener. I used this code and it did the task for me:

    binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
                override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
    
                    val pos = (recyclerView.layoutManager as? LinearLayoutManager)?.findLastCompletelyVisibleItemPosition()
    
                    if (pos == -1) return
    
                    Log.d(TAG, "onScrolled: Scrolled $pos")
    
                    if (posts[pos!!].messageType == "video" || posts[pos].messageType == "messageVideo") { // you might remove this line If you only use video players. But, I needed it.
                        posts[pos].playVideo(posts[pos].playerView!!)
                        Log.d(TAG, "onScrolled: played")
                    }
    
    
                    Log.d(TAG, "onScrolled: startCheckPauseTask")
                    for (position in posts.indices){
                        if (position == pos) continue
    
                        posts[position].playerView?.pause()
                        posts[position].playerView?.seekTo(0)
                    }
                    Log.d(TAG, "onScrolled: finishCheckPauseTask")
    
                }
            })
    

    Result


    You can view the result over here