android recycleView 原来还可以这么用,,,,,,显示四路视频

最近公司做项目,要求可以显示四路视频,如果 用 布局包裹的话  那会非常麻烦,后来在大神的带领下,知道了用recycleview可以实现,

具体的需求如下

























具体的需求如上图  接下来用recycleview实现此功能,直接上代码

1, recycleview 继承类

public class VideoViewContainer extends RecyclerView {
    public VideoViewContainer(Context context) {
        super(context);
    }

    public VideoViewContainer(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public VideoViewContainer(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    private VideoViewRecycleAdapter mVideoViewRecycleAdapter;

    private boolean initAdapter(LinkedHashMap<String, StreamView> users) {
        if (mVideoViewRecycleAdapter == null) {
            mVideoViewRecycleAdapter = new VideoViewRecycleAdapter(getContext(), users);
            return true;
        }
        return false;
    }

    public void initViewContainer(Context context, LinkedHashMap<String, StreamView> streamViewMap) {
/*        ArrayList<StreamView> list = new ArrayList<StreamView>();
        Collection<StreamView> collection = streamViewMap.values();
        Iterator<StreamView> iterator = collection.iterator();
        while (iterator.hasNext()) {
            StreamView value = (StreamView) iterator.next();
            list.add(value);
        }*/
        boolean newCreated = initAdapter(streamViewMap);  //初始化adapter

        if (!newCreated) {
           mVideoViewRecycleAdapter.init(streamViewMap);  //adapter里面的方法 主要是为了计算出 每个item的高度
        }

        this.setAdapter(mVideoViewRecycleAdapter);

        int count = streamViewMap.size();  //streamViewMap为activity传过来的 装有surfaceview的 集合
        if (count < 2) { // only local full view or or with one peer  当有一路视频或者没有视频的时候 布局
            this.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
        } else if (count == 2 || count == 4) {  //当有两路视频或者四路视频的时候布局
       //     this.setLayoutManager(new GridLayoutManager(context, 2, RecyclerView.VERTICAL, false));
            GridLayoutManager llmv;
            llmv = new GridLayoutManager(context,2, GridLayoutManager.VERTICAL, false);
            this.setLayoutManager(llmv);
        }else if(count == 3){  //当有三路视频时候布局
            GridLayoutManager llmv;
            llmv = new GridLayoutManager(context,2, GridLayoutManager.VERTICAL, false);
            llmv.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    //返回值:跨列数
                    if (position == 2){
                        return 2;
                    }
                    return 1;
                }
            });
            this.setLayoutManager(llmv);
        }

        mVideoViewRecycleAdapter.notifyDataSetChanged();
    }

其中标注已经非常清楚了 大家可以看一下

2..下面是adapter  videoviewRecycleviewAdapter

public class VideoViewRecycleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    protected LayoutInflater mInflater;
    protected Context mContext;

  public ArrayList<StreamView> mUsers;
    public VideoViewRecycleAdapter(Context context, LinkedHashMap<String, StreamView> users) {
        mContext = context;
        mInflater = ((Activity) context).getLayoutInflater();
        mUsers = new ArrayList<>();
        if(users != null) {
            for (LinkedHashMap.Entry<String, StreamView> entry : users.entrySet()) {
                mUsers.add(entry.getValue());
            }
        }
    }

    protected int mItemWidth = 0;
    protected int mItemHeight = 0;

    /**
     * 实现的方法  主要是初始化布局
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.d("VideoViewAdapter", "--------------------onCreateViewHolder " + viewType);

        View v = mInflater.inflate(R.layout.item_recycle_video, parent, false);
        Log.d("VideoViewAdapter", "--------------------onCreateViewHolder mInflaterend");

        Log.d("VideoViewAdapter", "--------------------onCreateViewHolder container end");
        v.getLayoutParams().width = mItemWidth;
        v.getLayoutParams().height = mItemHeight;
        return new VideoHolder(v);
    }

    /**
     * 主要是检查传过来的view 有没有父类,如果有父类的话不删除的话  在addview会报错
     * @param view
     */
    protected final void stripSurfaceView(View view) {
        if(view == null){
            return;
        }
        ViewParent parent = view.getParent();
        if (parent != null) {
            ((ViewGroup) parent).removeView(view);
        }
    }

    /**
     * 计算出在不同路视频的情况下 item的高度
     * @param users 这里主要是 装有surfacaview 的集合 streamview继承了surfaceview
     */
    public void init(LinkedHashMap<String, StreamView> users){

        int beforeCount = mUsers.size();
        mUsers.clear();
        for (LinkedHashMap.Entry<String, StreamView> entry : users.entrySet()) {
            mUsers.add(entry.getValue());
        }
            WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics outMetrics = new DisplayMetrics();
            windowManager.getDefaultDisplay().getMetrics(outMetrics);

            int count = mUsers.size();
            int DividerX = 1;
            int DividerY = 1;
            if (count > 1) {
                DividerX = 2;
                DividerY = 2;
            }

            mItemWidth = outMetrics.widthPixels / DividerX;
            mItemHeight = outMetrics.heightPixels / DividerY;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        VideoHolder myHolder = ((VideoHolder) holder);

        final StreamView user = mUsers.get(position);

        V2Log.d("VideoViewAdapter","-----------------------------onBindViewHolder " + position + " " + user + " " + myHolder + " " + myHolder.itemView);
        LinearLayout holderView = (LinearLayout) myHolder.itemView;  //通过holder 获得每个item 布局
        FrameLayout container;
        container = (FrameLayout) holderView.findViewById(R.id.video_view_container);
        if(mUsers.size()==2){   //当有两路视频时 布局的位置显示和显示大小
            LinearLayout.LayoutParams layoutParams
           = new LinearLayout.LayoutParams(mItemWidth, mItemHeight);
                //    (FrameLayout.LayoutParams) holderView.getLayoutParams();
           layoutParams.setMargins(0, mItemHeight/2,0 , mItemHeight/2);
            holderView.setLayoutParams(layoutParams);
        }else if(position==2 && mUsers.size()==3){  //当有三路视频时  第三路布局的位置显示 和显示大小
            Log.e("VideoViewAdapter","-----------------------------onBindViewHolder " + position + " " + user + " " + myHolder + " " + myHolder.itemView);
            LinearLayout.LayoutParams layoutParams
                    = new LinearLayout.LayoutParams(mItemWidth, mItemHeight);
               // (FrameLayout.LayoutParams) holderView.getLayoutParams();
            layoutParams.setMargins(mItemWidth/2, 0,mItemWidth/2 , 0);
            holderView.setLayoutParams(layoutParams);
        }

        if (container.getChildCount() == 0 && user!=null) {  //当为一路视频时,全屏显示
            stripSurfaceView(user);
            container.addView(user, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        }
    }

    @Override
    public int getItemCount() {
        Log.d("VideoViewAdapter", "getItemCount " + mUsers.size());
        int sizeLimit = mUsers.size();
        if (sizeLimit >= 4) {
            sizeLimit = 4;
        }
        return sizeLimit;
    }

}
里面的注释已经很清楚了 ,

