当滚动关闭屏幕播放/暂停视频 - 播放视频在RecyclerView

问题描述 投票:3回答:4

我实现了视频播放器回收者视图中使用一个纹理视图和媒体播放器来实现。

如果我在列表中向下滚动,我可以按一下该项目,并在视频播放。然而,随着一旦视图回收站视图熄灭屏幕则然后回收再利用。如果我滚动备份所有的意见,现在是空白的(黑色)。

我期待添加的功能,当用户滚动视频戏外,它将暂停和继续参考该视频,这样,如果他们向后滚动到视频它将从点开始播放。

我已签出this但是我不想下载的视频,我只是想流。我不找人做这对我来说,我只是寻找一些指针和希望有人能分享这一知识...在此先感谢

这是我迄今所做的:

视频播放器

public class CustomVideoPlayer implements TextureView.SurfaceTextureListener, VideoControllerView.MediaPlayerControl, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnVideoSizeChangedListener {

    private Context mContext;
    private String mUrl;
    private MediaPlayer mMediaPlayer;
    private Surface mSurface;
    private VideoControllerView mControllerView;

    private TextureView mTextureView;
    private CardView mCardView;
    private ProgressBar mProgress;
    private FrameLayout mView;
    private RelativeLayout mLayout;


    public CustomVideoPlayer(Context ctx, TextureView view, ProgressBar progressDialog, FrameLayout holderView){

        this.mContext = ctx;
        mTextureView = view;
        mTextureView.setSurfaceTextureListener(this);
        mProgress = progressDialog;
        mControllerView = new VideoControllerView(ctx);
        mView = holderView;

        mTextureView.setOnTouchListener(new ControlTouchListener());
    }


    @Override
    public boolean canPause() {
        return true;
    }

    @Override
    public boolean canSeekBackward() {
        return true;
    }

    @Override
    public boolean canSeekForward() {
        return true;
    }

    @Override
    public int getBufferPercentage() {
        return 0;
    }

    @Override
    public int getCurrentPosition() {
        return mMediaPlayer.getCurrentPosition();
    }

    @Override
    public int getDuration() {
        return mMediaPlayer.getDuration();
    }

    @Override
    public boolean isPlaying() {
        return mMediaPlayer.isPlaying();
    }

    @Override
    public void pause() {
        mMediaPlayer.pause();
    }

    @Override
    public void seekTo(int i) {
        mMediaPlayer.seekTo(i);
    }

    @Override
    public void start() {
        mMediaPlayer.start();
    }

    @Override
    public boolean isFullScreen() {
        return false;
    }

    @Override
    public void toggleFullScreen() {

    }

    @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {

    }

    @Override
    public void onCompletion(MediaPlayer mp) {

    }



