MultiVideoLayout多人视频

116 阅读1分钟
public class MultiVideoLayout extends ViewGroup {

    private Context context;

    private int childVerticalSpace; //纵向子view间距
    private int childHorizontalSpace;   //横向子view间距
    private int maxColumnNum;  //最大列数
    private int maxRowNum; //最大行数
    private int childWidth; //子view宽度
    private int childHeight;    //子view高度

    private Map<String, VideoUserWindow> userWindowMap;
    private Map<String, Rect> userLocationMap;

    private User user;

    public MultiVideoLayout(Context context) {
        this(context, null);
    }

    public MultiVideoLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        userWindowMap = new HashMap<>();
        userLocationMap = new HashMap<>();
        user = UserUtil.getUserUtil(context).getUserData();
        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MultiVideoLayout);
        if (attributes != null) {
            childVerticalSpace = attributes.getDimensionPixelSize(R.styleable.MultiVideoLayout_childVerticalSpace, 0);
            childHorizontalSpace = attributes.getDimensionPixelSize(R.styleable.MultiVideoLayout_childHorizontalSpace, 0);
            maxColumnNum = attributes.getInt(R.styleable.MultiVideoLayout_maxColumnNum, 0);
            maxRowNum = attributes.getInt(R.styleable.MultiVideoLayout_maxRowNum, 0);
            attributes.recycle();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        int childCount = getChildCount();

        if (childCount == 0) {
            setMeasuredDimension(0, 0);
        } else {
            childWidth = (width - (maxColumnNum - 1) * childHorizontalSpace) / maxColumnNum;
            childHeight = (height - (maxRowNum - 1) * childVerticalSpace) / maxRowNum;

            for (int i = 0; i < getChildCount(); i++) {
                getChildAt(i).measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
            }
            int realWidth = width;
            int realHeight;

            if (childCount < maxColumnNum) {
                realWidth = childCount * childWidth + ((childCount - 1) * childHorizontalSpace);
            }

            int rowCount = childCount / maxColumnNum + (childCount % maxColumnNum != 0 ? 1 : 0);
            realHeight = rowCount * childHeight + (rowCount - 1) * childVerticalSpace;

            setMeasuredDimension(realWidth, realHeight);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left;
        int top;
        for (int i = 0; i < getChildCount(); i++) {
            VideoUserWindow userWindow = (VideoUserWindow) getChildAt(i);
            left = (i % maxColumnNum) * (childWidth + childHorizontalSpace);
            top = (i / maxRowNum) * (childHeight + childVerticalSpace);
            userWindow.layout(left, top, left + childWidth, top + childHeight);
        }
    }

    public void addUser(String userId) {
        if (!isExistUser(userId)) {
            VideoUserWindow userWindow = new VideoUserWindow(context);
            userWindow.bindUser(userId);
            addView(userWindow);
            userWindow.setOnLayoutChangeListener(userWindow1 -> userWindow1.post(() -> {
                int[] userLocation = new int[2];
                //保存每个视频窗口在屏幕中的坐标
                userWindow1.getLocationOnScreen(userLocation);
                Rect rect = new Rect();
                rect.left = userLocation[0];
                rect.top = userLocation[1];
                rect.right = userLocation[0] + userWindow1.getWidth();
                rect.bottom = userLocation[1] + userWindow1.getHeight();
                LogUtil.error("坐标", "l=" + rect.left + "&t=" + rect.top + "&r=" + rect.right + "&b=" + rect.bottom);
                userLocationMap.put(userId,rect);
            }));
            userWindowMap.put(userId, userWindow);
        }
    }

    public void removeUser(String userId) {
        if (isExistUser(userId)) {
            removeView(userWindowMap.get(userId));
            userWindowMap.remove(userId);
            userLocationMap.remove(userId);
        }
    }

    public VideoUserWindow getUser(String userId) {
        return isExistUser(userId) ? userWindowMap.get(userId) : null;
    }

    public boolean isExistUser(String userId) {
        return userWindowMap.containsKey(userId);
    }

    // 删除所有的子view
    public void removeAllUser() {
        userWindowMap.clear();
        removeAllViews();
    }

    public void replace(String oldUserId,String newUserId) {
        VideoUserWindow userWindow = userWindowMap.remove(oldUserId);
        userWindowMap.put(newUserId,userWindow);
        //如果原view的userId是自己,就停掉预览,不是自己就停止订阅视频流
        if (oldUserId.equals(user.getUserId())) {
            userWindow.stopPreviewView();
        } else {
            MeetingManager.getInstance().stopPlay(oldUserId, PaasPlusSDKStreamType.VIDEO);
        }
        //如果拖拽下来的用户的userId是自己,就开启预览,不是自己就绑定userId订阅视频流更新用户信息
        if (newUserId.equals(user.getUserId())) {
            userWindow.bindUser(newUserId);
            userWindow.setPreviewView();
        } else {
            userWindow.bindUser(newUserId);
            userWindow.startPlay();
            userWindow.updateUser();
        }

        userWindow.switchCamera();

        userLocationMap.put(newUserId,userLocationMap.remove(oldUserId));
    }

    public Map<String, Rect> getUserLocation() {
        return userLocationMap;
    }

    //达到子view最大值
    public boolean isMax() {
        return getChildCount() >= maxColumnNum * maxRowNum;
    }

    //设置在讲话的用户样式
    public void setActiveVoice(String userId, boolean isMaxVoice) {
        if (isMaxVoice) {
            for (Map.Entry<String, VideoUserWindow> entry : userWindowMap.entrySet()) {
                if (entry.getKey().equals(userId)) {
                    entry.getValue().setMaxVoice(true);
                } else {
                    entry.getValue().setMaxVoice(false);
                }
            }
        } else {
            for (Map.Entry<String, VideoUserWindow> entry : userWindowMap.entrySet()) {
                entry.getValue().setMaxVoice(false);
            }
        }
    }

}