3, streamview 为surfaceview的封装类

public class StreamView extends RelativeLayout {
    TextView textView,textViewName;
    SurfaceView surfaceView;
    boolean isLocalStream;

    public long getStreamId() {
        return streamId;
    }

    public long getUserId() {
        return userId;
    }

    long streamId;
    long userId;
    public StreamView(@NonNull Context context, SurfaceView view, boolean local,long streamId, long userId) {
        super(context);
        isLocalStream = local;
        this.streamId = streamId;
        this.userId = userId;
        textView = new TextView(context);
        textViewName = new TextView(context);
        surfaceView = view;
        initSurfaceView();

    }

    public StreamView(@NonNull Context context, @Nullable AttributeSet attrs, SurfaceView view, boolean local,long streamId, long userId) {
        super(context, attrs);
        this.addView(view);
        isLocalStream = local;
        this.streamId = streamId;
        this.userId = userId;
        surfaceView = view;
        textView = new TextView(context);
        textViewName = new TextView(context);
        initSurfaceView();
    }

    public StreamView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, SurfaceView view, boolean local,long streamId, long userId) {
        super(context, attrs, defStyleAttr);
        this.addView(view);
        isLocalStream = local;
        this.streamId = streamId;
        this.userId = userId;
        surfaceView = view;
        textView = new TextView(context);
        textViewName = new TextView(context);
        initSurfaceView();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public StreamView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, SurfaceView view, boolean local,long streamId, long userId) {
        super(context, attrs, defStyleAttr, defStyleRes);
        isLocalStream = local;
        this.streamId = streamId;
        this.userId = userId;
        surfaceView = view;
        textView = new TextView(context);
        textViewName = new TextView(context);
        initSurfaceView();
    }

    public void initSurfaceView(){
        LayoutParams layoutParams
           =new LayoutParams(LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
        if(surfaceView!= null) {
            surfaceView.setLayoutParams(layoutParams);
        }
        this.addView(surfaceView);
        LayoutParams layoutParams2
                =new LayoutParams(LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            layoutParams2.setMarginEnd(10);
        }
        layoutParams2.rightMargin = 10;
        layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
    //    layoutParams.addRule(RelativeLayout.);
        textView.setLayoutParams(layoutParams2);
        this.addView(textView);

        LayoutParams layoutParams1 = new LayoutParams(layoutParams.WRAP_CONTENT,layoutParams.WRAP_CONTENT);
        layoutParams1.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        layoutParams1.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        layoutParams1.rightMargin = 10;
        textViewName.setLayoutParams(layoutParams1);
        this.addView(textViewName);
    }
里面主要是 加入了surfaceview  textview显示姓名等

4.adapter 布局 

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="@drawable/video_view_border"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">
    <FrameLayout
        android:layout_margin="2dp"
        android:layout_marginBottom="2dp"
        android:layout_marginTop="2dp"
        android:layout_marginLeft="2dp"
        android:layout_marginEnd="2dp"
        android:layout_marginRight="2dp"
        android:gravity="center"
        android:id="@+id/video_view_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        >

    </FrameLayout>
</LinearLayout>


最后 通过上面的主要代码,就可以完成如图上面的需求拉 ,希望可以帮助到小伙伴们




猜你喜欢

转载自blog.csdn.net/qq_35893839/article/details/79125952