RecyclerView中播放视频

在很多播放视频的APP中都有在列表中播放视频的效果,当点击播放的时候,在列表中播放,当视频列表滑动出屏幕的时候,就在屏幕的右下角播放。大致效果如下图:

  • 主要思路

    1. 在和RecyclerView的同级布局文件中,在右下角放置一个隐藏FrameLayout,当正在播放的列表滑出界面的时候,将右下角的FragmeLayout设置为显示,并将播放的SurfaceView添加到右下角的FragmeLayout播放。
    2. 在列表的ViewHolder布局文件中放置一个FragmeLayout,当点击播放按钮时,将SurfaceView添加到FragmentLayout中播放。
    3. 为RecyclerView设置addOnChildAttachStateChangeListener事件,这个监听有两个重要的方法
    /**
     *当添加子View时回调
     */
    public void onChildViewAttachedToWindow(View view);
    
    /**
     *当移除子View时回调
     */
    public void onChildViewDetachedFromWindow(View view)
    
  • 首先看下主界面布局代码:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@color/colorPrimary"
                app:layout_scrollFlags="scroll|enterAlways|snap" />
        android.support.design.widget.AppBarLayout>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    android.support.design.widget.CoordinatorLayout>

    
    <FrameLayout
        android:id="@+id/video_root_fl"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:background="#000"
        android:visibility="gone" />

    
    <FrameLayout
        android:id="@+id/video_full_screen"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />
RelativeLayout>

可以在布局文件中看到,在右下角中放置了一个隐藏的FrameLayout,当正在播放的列表滑出界面时我们会使用这个FrameLayout来放置播放视频的SurfaceView。

  • 在RecyclerView中的item布局文件中也有一个FrameLayout

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/item_cardview"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:layout_margin="10dp"
    android:background="#fff"
    android:elevation="8dp"
    android:padding="5dp"
    app:cardBackgroundColor="#fff"
    app:cardCornerRadius="5dp">

    
    <FrameLayout
        android:id="@+id/item_video_root_fl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

    <ImageView
        android:id="@+id/item_imageview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop" />

    <ImageView
        android:id="@+id/item_image_play"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/ic_play_circle_outline_white_48dp" />
android.support.v7.widget.CardView>

item中这个FrameLayout用于点击列表中播放按钮将要播放的SurfaceView添加到这个FrameLayout中

  • 为RecyclerView添加addOnChildAttachStateChangeListener监听,当正在播放的item滑出界面时会回调onChildViewDetachedFromWindow这个方法,我们在这个方法中判断如果FragmeLayout中有视频播放,将右下角的FrameLayout设置为显示,移除item布局中的SurfaceView并将其添加到右下角的FrameLayout,将记录这个item的位置,当再次将这个item滑动到界面中时,会回调onChildViewAttachedToWindow这个方法。同理再将这个右下角中的FrameLayout中的SurfaceView移除并设置为隐藏,再将SurfaceView添加到item中的FrameLayout播放。
	//为RecyclerView添加addOnChildAttachStateChangeListener监听
recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
            @Override
            public void onChildViewAttachedToWindow(View view) {
                if (videoPosition == -1 || videoRootViewFl.getVisibility() != View.VISIBLE) {
                    return;
                }
                if (videoPosition == recyclerView.getChildAdapterPosition(view)) {
                    videoPosition = -1;
                    showVideo(view, VIDEO_PATH);
                }
            }

            @Override
            public void onChildViewDetachedFromWindow(View view) {
                if (videoView == null || videoRootViewFl.getVisibility() == View.VISIBLE) return;
                View v = view.findViewById(R.id.item_video_root_fl);
                if (v != null) {
                    FrameLayout fl = (FrameLayout) v;
                    videoPosition = recyclerView.getChildAdapterPosition(view);
                    if (fl.getChildCount() > 0) {
                        fl.removeAllViews();
                        int position = 0;
                        if (videoView.isPlaying()) {
                            position = videoView.getPosition();
                            videoView.stop();
                        }
                        videoRootViewFl.setVisibility(View.VISIBLE);
                        videoRootViewFl.removeAllViews();
                        lastView = videoRootViewFl;
                        videoRootViewFl.addView(videoView, new ViewGroup.LayoutParams(-1, -1));
                        videoView.setVideoPath(VIDEO_PATH);
                        videoView.start();
                        videoView.seekTo(position);
//                        if (videoView.isPause()) {
//                            videoView.resume();
//                        }
                    }
                    fl.setVisibility(View.GONE);
                }
                v = view.findViewById(R.id.item_imageview);
                if (v != null) {
                    if (v.getVisibility() != View.VISIBLE) {
                        v.setVisibility(View.VISIBLE);
                    }
                }
                v = view.findViewById(R.id.item_image_play);
                if (v != null) {
                    if (v.getVisibility() != View.VISIBLE) {
                        v.setVisibility(View.VISIBLE);
                    }
                }
            }
        });

完整代码
传送门

你可能感兴趣的:(Android)