欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(仿头条App项目)9.视频列表页面实现

程序员文章站 2022-05-16 20:27:04
...

视频列表页面实现

效果图

(仿头条App项目)9.视频列表页面实现

相关布局

视频VideoFragment页面放一个ListView存放视频列表
(仿头条App项目)9.视频列表页面实现
每条列表布局

<?xml version="1.0" encoding="utf-8"?>
<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">
        <com.volokh.danylo.video_player_manager.ui.VideoPlayerView
            android:id="@+id/video_view"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            />
        <ImageView
            android:background="#C00FFF"
            android:id="@+id/cover_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <TextView
            android:text="我是标题"
            android:textSize="25sp"
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
</RelativeLayout>

功能实现

引入第三方视频库插件

引入三个依赖,分别是视频管理器,视频列表,因为依赖用到了recyclerview,所以虽然用不到,但是也要导入,否则会报错。
(仿头条App项目)9.视频列表页面实现

从服务端获取数据

根据服务端的数据进行解析json,用Gson插件直接快速创建存放视频bean文件VideoData。
(仿头条App项目)9.视频列表页面实现
在MyApi中添加获取视频数据地址的方法getVideoData()。
(仿头条App项目)9.视频列表页面实现
请求数据

    //2:获取服务端数据
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        System.out.println("VideoFragment onActivityCreated");
        //retrofit ->MyApi
        retrofit.create(MyApi.class).getVideoData().enqueue(new Callback<VideoData>() {
            @Override
            public void onResponse(Call<VideoData> call, Response<VideoData> response) {
                try {
                    System.out.println("VideoFragment onResponse");
                    System.out.println(response.body().data);//json
                    setDataToListView(response.body().data);
                    //# 1:滚动播放列表中心的视频
                    initCalculator();
                    //# 6:添加滚动监听器
                    onListViewScroll();
                    initIndex();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void onFailure(Call<VideoData> call, Throwable t) {
                Toast.makeText(getContext(), "网络异常", Toast.LENGTH_SHORT).show();
            }
        });

    }

显示

编写setDataToListView方法显示视频列表

    //3:显示
    private void setDataToListView(VideoData.VideoBean data) {
        if(listView!=null){

            //做一个数据的转换  VlistBean->MyVideoItem
            for(VideoData.VideoBean.VlistBean video: data.vlist){
                list.add(new MyVideoItem(getContext(),getVideoManager(),video));
            }
            //创建适配器
            //#视频列表:1:添加适配器
            //参1:播放管理者 参2:上下文
            VideoListViewAdapter adapter=new VideoListViewAdapter(getVideoManager(),getContext(),list);
            //设置适配器
            listView.setAdapter(adapter);
        }
    }

这时显示的还只是文字和覆盖的图片,还没有播放功能,下面是滚动播放功能。

滚动播放功能实现

初始化列表索引

    @Override
    public void onResume() {
        super.onResume();
        System.out.println("VideoFragment onResume");
        initIndex();
    }
    private void initIndex() {
        if(!list.isEmpty()){
            listView.post(new Runnable() {
                @Override
                public void run() {
                    //由坐标得到item的位置position
                    mListItemVisibilityCalculator.onScrollStateIdle(
                            mItemsPositionGetter,
                            listView.getFirstVisiblePosition(),
                            listView.getLastVisiblePosition());
                }
            });
        }
    }

计算处于列表中间的条目是哪个

    private ListItemsVisibilityCalculator mListItemVisibilityCalculator;
    //# 2:Getter可以获取视频的position
    private ItemsPositionGetter mItemsPositionGetter;
    /*
	# 3:将坐标转成position
	记录列表滚动的状态
	    SCROLL_STATE_IDLE:列表停住
	*/
    private int mScrollState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
    private void initCalculator() {
        /**
         * 5:用于计算处于列表中间的条目是哪个。
         * 暂停其他视频,播放当前视频
         */
        mListItemVisibilityCalculator =
                new SingleListViewItemActiveCalculator(new DefaultSingleItemCalculatorCallback(), list);

        mItemsPositionGetter = new ListViewItemPositionGetter(listView);
    }

滚动播放

    private void onListViewScroll() {
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                // # 6 :记录状态
                mScrollState = scrollState;
                if (scrollState == SCROLL_STATE_IDLE && !list.isEmpty()) { //停止
                    mListItemVisibilityCalculator.onScrollStateIdle(mItemsPositionGetter, view.getFirstVisiblePosition(), view.getLastVisiblePosition());
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (!list.isEmpty()) {
                    //计算可见item的坐标
                    System.out.println("mListItemVisibilityCalculator="+mListItemVisibilityCalculator);
                    System.out.println("mItemsPositionGetter="+mItemsPositionGetter);
                    mListItemVisibilityCalculator.onScroll(mItemsPositionGetter, firstVisibleItem, visibleItemCount, mScrollState);
                }
            }
        });
    }

当页面处于后台时,那么停止播放

    @Override
    public void onStop() {
        super.onStop();
        // 如果页面处于后台,那么停止播放
        playerManager.resetMediaPlayer();
    }