    @Override
    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {

    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mSurface = new Surface(surface);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    public void changePlayState(){
        if(mMediaPlayer.isPlaying()){
            mMediaPlayer.pause();
        }else{
            mMediaPlayer.start();
        }
    }

    public void startVideo(String url){
        if(mMediaPlayer!=null){
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = new MediaPlayer();
        }else{
            mMediaPlayer = new MediaPlayer();
        }
        if(!mMediaPlayer.isPlaying()){
            try {
                mMediaPlayer.setSurface(mSurface);
                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mMediaPlayer.setDataSource(url);
                mMediaPlayer.prepareAsync();
                mMediaPlayer.setOnCompletionListener(this);
                mMediaPlayer.setOnBufferingUpdateListener(this);
                mMediaPlayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
                mMediaPlayer.setOnPreparedListener(this);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    @Override
    public void onPrepared(MediaPlayer mp) {
        Log.i(VersysVideoPlayer.class.getSimpleName(), "ON PREPARED CALLED");
        mControllerView.setMediaPlayer(this);
        mControllerView.setAnchorView(mView);
        mControllerView.show();
        mProgress.setVisibility(View.GONE);
        mMediaPlayer.start();
    }

    //Touch listener to display video controls
    class ControlTouchListener implements View.OnTouchListener{

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_DOWN){
                mControllerView.show();
            }
            return false;
        }
    }
}

活动/ ADAPTER

public class VideoViewListActivity extends AppCompatActivity   {

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

        //Create instance of Recycler view
        final RecyclerView videoList = (RecyclerView) findViewById(R.id.feed_list);
        LinearLayoutManager llm = new LinearLayoutManager(this);
        videoList.setLayoutManager(llm);
        videoList.setHasFixedSize(true);

        final List<String> list = new ArrayList<>();
        list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
        list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
        list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
        list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
        list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
        list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
        final VideoAdapter adapter = new VideoAdapter(list, this);
        videoList.setAdapter(adapter);


        videoList.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                TextureView view = adapter.getVideoPlayer();
                Log.i("PERCENTAGE VISIBLE: ", String.valueOf(getVisiblePercent(adapter.getVideoPlayer())));
                if(getVisiblePercent(view)==100) {
                    return;
                }
              }
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_video_view_list, menu);
        return true;
    }


    public static int getVisiblePercent(View v) {
        if (v.isShown()) {
            Rect r = new Rect();
            v.getGlobalVisibleRect(r);
            double sVisible = r.width() * r.height();
            double sTotal = v.getWidth() * v.getHeight();
            return (int) (100 * sVisible / sTotal);
        } else {
            return -1;
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


    /**
     * Recycler View Adapter
     */
    class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoFeedHolder> {

        public TextureView mPreview;
        private CardView mCardView;
        private List<String> mUrls;
        private Context mContext;
        private Surface mSurface;
        VideoControllerView controller;
        private View mAnchor;
        private ProgressBar mProgressDialog;
        private ImageView mHolder;
        private int mPosition;
        private VersysVideoPlayer mVideoPlayer;
        OnItemClickListener mItemClickListener;

        public VideoAdapter(List<String> url, Context ctx) {
            mUrls = url;
            mContext = ctx;
            controller = new VideoControllerView(ctx);
        }

        @Override
        public VideoAdapter.VideoFeedHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
            View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.video_item_feed, viewGroup, false);
            VideoFeedHolder holder = new VideoFeedHolder(v);
            return holder;
        }

        @Override
        public void onBindViewHolder(final VideoFeedHolder videoFeedHolder, final int i) {

            final VersysVideoPlayer videoPlayer = new VersysVideoPlayer(mContext, videoFeedHolder.mTexturePreview, mProgressDialog, videoFeedHolder.controlHolder);
            videoFeedHolder.placeholder.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    videoPlayer.startVideo(mUrls.get(i));
                    videoFeedHolder.placeholder.setVisibility(View.GONE);
                    videoFeedHolder.bar.setVisibility(View.VISIBLE);
                }
            });

            mPosition = i;
        }

        @Override
        public void onAttachedToRecyclerView(RecyclerView recyclerView) {
            super.onAttachedToRecyclerView(recyclerView);
        }


        public String getUrl() {
            return mUrls.get(mPosition);
        }


        @Override
        public int getItemCount() {

            return mUrls.size();
        }

        public TextureView getVideoPlayer() {
            return mPreview;
        }


        public class VideoFeedHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

            TextureView mTexturePreview;
            ProgressBar bar;
            ImageView placeholder;
            FrameLayout controlHolder;
            RelativeLayout touchLayout;
            public VideoFeedHolder(View itemView) {
                super(itemView);

                mTexturePreview = (TextureView) itemView.findViewById(R.id.video_player);
                mPreview = mTexturePreview;
                mCardView = (CardView) itemView.findViewById(R.id.cv);
                bar = (ProgressBar)itemView.findViewById(R.id.buffereing);
                placeholder = (ImageView) itemView.findViewById(R.id.holder);
                mProgressDialog = bar;

                controlHolder = (FrameLayout) itemView.findViewById(R.id.media_controller_anchor);

            }

            @Override
            public void onClick(View v) {
                if (mItemClickListener != null) {
                    mItemClickListener.onItemClick(v, getAdapterPosition());
                }
            }
        }

     }
}

