Browse Source

更新学生端直播间部分逻辑

Pq 3 years ago
parent
commit
bfbdfa7f0f

+ 74 - 22
rong_im/live/src/main/java/com/rong/io/live/widget/LiveRoomMicIconView.java

@@ -25,6 +25,8 @@ public class LiveRoomMicIconView extends LinearLayout {
     private ArrayList<UserInfo> mMicUserInfos;
     private String mCurrentUserId;
     public static final String DEFAULT_NICK = "连麦用户";
+    public OnEventListener mEventListener;
+    private String mCurrentUserName;
 
     public LiveRoomMicIconView(Context context) {
         this(context, null);
@@ -44,20 +46,7 @@ public class LiveRoomMicIconView extends LinearLayout {
         setGravity(Gravity.CENTER_VERTICAL);
         mMicUserInfos = new ArrayList<>();
         mCurrentUserId = UserHelper.getUserId();
-    }
-
-    public void delAllExcludeOwn() {
-        if (mMicUserInfos != null) {
-            int i = checkContain(mCurrentUserId);
-            UserInfo userInfo;
-            if (i != -1) {
-                userInfo = mMicUserInfos.get(i);
-                mMicUserInfos.clear();
-                addMicUser(userInfo);
-            } else {
-                delAll();
-            }
-        }
+        mCurrentUserName = UserHelper.getUserName();
     }
 
     public void delAll() {
@@ -67,7 +56,12 @@ public class LiveRoomMicIconView extends LinearLayout {
         }
     }
 
-    public void addMicUser(UserInfo userInfo) {
+    private void refreshAllUser() {
+        removeAllViews();
+        createMicTag();
+    }
+
+    public void updateTargetUserInfo(UserInfo userInfo) {
         int i = checkContain(userInfo.getUserId());
         if (i != -1) {
             String oldName = mMicUserInfos.get(i).getName();
@@ -78,8 +72,7 @@ public class LiveRoomMicIconView extends LinearLayout {
         } else {
             mMicUserInfos.add(userInfo);
         }
-        removeAllViews();
-        createMicTag();
+        refreshAllUser();
     }
 
     private void createMicTag() {
@@ -135,11 +128,70 @@ public class LiveRoomMicIconView extends LinearLayout {
         return pos;
     }
 
-    public UserInfo getUserInfoIfExist(String userId) {
-        int i = checkContain(userId);
-        if (i != -1 && i < mMicUserInfos.size()) {
-            return mMicUserInfos.get(i);
+    public void refreshUI(ArrayList<String> onMicUserIds) {
+        post(new Runnable() {
+            @Override
+            public void run() {
+                if (onMicUserIds != null && onMicUserIds.size() > 0) {
+                    ArrayList<UserInfo> lastOnMicUser = new ArrayList<>();
+                    if (mMicUserInfos != null && mMicUserInfos.size() != 0) {
+                        for (int i = 0; i < mMicUserInfos.size(); i++) {
+                            //找出已有的连麦用户信息
+                            UserInfo userInfo = mMicUserInfos.get(i);
+                            int pos = checkExitForTargetList(userInfo.getUserId(), onMicUserIds);
+                            if (pos != -1) {
+                                lastOnMicUser.add(userInfo);
+                                onMicUserIds.remove(pos);
+                            }
+                        }
+                    }
+                    for (int i = 0; i < onMicUserIds.size(); i++) {
+                        String s = onMicUserIds.get(i);
+                        UserInfo userInfo = new UserInfo(s, DEFAULT_NICK, null);
+                        lastOnMicUser.add(userInfo);
+                    }
+                    delAll();
+                    for (int i = 0; i < lastOnMicUser.size(); i++) {
+                        UserInfo targetUser = lastOnMicUser.get(i);
+                        if (TextUtils.equals(targetUser.getUserId(), mCurrentUserId)) {
+                            //如果是自身则不需要查询,直接取缓存名称
+                            targetUser.setName(mCurrentUserName);
+                        }
+                        String lastName = targetUser.getName();
+                        if (TextUtils.isEmpty(lastName) || TextUtils.equals(lastName, DEFAULT_NICK)) {
+                            //如果昵称为空,查询昵称
+                            if (mEventListener != null) {
+                                mEventListener.getUserInfoByUserId(targetUser.getUserId());
+                            }
+                        }
+                    }
+                    mMicUserInfos.addAll(lastOnMicUser);
+                    refreshAllUser();
+                } else {
+                    delAll();
+                }
+            }
+        });
+    }
+
+    private int checkExitForTargetList(String targetUserId, ArrayList<String> targetList) {
+        if (targetList == null || TextUtils.isEmpty(targetUserId)) {
+            return -1;
+        }
+        for (int i = 0; i < targetList.size(); i++) {
+            String s = targetList.get(i);
+            if (TextUtils.equals(targetUserId, s)) {
+                return i;
+            }
         }
-        return null;
+        return -1;
+    }
+
+    public void setOnEventListener(OnEventListener listener) {
+        mEventListener = listener;
+    }
+
+    public interface OnEventListener {
+        void getUserInfoByUserId(String userId);
     }
 }

+ 2 - 2
student/src/main/java/com/cooleshow/student/api/APIService.java

@@ -395,7 +395,7 @@ public interface APIService {
      *
      * @return
      */
-    @GET("api-web/imLiveBroadcastRoom/joinRoom")
+    @GET(STUDENT_GROUP+"liveRoom/joinRoom")
     Observable<BaseResponse<Object>> notifyJoinRoomAction(@Query("roomUid") String roomUid, @Query("userId") String userId);
 
     /**
@@ -403,7 +403,7 @@ public interface APIService {
      *
      * @return
      */
-    @POST("api-im/user/statusImUser")
+    @POST(STUDENT_GROUP+"liveRoom/syncUserStatus")
     Observable<BaseResponse<Object>> notifyLeaveRoomAction(@Body RequestBody body);
 
     /**

+ 21 - 0
student/src/main/java/com/cooleshow/student/contract/LiveRoomContract.java

@@ -5,6 +5,8 @@ import android.view.View;
 import com.cooleshow.base.presenter.view.BaseView;
 import com.cooleshow.student.bean.FriendInfoBean;
 import com.cooleshow.student.bean.LiveRoomInfoBean;
+import com.rong.io.live.message.RCChatJoinRoomMessage;
+import com.rong.io.live.message.RCOnSnappingUpMessage;
 import com.rong.io.live.message.RCUserKickOutMessage;
 import com.rong.io.live.message.RCUserLogOutUnusualMessage;
 import com.rong.io.live.message.RCUserSeatApplyMessage;
@@ -155,6 +157,25 @@ public interface LiveRoomContract {
          * @param isAddBlack
          */
         void changeBlackUserStatus(String userId,boolean isAddBlack);
+        /**
+         * 加入房间消息
+         *
+         * @param joinRoomMessage
+         */
+        void receiveJoinMessage(RCChatJoinRoomMessage joinRoomMessage);
+
+        /**
+         * 抢购消息
+         *
+         * @param
+         */
+        void receiveSnapUpMessage(RCOnSnappingUpMessage snappingUpMessage);
+
+        /**
+         * 远端有用户推流
+         * @param remoteUserId
+         */
+        void onRemoteUserPublishResource(String remoteUserId);
     }
 
     interface Presenter {

+ 87 - 2
student/src/main/java/com/cooleshow/student/presenter/live/LiveRoomPresenter.java

@@ -51,6 +51,7 @@ import cn.rongcloud.rtc.api.callback.IRCRTCRoomEventsListener;
 import cn.rongcloud.rtc.api.callback.IRCRTCSwitchRoleCallback;
 import cn.rongcloud.rtc.api.callback.IRCRTCSwitchRoleDataCallback;
 import cn.rongcloud.rtc.api.stream.RCRTCAudioInputStream;
+import cn.rongcloud.rtc.api.stream.RCRTCAudioOutputStream;
 import cn.rongcloud.rtc.api.stream.RCRTCInputStream;
 import cn.rongcloud.rtc.api.stream.RCRTCLiveInfo;
 import cn.rongcloud.rtc.api.stream.RCRTCOutputStream;
@@ -84,8 +85,10 @@ public class LiveRoomPresenter extends BasePresenter<LiveRoomContract.view> impl
     private final IRCRTCRoomEventsListener mRoomEventsListener = new IRCRTCRoomEventsListener() {
         @Override
         public void onRemoteUserPublishResource(RCRTCRemoteUser rcrtcRemoteUser, List<RCRTCInputStream> list) {
-            Log.i("pq", "onRemoteUserPublishResource");
-            subscribeAVStream();
+            Log.i("pq", "onRemoteUserPublishResource:");
+            if (getView() != null) {
+                getView().onRemoteUserPublishResource(rcrtcRemoteUser.getUserId());
+            }
         }
 
         @Override
@@ -706,6 +709,24 @@ public class LiveRoomPresenter extends BasePresenter<LiveRoomContract.view> impl
                             }
                         }
 
+                        if (TextUtils.equals(message.getObjectName(), LiveRoomMsgConstants.TAG_CHAT_ROOM_ENTER)) {
+                            //加入房间消息
+                            if (null != getView() && message.getContent() != null) {
+                                RCChatJoinRoomMessage joinRoomMessage = (RCChatJoinRoomMessage) message.getContent();
+                                getView().receiveJoinMessage(joinRoomMessage);
+                            }
+                            return;
+                        }
+
+                        if (TextUtils.equals(message.getObjectName(), LiveRoomMsgConstants.TAG_LIVE_ON_SNAP_UP)) {
+                            //抢购消息
+                            if (null != getView() && message.getContent() != null) {
+                                RCOnSnappingUpMessage rcOnSnappingUpMessage = (RCOnSnappingUpMessage) message.getContent();
+                                getView().receiveSnapUpMessage(rcOnSnappingUpMessage);
+                            }
+                            return;
+                        }
+
 
                         //以下为行为消息逻辑
                         //行为消息
@@ -892,6 +913,70 @@ public class LiveRoomPresenter extends BasePresenter<LiveRoomContract.view> impl
         }
     }
 
+    /**
+     * 获得当前房间所有的视频流和音频流
+     */
+    public void getAllStreams(List<RCRTCVideoOutputStream> outputStreams, List<RCRTCVideoInputStream> inputStreams, List<RCRTCAudioInputStream> audioinputstream, List<RCRTCAudioOutputStream> audioOutputStreams) {
+        RCRTCRoom mRtcRoom = LiveEventHelper.getInstance().getRtcRoom();
+        if (mRtcRoom == null) {
+            return;
+        }
+        for (final RCRTCRemoteUser remoteUser : mRtcRoom.getRemoteUsers()) {
+            if (remoteUser.getStreams().size() == 0) {
+                continue;
+            }
+            List<RCRTCInputStream> userStreams = remoteUser.getStreams();
+            for (RCRTCInputStream i : userStreams) {
+                if (i.getMediaType() == RCRTCMediaType.VIDEO) {
+                    inputStreams.add((RCRTCVideoInputStream) i);
+                }
+                if (i.getMediaType() == RCRTCMediaType.AUDIO) {
+                    audioinputstream.add((RCRTCAudioInputStream) i);
+                }
+            }
+        }
+
+        for (RCRTCOutputStream o : mRtcRoom.getLocalUser().getStreams()) {
+            if (o.getMediaType() == RCRTCMediaType.VIDEO) {
+                outputStreams.add((RCRTCVideoOutputStream) o);
+            }
+            if (o.getMediaType() == RCRTCMediaType.AUDIO) {
+                audioOutputStreams.add((RCRTCAudioOutputStream) o);
+            }
+        }
+    }
+
+    /**
+     * 获取房间所有的音频流
+     *
+     * @param audioinputstream
+     * @param audioOutputStreams
+     */
+    public void getAudioStreams(List<RCRTCAudioInputStream> audioinputstream, List<RCRTCAudioOutputStream> audioOutputStreams) {
+        RCRTCRoom mRtcRoom = LiveEventHelper.getInstance().getRtcRoom();
+        if (mRtcRoom == null) {
+            return;
+        }
+
+        for (final RCRTCRemoteUser remoteUser : mRtcRoom.getRemoteUsers()) {
+            if (remoteUser.getStreams().size() == 0) {
+                continue;
+            }
+            List<RCRTCInputStream> userStreams = remoteUser.getStreams();
+            for (RCRTCInputStream i : userStreams) {
+                if (i.getMediaType() == RCRTCMediaType.AUDIO) {
+                    audioinputstream.add((RCRTCAudioInputStream) i);
+                }
+            }
+        }
+
+        for (RCRTCOutputStream o : mRtcRoom.getLocalUser().getStreams()) {
+            if (o.getMediaType() == RCRTCMediaType.AUDIO) {
+                audioOutputStreams.add((RCRTCAudioOutputStream) o);
+            }
+        }
+    }
+
 
     /**
      * 主动订阅远端用户发布的流

+ 217 - 142
student/src/main/java/com/cooleshow/student/ui/live/LiveRoomActivity.java

@@ -19,6 +19,7 @@ import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
@@ -51,6 +52,8 @@ import com.cooleshow.student.bean.LiveRoomInfoBean;
 import com.cooleshow.student.contract.LiveRoomContract;
 import com.cooleshow.student.databinding.ActivityLiveroomLayoutBinding;
 import com.cooleshow.student.presenter.live.LiveRoomPresenter;
+import com.rong.io.live.helper.LiveMemberHelper;
+import com.rong.io.live.helper.LiveMessageHelper;
 import com.rong.io.live.helper.LiveRTCEngineInitHelper;
 import com.cooleshow.student.widgets.dialog.LiveRoomCloseMicTipDialog;
 import com.cooleshow.student.widgets.dialog.LiveRoomClosePageOnMicTipDialog;
@@ -61,6 +64,8 @@ import com.cooleshow.usercenter.helper.UserHelper;
 import com.rong.io.live.LiveRoomMsgConstants;
 import com.rong.io.live.config.LiveConfig;
 import com.rong.io.live.helper.LiveEventHelper;
+import com.rong.io.live.message.RCChatJoinRoomMessage;
+import com.rong.io.live.message.RCOnSnappingUpMessage;
 import com.rong.io.live.message.RCUserKickOutMessage;
 import com.rong.io.live.message.RCUserLogOutUnusualMessage;
 import com.rong.io.live.message.RCUserSeatApplyMessage;
@@ -86,6 +91,7 @@ import cn.rongcloud.rtc.api.RCRTCRemoteUser;
 import cn.rongcloud.rtc.api.RCRTCRoom;
 import cn.rongcloud.rtc.api.RCRTCVideoStream;
 import cn.rongcloud.rtc.api.stream.RCRTCAudioInputStream;
+import cn.rongcloud.rtc.api.stream.RCRTCAudioOutputStream;
 import cn.rongcloud.rtc.api.stream.RCRTCInputStream;
 import cn.rongcloud.rtc.api.stream.RCRTCVideoInputStream;
 import cn.rongcloud.rtc.api.stream.RCRTCVideoOutputStream;
@@ -137,6 +143,10 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
     ImageView mIvShopCar;
     ImageView mIvClose;
     TextView tv_input;
+    FrameLayout mFlJoinBarrage;
+    TextView mTvJoinBarrage;
+    FrameLayout mFlSnapUpBarrage;
+    TextView mTvSnapUpBarrage;
 
     private LiveRoomInfoBean mRoomInfoBean;
     private String mRoomId;
@@ -146,6 +156,7 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
     private boolean isEnableMic = false;//默认不禁止
     private boolean isEnableAll = false;//默认不禁止 黑名单状态
     private InputBarDialog mInputBarDialog;
+    private boolean isPcClientLive = true;//默认为PC端直播
     private int currentSeatStatus = LiveRoomMsgConstants.MIC_STATUS_NORMAL;//1未连麦,2连麦中,3连麦成功
     private LiveRoomCloseMicTipDialog mRoomCloseMicTipDialog;
     private LiveRoomInviteSeatMicTipDialog mInviteSeatMicTipDialog;
@@ -246,6 +257,10 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
         mIvShopCar = viewBinding.ivShopCar;
         mIvClose = viewBinding.ivClose;
         tv_input = viewBinding.tvInput;
+        mFlJoinBarrage = viewBinding.flJoinBarrage;
+        mTvJoinBarrage = viewBinding.tvJoinBarrage;
+        mFlSnapUpBarrage = viewBinding.flSnapUpBarrage;
+        mTvSnapUpBarrage = viewBinding.tvSnapUpBarrage;
         initListener();
     }
 
@@ -300,6 +315,14 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
         mRecyclerMsg.setAdapter(mMessageAdapter);
         IMCenter.getInstance().addConnectionStatusListener(connectStatusListener);
         SoftKeyboardUtil.registerSoftInputChangedListener(getWindow(), this);
+        mLlMicContainer.setOnEventListener(new LiveRoomMicIconView.OnEventListener() {
+            @Override
+            public void getUserInfoByUserId(String userId) {
+                if (presenter != null) {
+                    presenter.getUserInfoByUserId(userId);
+                }
+            }
+        });
         prepareInitRoom();
     }
 
@@ -541,13 +564,22 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
         if (mInputBarDialog == null) {
             mInputBarDialog = new InputBarDialog(LiveRoomActivity.this, new InputBar.InputBarListener() {
                 @Override
-                public void onClickSend(String message) {
+                public boolean onClickSend(String message) {
                     //发送消息
                     if (TextUtils.isEmpty(message)) {
                         ToastUtil.getInstance().show(LiveRoomActivity.this, "消息不能为空");
-                        return;
+                        return false;
+                    }
+                    if (message.length() > LiveConfig.LIVE_MAX_INPUT_TEXT_LENGTH) {
+                        ToastUtil.getInstance().show(LiveRoomActivity.this, "聊天消息需在40个字以内哦");
+                        return false;
+                    }
+                    if (LiveMessageHelper.isQuickAction()) {
+                        ToastUtil.getInstance().show(LiveRoomActivity.this, "您说话太快啦");
+                        return false;
                     }
                     sendTextMessage(message);
+                    return true;
                 }
 
 
@@ -625,8 +657,8 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
         if (roomInfoBean == null || isFinishing() || isDestroyed()) {
             return;
         }
-        boolean isPc = !TextUtils.equals("pc", roomInfoBean.os);
-        resetVideoContainer(isPc);
+        isPcClientLive = TextUtils.equals(mRoomInfoBean.os, "pc");
+        resetVideoContainer(!isPcClientLive);
         mRoomInfoBean = roomInfoBean;
         currentAddLikeCount = roomInfoBean.likeNum;
         if (!TextUtils.isEmpty(roomInfoBean.roomConfig)) {
@@ -636,6 +668,17 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
                 int micCtrlMode = jsonObject.optInt("whether_mic", 0);
                 isEnableChat = chatCtrlMode == 1;
                 isEnableMic = micCtrlMode == 1;
+                //购物车是否显示
+                int shopCarMode = jsonObject.optInt("whether_view_shop_cart", 0);
+                if (shopCarMode == 1) {
+                    //隐藏购物车
+                    mViewShopCarAnim.setVisibility(View.GONE);
+                    mIvShopCar.setVisibility(View.GONE);
+                } else {
+                    //显示购物车
+                    mViewShopCarAnim.setVisibility(View.VISIBLE);
+                    mIvShopCar.setVisibility(View.INVISIBLE);
+                }
             } catch (JSONException e) {
                 e.printStackTrace();
             }
@@ -644,7 +687,8 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
         isEnableAll = roomInfoBean.blacklistFlag == 1;//1是黑名单 0否
         updateInputTip();
         updateAddLikeCountView();
-
+        //更新未上麦状态
+        updateMicIcon(LiveRoomMsgConstants.MIC_STATUS_NORMAL);
         if (mTvNumPeople != null) {
             int peopleCount = roomInfoBean.lookNum + 1;//加上自己
             mTvNumPeople.setText(peopleCount + "人");
@@ -714,13 +758,34 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
             mVideoViewManager.setIsNeedFillScreen(isFullScreen);
         }
         if (isFullScreen) {
-            mGroupViews.setVisibility(View.GONE);
-            mIvClose.setVisibility(View.GONE);
-            mIvSwitchVideoOrientation.setVisibility(View.GONE);
-            mIvSwitchVideoOrientationFull.setVisibility(View.VISIBLE);
+            if (isPcClientLive) {
+                //隐藏消息列表
+                mGroupViews.setVisibility(View.GONE);
+                mIvClose.setVisibility(View.GONE);
+                //隐藏弹幕消息
+                mFlJoinBarrage.clearAnimation();
+                mFlJoinBarrage.setVisibility(View.GONE);
+                mFlSnapUpBarrage.clearAnimation();
+                mFlSnapUpBarrage.setVisibility(View.GONE);
+                //隐藏竖屏全屏按钮
+                mIvSwitchVideoOrientation.setVisibility(View.GONE);
+                mIvSwitchVideoOrientationFull.setVisibility(View.VISIBLE);
+            } else {
+                //不是PC端直播
+                mIvSwitchVideoOrientation.setVisibility(View.GONE);
+                mIvSwitchVideoOrientationFull.setVisibility(View.GONE);
+            }
             ConstraintSet set = new ConstraintSet();
             set.clone(content_view);
             set.clear(mFlLiveView.getId());
+            if (!isPcClientLive) {
+                //如果是非PC端直播,还需要设置下消息列表控件位置
+                set.clear(R.id.fl_recycler_container);
+                set.connect(R.id.fl_recycler_container, ConstraintSet.TOP, R.id.view_center, ConstraintSet.BOTTOM, SizeUtils.dp2px(50));
+                set.connect(R.id.fl_recycler_container, ConstraintSet.LEFT, content_view.getId(), ConstraintSet.LEFT, 0);
+                set.connect(R.id.fl_recycler_container, ConstraintSet.RIGHT, content_view.getId(), ConstraintSet.RIGHT, 0);
+                set.connect(R.id.fl_recycler_container, ConstraintSet.BOTTOM, tv_input.getId(), ConstraintSet.TOP, SizeUtils.dp2px(10));
+            }
             set.connect(mFlLiveView.getId(), ConstraintSet.TOP, content_view.getId(), ConstraintSet.TOP, 0);
             set.connect(mFlLiveView.getId(), ConstraintSet.LEFT, content_view.getId(), ConstraintSet.LEFT, 0);
             set.connect(mFlLiveView.getId(), ConstraintSet.RIGHT, content_view.getId(), ConstraintSet.RIGHT, 0);
@@ -732,10 +797,13 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
                 //还原显示头部信息
                 handleHeaderAnim();
             }
-            mGroupViews.setVisibility(View.VISIBLE);
-            mIvClose.setVisibility(View.VISIBLE);
-            mIvSwitchVideoOrientation.setVisibility(View.VISIBLE);
-            mIvSwitchVideoOrientationFull.setVisibility(View.GONE);
+            if (isPcClientLive) {
+                mGroupViews.setVisibility(View.VISIBLE);
+                mIvClose.setVisibility(View.VISIBLE);
+                mIvSwitchVideoOrientation.setVisibility(View.VISIBLE);
+                mIvSwitchVideoOrientationFull.setVisibility(View.GONE);
+            }
+
             ConstraintSet set = new ConstraintSet();
             set.clone(content_view);
             set.clear(mFlLiveView.getId());
@@ -746,7 +814,6 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
             set.constrainHeight(mFlLiveView.getId(), maxHeightAtRatio16_9);
             set.applyTo(content_view);
         }
-        changVideoViewSize();
     }
 
     public void changVideoViewSize() {
@@ -965,6 +1032,20 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
     }
 
     @Override
+    public void onRemoteUserPublishResource(String remoteUserId) {
+        if (!TextUtils.isEmpty(remoteUserId)) {
+            Log.i("pq", "收到onRemoteUserPublishResource:" + remoteUserId);
+            if (mRoomInfoBean != null && TextUtils.equals(mRoomInfoBean.speakerId, remoteUserId)) {
+                if (presenter != null) {
+                    presenter.subscribeAVStream();
+                }
+            } else {
+                refreshAudio(null, null);
+            }
+        }
+    }
+
+    @Override
     public void syncMemberCount(String count) {
         //同步成员数量
         Log.i("pq", "syncMemberCount" + count);
@@ -1017,11 +1098,15 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
     }
 
     private void refresh() {
+        //video流信息
         List<RCRTCVideoOutputStream> outputStreams = new ArrayList<>();
-        List<RCRTCVideoInputStream> input = new ArrayList<>();
+        List<RCRTCVideoInputStream> videoInputStreams = new ArrayList<>();
+        //音频流信息
         List<RCRTCAudioInputStream> audioinputstream = new ArrayList<>();
-        presenter.getVideoStream(outputStreams, input, audioinputstream);
-        updateVideoView(outputStreams, input, audioinputstream);
+        List<RCRTCAudioOutputStream> audioOutputStreams = new ArrayList<>();
+        presenter.getAllStreams(outputStreams, videoInputStreams, audioinputstream, audioOutputStreams);
+        updateVideoView(outputStreams, videoInputStreams, audioinputstream, audioOutputStreams);
+        refreshAudio(audioinputstream, audioOutputStreams);
     }
 
     @Override
@@ -1047,27 +1132,6 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
         }
     }
 
-    private void notifyMicContainerAdd(String userId, String userName) {
-        mLlMicContainer.post(new Runnable() {
-            @Override
-            public void run() {
-                String lastName = userName;
-                UserInfo targetUser = mLlMicContainer.getUserInfoIfExist(userId);
-                if (targetUser != null && !TextUtils.equals(targetUser.getName(), LiveRoomMicIconView.DEFAULT_NICK)) {
-                    lastName = targetUser.getName();
-                } else {
-                    if (TextUtils.isEmpty(lastName)) {
-                        //如果昵称为空,查询昵称
-                        if (presenter != null) {
-                            presenter.getUserInfoByUserId(userId);
-                        }
-                    }
-                }
-                mLlMicContainer.addMicUser(new UserInfo(userId, lastName, null));
-            }
-        });
-    }
-
     private void notifyMicContainerDel(String userId) {
         mLlMicContainer.post(new Runnable() {
             @Override
@@ -1083,7 +1147,6 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
     @Override
     public void onSeatMicSuccess() {
         updateMicIcon(LiveRoomMsgConstants.MIC_STATUS_CONNECT_SUCCESS);
-        notifyMicContainerAdd(mUserId, UserHelper.getUserName());
     }
 
     /**
@@ -1202,7 +1265,7 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
             return;
         }
         if (mLlMicContainer != null) {
-            mLlMicContainer.addMicUser(new UserInfo(friendInfoBean.friendId, friendInfoBean.friendNickname, null));
+            mLlMicContainer.updateTargetUserInfo(new UserInfo(friendInfoBean.friendId, friendInfoBean.friendNickname, null));
         }
     }
 
@@ -1274,8 +1337,45 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
         mInviteSeatMicTipDialog.setContent(defaultNick);
     }
 
+    private void refreshAudio(List<RCRTCAudioInputStream> audioInputStreams, List<RCRTCAudioOutputStream> audioOutputStreams) {
+        if (audioInputStreams == null || audioOutputStreams == null) {
+            //参数为空,先获取房间里的全部音频流信息
+            audioInputStreams = new ArrayList<>();
+            audioOutputStreams = new ArrayList<>();
+            presenter.getAudioStreams(audioInputStreams, audioOutputStreams);
+        }
+        ArrayList<String> onMicUserIds = new ArrayList<>();
+        //先处理本地用户
+        for (int i = 0; i < audioOutputStreams.size(); i++) {
+            RCRTCAudioOutputStream audioInputStream = audioOutputStreams.get(i);
+            if (audioInputStream.getMediaType() == RCRTCMediaType.AUDIO) {
+                //音频流判断显示上麦用户
+                String userId = audioInputStream.getUserId();
+                if (mRoomInfoBean != null) {
+                    if (!TextUtils.equals(mRoomInfoBean.speakerId, userId)) {
+                        onMicUserIds.add(userId);
+                    }
+                }
+            }
+        }
+
+        //远端用户的音频流信息
+        for (int i = 0; i < audioInputStreams.size(); i++) {
+            RCRTCAudioInputStream rcrtcAudioInputStream = audioInputStreams.get(i);
+            if (rcrtcAudioInputStream.getMediaType() == RCRTCMediaType.AUDIO) {
+                //音频流判断显示上麦用户
+                String userId = rcrtcAudioInputStream.getUserId();
+                if (mRoomInfoBean != null) {
+                    if (!TextUtils.equals(mRoomInfoBean.speakerId, userId)) {
+                        onMicUserIds.add(userId);
+                    }
+                }
+            }
+        }
+        mLlMicContainer.refreshUI(onMicUserIds);
+    }
 
-    public void updateVideoView(List<RCRTCVideoOutputStream> outputStreams, List<RCRTCVideoInputStream> inputStreams, List<RCRTCAudioInputStream> audioInputStreams) {
+    public void updateVideoView(List<RCRTCVideoOutputStream> outputStreams, List<RCRTCVideoInputStream> inputStreams, List<RCRTCAudioInputStream> audioInputStreams, List<RCRTCAudioOutputStream> audioOutputStreams) {
         mFlLiveView.post(new Runnable() {
             @Override
             public void run() {
@@ -1283,9 +1383,7 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
                 videoStreams.addAll(outputStreams);
                 videoStreams.addAll(inputStreams);
                 ArrayList<RCRTCVideoView> list = new ArrayList<>();
-                ArrayList<String> otherAudioUserIds = new ArrayList<>();
                 boolean isNormalCreateAudioStatus = true;
-
                 //视频流
                 for (int i = 0; i < videoStreams.size(); i++) {
                     RCRTCVideoStream rcrtcVideoStream = videoStreams.get(i);
@@ -1300,35 +1398,20 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
                     if (audioInputStream.getMediaType() == RCRTCMediaType.AUDIO) {
                         //音频流判断显示上麦用户
                         String userId = audioInputStream.getUserId();
-                        if (TextUtils.equals(mUserId, userId)) {
-                            continue;
-                        }
                         if (mRoomInfoBean != null) {
-                            if (!TextUtils.equals(mRoomInfoBean.speakerId, userId)) {
-                                otherAudioUserIds.add(userId);
-                            } else {
-                                //主播的音频流
+                            if (TextUtils.equals(mRoomInfoBean.speakerId, userId)) {
+                                //找出主播的音频流
                                 RCRTCResourceState resourceState = audioInputStream.getResourceState();
                                 isNormalCreateAudioStatus = resourceState == RCRTCResourceState.NORMAL;
                             }
                         }
                     }
                 }
-
-                if (otherAudioUserIds.size() != 0) {
-                    mLlMicContainer.delAllExcludeOwn();
-                    for (int i = 0; i < otherAudioUserIds.size(); i++) {
-                        String onMicUserId = otherAudioUserIds.get(i);
-                        notifyMicContainerAdd(onMicUserId, "");
-                    }
-                } else {
-                    mLlMicContainer.delAllExcludeOwn();
-                }
                 if (list.size() != 0) {
                     creatorIsCloseVideoStream = false;
                     mViewLiveStatus.setVisibility(View.GONE);
                     checkVideoViewManager();
-                    mVideoViewManager.update(list, 0, true);
+                    mVideoViewManager.update(list, isPcClientLive, true);
                 } else {
                     creatorIsCloseVideoStream = true;
                     if (isNormalCreateAudioStatus) {
@@ -1371,85 +1454,6 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
         return false;
     }
 
-    /**
-     * 当远端或本端视频流发生变化时全量更新ui
-     */
-    void updateVideoView(List<RCRTCInputStream> inputStreams) {
-        mFlLiveView.post(new Runnable() {
-            @Override
-            public void run() {
-                hideLoading();
-                ArrayList<RCRTCVideoView> list = new ArrayList<>();
-                ArrayList<String> otherAudioUserIds = new ArrayList<>();
-                boolean isNormalCreateAudioStatus = true;
-                if (null != inputStreams) {
-                    for (RCRTCInputStream i : inputStreams) {
-                        if (i.getMediaType() == RCRTCMediaType.VIDEO) {
-//                            if (mRoomInfoBean != null) {
-//                                if (TextUtils.equals(createRoomId, i.getUserId())) {
-//                                    Log.i("pq","已存在相同的流,无须重复渲染");
-//                                    return;
-//                                }
-//                            }
-                            RCRTCVideoInputStream j = (RCRTCVideoInputStream) i;
-                            RCRTCVideoView rongRTCVideoView = new RCRTCVideoView(LiveRoomActivity.this);
-                            j.setVideoView(rongRTCVideoView);
-                            createRoomId = j.getUserId();
-                            list.add(rongRTCVideoView);
-                        }
-
-                        if (i.getMediaType() == RCRTCMediaType.AUDIO) {
-                            //音频流判断显示上麦用户
-                            String userId = i.getUserId();
-                            if (TextUtils.equals(mUserId, userId)) {
-                                continue;
-                            }
-                            if (mRoomInfoBean != null) {
-                                if (!TextUtils.equals(mRoomInfoBean.speakerId, userId)) {
-                                    otherAudioUserIds.add(userId);
-                                } else {
-                                    //主播的音频流
-                                    RCRTCAudioInputStream rcrtcAudioInputStream = (RCRTCAudioInputStream) i;
-                                    RCRTCResourceState resourceState = rcrtcAudioInputStream.getResourceState();
-                                    isNormalCreateAudioStatus = resourceState == RCRTCResourceState.NORMAL;
-                                }
-                            }
-                        }
-                    }
-                }
-                if (otherAudioUserIds.size() != 0) {
-                    mLlMicContainer.delAllExcludeOwn();
-                    for (int i = 0; i < otherAudioUserIds.size(); i++) {
-                        String onMicUserId = otherAudioUserIds.get(i);
-                        notifyMicContainerAdd(onMicUserId, "");
-                    }
-                } else {
-                    mLlMicContainer.delAllExcludeOwn();
-                }
-                if (list.size() != 0) {
-                    creatorIsCloseVideoStream = false;
-                    mViewLiveStatus.setVisibility(View.GONE);
-                    RCRTCVideoView rcrtcVideoView = list.get(list.size() - 1);
-                    mFlLiveView.removeAllViews();
-//                    mFlLiveView.addView(rcrtcVideoView);
-                    rcrtcVideoView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
-                    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
-                    params.addRule(RelativeLayout.CENTER_IN_PARENT);
-                    // 将远端视图添加至布局
-                    mFlLiveView.addView(rcrtcVideoView, params);
-                } else {
-                    creatorIsCloseVideoStream = true;
-                    if (isNormalCreateAudioStatus) {
-                        showCloseVideoView();
-                    } else {
-                        //主播关闭了视频流,同时音频流的状态也不是normal状态时
-                        showRestView();
-                    }
-                }
-            }
-        });
-    }
-
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
@@ -1527,6 +1531,7 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
             if (mVideoViewManager != null && mVideoViewManager.getAllVideoViews() != null && mVideoViewManager.getAllVideoViews().size() > 0) {
                 Intent intent = new Intent(this, FloatingWindowService.class);
                 initServiceConnection();
+                intent.putExtra("isPc", isPcClientLive);
                 bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
             }
         }
@@ -1547,7 +1552,7 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
                             @Override
                             public void onServiceDestroy() {
                                 if (mVideoViewManager != null) {
-                                    mVideoViewManager.update(mVideoViewManager.getAllVideoViews(), 0, false);
+                                    mVideoViewManager.update(mVideoViewManager.getAllVideoViews(), isPcClientLive, false);
                                 }
                             }
 
@@ -1563,7 +1568,7 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
                 @Override
                 public void onServiceDisconnected(ComponentName name) {
                     if (mVideoViewManager != null) {
-                        mVideoViewManager.update(mVideoViewManager.getAllVideoViews(), 0, false);
+                        mVideoViewManager.update(mVideoViewManager.getAllVideoViews(), isPcClientLive, false);
                     }
                 }
             };
@@ -1657,6 +1662,76 @@ public class LiveRoomActivity extends BaseMVPActivity<ActivityLiveroomLayoutBind
     }
 
     @Override
+    public void receiveJoinMessage(RCChatJoinRoomMessage joinRoomMessage) {
+        //收到加入房间消息
+        if (isFinishing() || isDestroyed()) {
+            return;
+        }
+        if (joinRoomMessage == null) {
+            return;
+        }
+        if (isCanShowBarrage()) {
+            mTvJoinBarrage.setText(getString(R.string.enter_live_tip_str, LiveMemberHelper.getMessageName(joinRoomMessage)));
+            showBarrageViewAnim(mFlJoinBarrage);
+        }
+    }
+
+    /**
+     * 显示弹幕消息
+     */
+    private void showBarrageViewAnim(View targetView) {
+        if (mFlJoinBarrage.getVisibility() == View.VISIBLE || mFlSnapUpBarrage.getVisibility() == View.VISIBLE) {
+            return;
+        }
+        LiveRoomAnimatorHelper.getInstance().startBarrageViewAnimation(this, targetView);
+        hideBarrageView();
+    }
+
+    /**
+     * 隐藏弹幕消息
+     */
+    private void hideBarrageView() {
+        mHandler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                if (mFlJoinBarrage != null) {
+                    mFlJoinBarrage.setVisibility(View.GONE);
+                }
+                if (mFlSnapUpBarrage != null) {
+                    mFlSnapUpBarrage.setVisibility(View.GONE);
+                }
+            }
+        }, LiveConfig.LIVE_HIDE_BARRAGE_VIEW_TIME);
+    }
+
+    @Override
+    public void receiveSnapUpMessage(RCOnSnappingUpMessage onSnappingUpMessage) {
+        //收到抢购消息
+        if (isFinishing() || isDestroyed()) {
+            return;
+        }
+        if (onSnappingUpMessage == null) {
+            return;
+        }
+        if (isCanShowBarrage()) {
+            mTvSnapUpBarrage.setText(getString(R.string.live_snap_up_tip_str, LiveMemberHelper.getMessageName(onSnappingUpMessage)));
+            showBarrageViewAnim(mFlSnapUpBarrage);
+        }
+    }
+
+    /**
+     * 判断是否显示弹幕消息
+     *
+     * @return
+     */
+    private boolean isCanShowBarrage() {
+        if (isFullScreen()) {
+            return false;
+        }
+        return mFlJoinBarrage.getVisibility() != View.VISIBLE && mFlSnapUpBarrage.getVisibility() != View.VISIBLE;
+    }
+
+    @Override
     public void onDestroy() {
         if (presenter != null) {
             //通知离开房间

+ 33 - 14
student/src/main/java/com/cooleshow/student/ui/live/floatPop/FloatWindowHelper.java

@@ -50,31 +50,40 @@ public class FloatWindowHelper implements View.OnTouchListener {
     private int initX = 0;//初始位置坐标
     private int initY = 0;//初始位置坐标
     private OnEventListener mEventListener;
+    private boolean isLiveFromPc = true;
 
     public FloatWindowHelper(Context context, OnEventListener eventListener) {
         mContext = context;
         this.mEventListener = eventListener;
-        int deviceWidth = QMUIDisplayHelper.getScreenWidth(context);
-        int deviceHeight = QMUIDisplayHelper.getScreenHeight(context);
-        int orientation = context.getResources().getConfiguration().orientation;
+        initView();
+    }
+
+    private void setDefaultParams() {
+        int deviceWidth = QMUIDisplayHelper.getScreenWidth(mContext);
+        int deviceHeight = QMUIDisplayHelper.getScreenHeight(mContext);
+        int orientation = mContext.getResources().getConfiguration().orientation;
         if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
             maxWidth = deviceHeight / 2;
             maxDragX = deviceHeight - maxWidth;
-            maxHeight = UiUtils.getHeightAtRatio16_9(context, maxWidth);
-            int actionBarHeight = QMUIDisplayHelper.getActionBarHeight(context);
-            int statusBarHeight = QMUIStatusBarHelper.getStatusbarHeight(context);
+            maxHeight = UiUtils.getHeightAtRatio16_9(mContext, maxWidth);
+            int actionBarHeight = QMUIDisplayHelper.getActionBarHeight(mContext);
+            int statusBarHeight = QMUIStatusBarHelper.getStatusbarHeight(mContext);
             maxDragY = deviceWidth - actionBarHeight - statusBarHeight - maxHeight;
-            initX = maxWidth - 50;
-            initY = maxDragY - 300;
         } else {
-            maxWidth = deviceWidth / 2;
+            if (isLiveFromPc) {
+                //PC端是16:9的比例尺寸
+                maxWidth = deviceWidth / 2;
+                maxHeight = UiUtils.getHeightAtRatio16_9(mContext, maxWidth);
+            } else {
+                maxWidth = deviceWidth / 4;
+                float ratio = (float) deviceWidth / (float) deviceHeight;
+                maxHeight = (int) (maxWidth / ratio);
+            }
             maxDragX = deviceWidth - maxWidth;
-            maxHeight = UiUtils.getHeightAtRatio16_9(context, maxWidth);
             maxDragY = deviceHeight - maxHeight;
-            initX = maxWidth - 50;
-            initY = maxDragY - 300;
         }
-        initView();
+        initX = deviceWidth - maxWidth - 50;
+        initY = maxDragY - 300;
     }
 
     /**
@@ -96,6 +105,16 @@ public class FloatWindowHelper implements View.OnTouchListener {
         return false;
     }
 
+    public boolean isLiveFromPc() {
+        return isLiveFromPc;
+    }
+
+    public void setLiveFromPc(boolean liveFromPc) {
+        isLiveFromPc = liveFromPc;
+        //设置默认参数
+        setDefaultParams();
+    }
+
     /**
      * 判断是否有悬浮窗权限
      *
@@ -259,7 +278,7 @@ public class FloatWindowHelper implements View.OnTouchListener {
                 }
                 RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                 layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
-                videoView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
+                videoView.setScalingType(isLiveFromPc ? RendererCommon.ScalingType.SCALE_ASPECT_FIT : RendererCommon.ScalingType.SCALE_ASPECT_FILL);
                 mLiveContainer.addView(videoView, layoutParams);
             }
         }

+ 5 - 3
student/src/main/java/com/cooleshow/student/ui/live/floatPop/FloatingWindowService.java

@@ -34,13 +34,15 @@ public class FloatingWindowService extends Service implements FloatWindowHelper.
     @Nullable
     @Override
     public IBinder onBind(Intent intent) {
+        if (mBinder == null) {
+            mBinder = new MyBinder();
+        }
+        boolean isPc = intent.getBooleanExtra("isPc", true);
         if (mHelper != null && !isShowing) {
+            mHelper.setLiveFromPc(isPc);
             mHelper.showFloatingWindowView(this);
             isShowing = true;
         }
-        if (mBinder == null) {
-            mBinder = new MyBinder();
-        }
         return mBinder;
     }
 

+ 28 - 0
student/src/main/java/com/cooleshow/student/widgets/helper/LiveRoomAnimatorHelper.java

@@ -87,6 +87,34 @@ public class LiveRoomAnimatorHelper {
         });
     }
 
+
+
+    public void startBarrageViewAnimation(Context context, View targetView) {
+        targetView.setVisibility(View.VISIBLE);
+        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(targetView, "translationX", -300, 0f);
+        ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(targetView, "alpha", 0.2f, 1f);
+        AnimatorSet animatorSet = new AnimatorSet();
+        LinearInterpolator linearInterpolator = new LinearInterpolator();
+        animatorSet.setInterpolator(linearInterpolator);
+        animatorSet.play(objectAnimator).with(objectAnimator2);
+        animatorSet.setDuration(1000);
+        animatorSet.start();
+        addLikeAnimaViews.add(targetView);
+        addLikeAnimas.add(animatorSet);
+        animatorSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                if (addLikeAnimaViews != null) {
+                    addLikeAnimaViews.remove(targetView);
+                }
+                if (addLikeAnimas != null) {
+                    addLikeAnimas.remove(animatorSet);
+                }
+            }
+        });
+    }
+
     public void releaseAnimator(){
         if (addLikeAnimaViews != null) {
             for (int i = 0; i < addLikeAnimaViews.size(); i++) {

+ 4 - 2
student/src/main/java/com/cooleshow/student/widgets/helper/VideoViewManager.java

@@ -19,6 +19,8 @@ import cn.rongcloud.rtc.api.stream.RCRTCVideoView;
 import cn.rongcloud.rtc.api.stream.view.RCRTCRendererEventsListener;
 import cn.rongcloud.rtc.core.RendererCommon;
 
+import static cn.rongcloud.rtc.core.RendererCommon.ScalingType.SCALE_ASPECT_FILL;
+
 public class VideoViewManager {
 
     private static final String TAG = "VideoViewManager";
@@ -66,7 +68,7 @@ public class VideoViewManager {
      *
      * @param list
      */
-    public void update(ArrayList<RCRTCVideoView> list, int mainScreenPosition, boolean isShowLoading) {
+    public void update(ArrayList<RCRTCVideoView> list, boolean isPc, boolean isShowLoading) {
         Log.i("pq", "update" + list.size());
         Log.i("pq", "mainScreenPosition" + mainScreenPosition);
         arrayListVideoView = list;
@@ -111,7 +113,7 @@ public class VideoViewManager {
 
                 }
             });
-            arrayListVideoView.get(i).setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
+            arrayListVideoView.get(i).setScalingType(isPc ? RendererCommon.ScalingType.SCALE_ASPECT_FIT : SCALE_ASPECT_FILL);
             flSurfaceContainer.addView(arrayListVideoView.get(i), layoutParams);
             index++;
         }

BIN
student/src/main/res/drawable-xhdpi/icon_live_barrage_buy_tag.png


BIN
student/src/main/res/drawable-xxhdpi/icon_live_barrage_buy_tag.png


+ 7 - 0
student/src/main/res/drawable/shape_live_barrage_for_join_msg.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+        android:endColor="#60FFF7"
+        android:startColor="#00BF85" />
+    <corners android:radius="12dp" />
+</shape>

+ 7 - 0
student/src/main/res/drawable/shape_live_barrage_for_snap_up_msg.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+        android:endColor="#FF6500"
+        android:startColor="#FFB300" />
+    <corners android:radius="12dp" />
+</shape>

+ 62 - 0
student/src/main/res/layout/activity_liveroom_layout.xml

@@ -271,6 +271,16 @@
         app:layout_constraintRight_toLeftOf="@+id/icon_add_like"
         app:layout_constraintTop_toTopOf="@+id/icon_add_like" />
 
+    <View
+        android:visibility="invisible"
+        android:id="@+id/view_center"
+        android:layout_width="1px"
+        android:layout_height="1px"
+        android:layout_marginTop="50dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
     <FrameLayout
         android:id="@+id/fl_recycler_container"
         android:layout_width="match_parent"
@@ -292,6 +302,58 @@
             android:scrollbars="none" />
     </FrameLayout>
 
+    <FrameLayout
+        android:id="@+id/fl_join_barrage"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="11dp"
+        android:layout_marginBottom="10dp"
+        android:background="@drawable/shape_live_barrage_for_join_msg"
+        android:paddingStart="10dp"
+        android:paddingTop="3dp"
+        android:paddingEnd="10dp"
+        android:paddingBottom="3dp"
+        android:visibility="gone"
+        app:layout_constraintBottom_toTopOf="@+id/fl_recycler_container"
+        app:layout_constraintLeft_toLeftOf="parent">
+
+        <TextView
+            android:id="@+id/tv_join_barrage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="@color/white"
+            android:textSize="@dimen/sp_13"
+            tools:text="新雷 进入直播间" />
+
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/fl_snap_up_barrage"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="11dp"
+        android:background="@drawable/shape_live_barrage_for_snap_up_msg"
+        android:paddingStart="10dp"
+        android:layout_marginBottom="10dp"
+        android:paddingTop="3dp"
+        android:paddingEnd="10dp"
+        android:paddingBottom="3dp"
+        android:visibility="gone"
+        app:layout_constraintBottom_toTopOf="@+id/fl_recycler_container"
+        app:layout_constraintLeft_toLeftOf="parent">
+
+        <TextView
+            android:id="@+id/tv_snap_up_barrage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableLeft="@drawable/icon_live_barrage_buy_tag"
+            android:drawablePadding="4dp"
+            android:textColor="@color/white"
+            android:textSize="@dimen/sp_13"
+            tools:text="张予锡 正在去购买" />
+
+    </FrameLayout>
+
     <androidx.constraintlayout.widget.Group
         android:id="@+id/group_views"
         android:layout_width="wrap_content"

+ 2 - 1
student/src/main/res/values/strings.xml

@@ -35,6 +35,7 @@
     <string name="cancel_seat_on_connected">连麦中,确认取消连麦吗?</string>
     <string name="exit_str">退出</string>
     <string name="enable_mic_mode_tip">禁止连麦模式</string>
-
+    <string name="enter_live_tip_str">%1$s 进入直播间</string>
+    <string name="live_snap_up_tip_str">%1$s 正在抢购</string>
 
 </resources>