MultiMeetingView多人会议

73 阅读1分钟
public class MultiMeetingView extends FrameLayout implements IUserUpdateCallback, SpectatorView.OnItemLongClickListener, View.OnTouchListener {

    //观众席容器
    private SpectatorView spectatorView;
    //四宫格容器
    private MultiVideoLayout multiVideoLayout;

    private ImageView touchView;
    private String touchUserId;

    private User user;

    private float lastX;
    private float lastY;

    public MultiMeetingView(@NonNull @NotNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    private void initView(Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.layout_multi_meeting, this);
        spectatorView = view.findViewById(R.id.spectator_view);
        multiVideoLayout = view.findViewById(R.id.multi_video_layout);
        MeetingManager.getInstance().addUserUpdateCallback(this.getClass(), this);
        spectatorView.setOnItemLongClickListener(this);
    }

    @Override
    public void addUser(String userId) {
        if (multiVideoLayout.isMax()) { //四宫格满了添加至观众席
            spectatorView.setVisibility(View.VISIBLE);
            spectatorView.addUser(userId);
        } else {
            spectatorView.setVisibility(View.GONE);
            multiVideoLayout.addUser(userId);
        }
    }

    @Override
    public void updateUser(String userId) {
        //四宫格更新用户
        if (multiVideoLayout.isExistUser(userId)) {
            multiVideoLayout.getUser(userId).updateUser();
        }
        //观众席更新用户
        if (spectatorView.isExistUser(userId)) {
            spectatorView.updateUser(userId);
        }
    }

    @Override
    public void removeUser(String userId) {
        if (multiVideoLayout.isExistUser(userId)) {
            multiVideoLayout.removeUser(userId);
            //如果删除的是四宫格,并且观众席有用户,就拉第一个补位
            if (spectatorView.getData() != null && spectatorView.getData().size() > 0) {
                //补位用户添加
                multiVideoLayout.addUser(spectatorView.getData().get(0).getUserId());
                //补位用户拉流
                multiVideoLayout.getUser(spectatorView.getData().get(0).getUserId()).startPlay();
                //补位用户更新
                multiVideoLayout.getUser(spectatorView.getData().get(0).getUserId()).updateUser();
                //四宫格补位完观众席删掉
                spectatorView.removeUser(spectatorView.getData().get(0).getUserId(), 0);
                //如果观众席没人则隐藏
                if (spectatorView.getData() == null || (spectatorView.getData() != null && spectatorView.getData().size() == 0)) {
                    spectatorView.setVisibility(View.GONE);
                }
            }
        } else if (spectatorView.isExistUser(userId)) {
            spectatorView.removeUser(userId);
            //如果观众席没人则隐藏
            if (spectatorView.getData() == null || (spectatorView.getData() != null && spectatorView.getData().size() == 0)) {
                spectatorView.setVisibility(View.GONE);
            }
        }
    }

    @Override
    public void userCameraStateUpdate(String userId) {
        if (multiVideoLayout.isExistUser(userId)) {
            multiVideoLayout.getUser(userId).switchCamera();
        }
    }

    @Override
    public void userMicStateUpdate(String userId) {
        if (multiVideoLayout.isExistUser(userId)) {
            multiVideoLayout.getUser(userId).switchMic();
        }
    }

    @Override
    public void onStreamUpdate(String userId, boolean isAdd) {
        if (multiVideoLayout.isExistUser(userId)) {
            if (isAdd) {
                multiVideoLayout.getUser(userId).startPlay();
            } else {
                multiVideoLayout.getUser(userId).stopPlay();
            }
        }
        if (spectatorView.isExistUser(userId) && !isAdd) {
            MeetingManager.getInstance().stopPlay(userId);
        }
    }

    @Override
    public void onVideoStreamUpdate(String userId, boolean isVideoStream) {
        if (multiVideoLayout.isExistUser(userId)) {
            multiVideoLayout.getUser(userId).switchCamera();
        }
    }