视频源项目XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.CardView
        android:layout_margin="10dp"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:id="@+id/cv">
        <RelativeLayout
            android:id="@+id/anchor"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
            <RelativeLayout
                android:id="@+id/detail_layout"
                android:layout_marginTop="10dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageView
                    android:id="@+id/profile_pic"
                    android:background="@drawable/profiler"
                    android:layout_marginLeft="10dp"
                    android:layout_width="50dp"
                    android:layout_height="50dp" />

                <TextView
                    android:id="@+id/user_name"
                    android:layout_alignTop="@+id/profile_pic"
                    android:layout_toRightOf="@+id/profile_pic"
                    android:text="Joe Bloggs"
                    android:layout_marginLeft="10dp"
                    android:textColor="#000000"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/date"
                    android:layout_below="@+id/user_name"
                    android:layout_toRightOf="@+id/profile_pic"
                    android:layout_marginLeft="10dp"
                    android:text="10 Aug 2015"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/desc"
                    android:layout_below="@+id/profile_pic"
                    android:layout_marginLeft="10dp"
                    android:text="This a sample video of a bird getting hit on the head and a rabbit waking from a nap!!"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
            </RelativeLayout>
            <RelativeLayout
                android:layout_below="@+id/detail_layout"
                android:layout_margin="10dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                    <TextureView
                        android:id="@+id/video_player"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent" />
                   <FrameLayout
                       android:id="@+id/media_controller_anchor"
                       android:layout_alignParentBottom="true"
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content">
                   </FrameLayout>

                    <ImageView
                        android:id="@+id/holder"
                        android:layout_centerInParent="true"
                        android:background="@drawable/default_video_poster"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />

                    <ProgressBar
                        android:id="@+id/buffereing"
                        android:visibility="gone"
                        android:layout_centerInParent="true"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />
            </RelativeLayout>
        </RelativeLayout>
    </android.support.v7.widget.CardView>
</RelativeLayout>
android android-mediaplayer android-recyclerview textureview android-textureview
4个回答
2
投票

通过适配器overridding onViewAttachedToWindow(VH holder)onViewDetachedFromWindow(VH holder),你可以在每个项目进入或从RecyclerView的可见区域出口得到通知。因此,它可以保存该项目的状态。例如,您可以创建适配器类HashMap<Integer, Long>持有打球的最后一次。通过这种方式,我们应该暂停视频和存储视频播放时间与项目位置键HashMap,在onViewDetachedFromWindow。然后在onViewAttachedToWindow从地图并恢复它...

基于文档:

当由该适配器创建的视图已被附接到一个窗口onViewAttachedToWindow被调用。

当这个适配器创建的视图已经从它的窗口分离onViewDetachedFromWindow被调用。


Visual Result:

enter image description here


1
投票

我会通过增加visibilitylistener到回收viewholder类接近这一点。 Facebook的fresco库使用类似的技术用于其“ImageView的”执行。

壁画是开源所以它简单结账如何做。


0
投票

看一看文档here。 在该方法

onViewRecycled(RecyclerView.ViewHolder holder)

你可以让你的视频被打的时候,后来就时你会得到相同的视频只需设置播放时间与保存的值


0
投票

相反,只用String对象,创建类,如下:

public class MyVideoObject {
    String url;
    int seek_position;
}

而作为@gropapa提到的,你可以在seek_position方法设置onViewRecycled。当视图被重建,可以从存储在对象的seek_position开始播放。

有一个图书馆,我写这将播放影片时,ViewHolder是可见的,暂停时,它是部分可见。目前,它不seek_position存储这些被回收的观点,但其恢复不回收(部分可见)的视频。

AutoPlayVideos:https://github.com/Krupen/AutoplayVideos

© www.soinside.com 2019 - 2024. All rights reserved.