    public void setActiveVoice(String userId) {
        if (multiVideoLayout.isExistUser(userId)) {
            multiVideoLayout.setActiveVoice(userId, true);
            spectatorView.setActiveVoice(userId, false);
        } else if (spectatorView.isExistUser(userId)) {
            spectatorView.setActiveVoice(userId, true);
            multiVideoLayout.setActiveVoice(userId, false);
        } else {
            multiVideoLayout.setActiveVoice("", false);
            if (multiVideoLayout.isMax()) {
                spectatorView.setActiveVoice("", false);
            }
        }
    }

    public void setVisible(boolean isVisible) {
        if (isVisible) {
            if (isVisible()) {
                return;
            }
            setVisibility(View.VISIBLE);
            multiVideoLayout.getUser(user.getUserId()).switchCamera();
            setRemoteStream(true);
        } else {
            if (!isVisible()) {
                return;
            }
            setVisibility(View.GONE);
            setRemoteStream(false);
        }
    }

    public void setRemoteStream(boolean isStart) {
        if (isStart) {
            for (int i = 0; i < multiVideoLayout.getChildCount(); i++) {
                VideoUserWindow userWindow = (VideoUserWindow) multiVideoLayout.getChildAt(i);
                userWindow.startPlay();
            }
        } else {
            for (int i = 0; i < multiVideoLayout.getChildCount(); i++) {
                VideoUserWindow userWindow = (VideoUserWindow) multiVideoLayout.getChildAt(i);
                userWindow.stopPlay();
            }
        }
    }

    public boolean isVisible() {
        return getVisibility() == View.VISIBLE;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public void onItemLongClick(View view, String userId, int x, int y) {
        if (touchView != null) {
            spectatorView.replace(touchUserId, "", false);
            removeView(touchView);
            touchView = null;
            touchUserId = "";
        }
        touchUserId = userId;
        touchView = new ImageView(getContext());
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(view.getWidth(), view.getHeight());
        params.leftMargin = x;
        params.topMargin = y - view.getHeight() / 2 - DensityUtil.dip2px(getContext(), 48);
        touchView.setLayoutParams(params);
        addView(touchView);
        if (TextUtils.isEmpty(MeetingManager.getInstance().getUser(touchUserId).getAvatarUrl())) {
            touchView.setImageResource(R.drawable.common_contact_avatar_bg);
        } else {
            GlideShowUtil.showCircleImage(getContext(), touchView, MeetingManager.getInstance().getUser(touchUserId).getAvatarUrl());
        }

        touchView.setOnTouchListener(MultiMeetingView.this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (v == touchView) {
            float x = event.getX();
            float y = event.getY();
            int[] viewPosition = new int[2];
            v.getLocationOnScreen(viewPosition);
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    lastX = x;
                    lastY = y;
                    break;
                case MotionEvent.ACTION_MOVE:
                    int moveX = (int) (x - lastX);
                    int moveY = (int) (y - lastY);
                    FrameLayout.LayoutParams moveParams = (FrameLayout.LayoutParams) touchView.getLayoutParams();
                    moveParams.leftMargin = viewPosition[0] + moveX;
                    moveParams.topMargin = viewPosition[1] - DensityUtil.dip2px(getContext(), 48) + moveY;
                    touchView.setLayoutParams(moveParams);
                    break;
                case MotionEvent.ACTION_UP:
                    if (touchView != null) {
                        matchVideoWindow((int) touchView.getX(), (int) touchView.getY());
                        removeView(touchView);
                        touchView = null;
                        touchUserId = "";
                    }
                    break;
            }
            return true;
        }
        return false;
    }

    //判断手指离开屏幕的坐标是否在视频窗口范围内
    private void matchVideoWindow(int x, int y) {
        for (Map.Entry<String, Rect> rectEntry : multiVideoLayout.getUserLocation().entrySet()) {
            if (rectEntry.getValue().contains(x, y)) {
                //匹配到了,开始交换
                spectatorView.replace(touchUserId, rectEntry.getKey(), true);
                multiVideoLayout.replace(rectEntry.getKey(), touchUserId);
                return;
            }
        }
        //没有匹配到,交换失败,显示原来的view
        spectatorView.replace(touchUserId, "", false);
    }
}