// // TUICallingView.m // TUICalling // // Created by noah on 2021/8/23. // #import "TUICallingView.h" #import "TUIAudioUserContainerView.h" #import "TUIVideoUserContainerView.h" #import static CGFloat const kSmallVideoViewWidth = 100.0f; #define kCallingViewMicroRenderFrame CGRectMake(self.frame.size.width - kSmallVideoViewWidth - 18, StatusBar_Height + 20, kSmallVideoViewWidth, kSmallVideoViewWidth / 9.0 * 16.0) @interface TUICallingView() /// 记录Calling当前的状态 @property (nonatomic, assign) TUICallingState curCallingState; /// 记录远程通话人信息 @property (nonatomic, strong) CallUserModel *remoteSponsor; /// 通话时间按钮 @property (nonatomic, strong) UILabel *callingTime; /// 关闭麦克风按钮 @property (nonatomic, strong) TUICallingControlButton *muteBtn; /// 挂断按钮 @property (nonatomic, strong) TUICallingControlButton *hangupBtn; /// 免提按钮 @property (nonatomic, strong) TUICallingControlButton *handsfreeBtn; /// 接听控制视图 @property (nonatomic, strong) TUIInvitedContainerView *invitedContainerView; /// 远程音频用户信息视图 @property (nonatomic, strong) TUIAudioUserContainerView *audioUserContainerView; /** 视频相关处理 */ /// 远程视频用户信息视图 @property (nonatomic, strong) TUIVideoUserContainerView *videoUserContainerView; /// 视频通话 - 视频的渲染视图 - 本地视图 @property (nonatomic, strong) TUICallingVideoRenderView *localPreView; /// 视频通话 - 视频的渲染视图 - 远程视图 @property (nonatomic, strong) TUICallingVideoRenderView *remotePreView; /// 关闭摄像头 @property (nonatomic, strong) TUICallingControlButton *closeCameraBtn; /// 视频通话 - 用于切换摄像头的按钮 @property (nonatomic, strong) UIButton *switchCameraBtn; /// 视频通话 - 用于切换到语音按钮 @property (nonatomic, strong) TUICallingControlButton *switchToAudioBtn; /// 记录是本地预览大图 @property (nonatomic, assign) BOOL isLocalPreViewLarge; /// 记录是否为前置相机 @property (nonatomic, assign) BOOL isFrontCamera; /// 标记是否需要清除页面 @property (nonatomic, assign) BOOL isClearFlag; /// 麦克风 / 切换音频和听筒状态记录 @property (nonatomic, assign) BOOL isMicMute; @property (nonatomic, assign) BOOL isHandsFreeOn; @property (nonatomic, assign) BOOL isSwitchedToAudio; @property (nonatomic, assign) BOOL isCloseCamera; @end @implementation TUICallingView - (instancetype)initWithIsVideo:(BOOL)isVideo isCallee:(BOOL)isCallee { self = [super initWithFrame:[UIScreen mainScreen].bounds]; if (self) { self.isVideo = isVideo; self.isCallee = isCallee; self.isClearFlag = NO; if (isVideo) { self.isLocalPreViewLarge = YES; self.isFrontCamera = YES; self.isHandsFreeOn = YES; } else { self.isHandsFreeOn = NO; } [self setupUI]; [[TRTCCalling shareInstance] setHandsFree:self.isHandsFreeOn]; } return self; } - (void)setupUI { self.backgroundColor = [UIColor t_colorWithHexString:@"#F4F5F9"]; if (self.isVideo) { self.backgroundColor = [UIColor t_colorWithHexString:@"#242424"]; // 设置背景视频试图 [[TRTCCalling shareInstance] closeCamara]; [[TRTCCalling shareInstance] openCamera:self.isFrontCamera view:self.localPreView]; } _curCallingState = self.isCallee ? TUICallingStateOnInvitee : TUICallingStateDailing; } /// 音频通话,主叫方UI初始化 - (void)initUIForAudioCaller { [self addSubview:self.audioUserContainerView]; [self addSubview:self.callingTime]; [self addSubview:self.muteBtn]; [self addSubview:self.hangupBtn]; [self addSubview:self.handsfreeBtn]; // 视图约束 [self.audioUserContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self).offset(StatusBar_Height + 74); make.left.equalTo(self).offset(20); make.right.equalTo(self).offset(-20); }]; [self.callingTime mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.equalTo(self); make.bottom.equalTo(self.hangupBtn.mas_top).offset(-10); make.height.equalTo(@(30)); }]; [self.muteBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.hangupBtn.mas_left); make.bottom.equalTo(self.hangupBtn); make.size.equalTo(@(kControlBtnSize)); }]; [self.hangupBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self); make.bottom.equalTo(self.mas_top).offset(self.frame.size.height - Bottom_SafeHeight - 20); make.size.equalTo(@(kControlBtnSize)); }]; [self.handsfreeBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.hangupBtn.mas_right); make.bottom.equalTo(self.hangupBtn); make.size.equalTo(@(kControlBtnSize)); }]; [self bringFloatingWindowWhiteButtonToFront:NO]; self.callingTime.textColor = [UIColor t_colorWithHexString:@"#333333"]; [self.muteBtn configTitleColor:[UIColor t_colorWithHexString:@"#666666"]]; [self.hangupBtn configTitleColor:[UIColor t_colorWithHexString:@"#666666"]]; [self.handsfreeBtn configTitleColor:[UIColor t_colorWithHexString:@"#666666"]]; } /// 音频通话,被呼叫方UI初始化 - (void)initUIForAudioCallee { [self addSubview:self.audioUserContainerView]; [self addSubview:self.invitedContainerView]; // 视图约束 [self.audioUserContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self).offset(StatusBar_Height + 74); make.left.equalTo(self).offset(20); make.right.equalTo(self).offset(-20); }]; [self.invitedContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.centerX.equalTo(self).offset(60); make.right.centerX.equalTo(self).offset(-60); make.height.equalTo(@(94)); make.bottom.equalTo(self).offset(-Bottom_SafeHeight - 20); }]; [self bringFloatingWindowWhiteButtonToFront:NO]; [self.invitedContainerView configTitleColor:[UIColor t_colorWithHexString:@"#666666"]]; } /// 视频通话,主叫方UI初始化 - (void)initUIForVideoCaller { [self addSubview:self.remotePreView]; [self addSubview:self.localPreView]; [self addSubview:self.videoUserContainerView]; [self addSubview:self.switchCameraBtn]; [self addSubview:self.switchToAudioBtn]; [self addSubview:self.hangupBtn]; // 视图约束 [self.videoUserContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self).offset(StatusBar_Height + 20); make.left.equalTo(self).offset(20); make.right.equalTo(self).offset(-20); }]; [self.switchToAudioBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self); make.bottom.equalTo(self.hangupBtn.mas_top).offset(-10); make.size.equalTo(@(CGSizeMake(200, 46))); }]; [self.hangupBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self); make.bottom.equalTo(self.mas_top).offset(self.frame.size.height - Bottom_SafeHeight - 20); make.size.equalTo(@(kControlBtnSize)); }]; [self.switchCameraBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.hangupBtn); make.left.equalTo(self.hangupBtn.mas_right).offset(20); make.size.equalTo(@(CGSizeMake(36, 36))); }]; [self bringFloatingWindowWhiteButtonToFront:YES]; self.localPreView.hidden = NO; [self.hangupBtn configTitleColor:[UIColor t_colorWithHexString:@"#FFFFFF"]]; } /// 视频通话, 功能控制试图(时间,摄像头,麦克风,免提) - (void)initUIForVideoControl { [self addSubview:self.callingTime]; [self addSubview:self.muteBtn]; [self addSubview:self.handsfreeBtn]; [self addSubview:self.closeCameraBtn]; // 视图约束 [self.callingTime mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.equalTo(self); make.bottom.equalTo(self.switchToAudioBtn.mas_top).offset(-10); make.height.equalTo(@(30)); }]; [self.switchToAudioBtn mas_remakeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self); make.bottom.equalTo(self.handsfreeBtn.mas_top).offset(-10); make.size.equalTo(@(CGSizeMake(200, 46))); }]; [self.muteBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.handsfreeBtn.mas_left); make.centerY.equalTo(self.handsfreeBtn); make.size.equalTo(@(kControlBtnSize)); }]; [self.handsfreeBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self); make.bottom.equalTo(self.hangupBtn.mas_top).offset(-10); make.size.equalTo(@(kControlBtnSize)); }]; [self.closeCameraBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.handsfreeBtn.mas_right); make.centerY.equalTo(self.handsfreeBtn); make.size.equalTo(@(kControlBtnSize)); }]; [self bringFloatingWindowWhiteButtonToFront:YES]; [self.handsfreeBtn configBackgroundImage:[TUICommonUtil getBundleImageWithName:@"ic_handsfree_on"]]; self.callingTime.textColor = [UIColor t_colorWithHexString:@"#FFFFFF"]; [self.muteBtn configTitleColor:[UIColor t_colorWithHexString:@"#FFFFFF"]]; [self.handsfreeBtn configTitleColor:[UIColor t_colorWithHexString:@"#FFFFFF"]]; [self.hangupBtn configTitleColor:[UIColor t_colorWithHexString:@"#FFFFFF"]]; } /// 视频通话,被呼叫方UI初始化 - (void)initUIForVideoCallee { [self addSubview:self.localPreView]; [self addSubview:self.videoUserContainerView]; [self addSubview:self.invitedContainerView]; [self addSubview:self.switchToAudioBtn]; // 视图约束 [self.videoUserContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self).offset(StatusBar_Height + 32); make.left.equalTo(self).offset(20); make.right.equalTo(self).offset(-20); }]; [self.invitedContainerView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.centerX.equalTo(self).offset(60); make.right.centerX.equalTo(self).offset(-60); make.height.equalTo(@(94)); make.bottom.equalTo(self).offset(-Bottom_SafeHeight - 20); }]; [self.switchToAudioBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self); make.bottom.equalTo(self.invitedContainerView.mas_top).offset(-10); make.size.equalTo(@(CGSizeMake(200, 46))); }]; [self bringFloatingWindowWhiteButtonToFront:YES]; self.localPreView.hidden = NO; [self.invitedContainerView configTitleColor:[UIColor t_colorWithHexString:@"#FFFFFF"]]; } #pragma mark - Puilic - (void)switchToAudio { self.isVideo = NO; self.isClearFlag = YES; self.backgroundColor = [UIColor t_colorWithHexString:@"#F4F5F9"]; [[TRTCCalling shareInstance] closeCamara]; if (self.isHandsFreeOn) { [self hangsfreeTouchEvent:nil]; } [self setCurCallingState:self.curCallingState]; [[TUICallingFloatingWindowManager shareInstance] switchToAudioMicroWindowWith:self.curCallingState]; } - (void)setCurCallingState:(TUICallingState)curCallingState { _curCallingState = curCallingState; if (self.isClearFlag) { self.isClearFlag = NO; [self clearAllSubViews]; } switch (curCallingState) { case TUICallingStateOnInvitee: { self.callingTime.hidden = YES; if (self.isVideo) { [self initUIForVideoCallee]; [self.videoUserContainerView configUserInfoViewWith:self.remoteSponsor showWaitingText:TUICallingLocalize(@"Demo.TRTC.calling.invitetovideocall")]; } else { [self initUIForAudioCallee]; [self.audioUserContainerView configUserInfoViewWith:self.remoteSponsor showWaitingText:TUICallingLocalize(@"Demo.TRTC.calling.invitetoaudiocall")]; } } break; case TUICallingStateDailing: { self.callingTime.hidden = YES; if (self.isVideo) { [self initUIForVideoCaller]; [self.videoUserContainerView configUserInfoViewWith:self.remoteSponsor showWaitingText:TUICallingLocalize(@"Demo.TRTC.Calling.waitaccept")]; } else { [self initUIForAudioCaller]; [self.audioUserContainerView configUserInfoViewWith:self.remoteSponsor showWaitingText:TUICallingLocalize(@"Demo.TRTC.Calling.waitaccept")]; } } break; case TUICallingStateCalling: { self.callingTime.hidden = NO; if (self.isVideo) { [self initUIForVideoCaller]; [self initUIForVideoControl]; self.videoUserContainerView.hidden = YES; // 主叫接通,互换本地/远程视频页面位置 [self setRemotePreViewWith:self.remoteSponsor]; [self switchTo2UserPreView]; if (self.isCloseCamera) { self.localPreView.hidden = YES; } [self.videoUserContainerView configUserInfoViewWith:self.remoteSponsor showWaitingText:@""]; } else { [self initUIForAudioCaller]; [self.audioUserContainerView configUserInfoViewWith:self.remoteSponsor showWaitingText:@""]; } } break; default: break; } } - (void)clearAllSubViews { if (_localPreView != nil && self.localPreView.superview != nil) { self.localPreView.hidden = YES; [self.localPreView removeFromSuperview]; } if (_remotePreView != nil && self.remotePreView.superview != nil) { self.remotePreView.hidden = YES; [self.remotePreView removeFromSuperview]; } if (_videoUserContainerView != nil && self.videoUserContainerView.superview != nil) { [self.videoUserContainerView removeFromSuperview]; } if (_invitedContainerView != nil && self.invitedContainerView.superview != nil) { [self.invitedContainerView removeFromSuperview]; } if (_callingTime != nil && self.callingTime.superview != nil) { [self.callingTime removeFromSuperview]; } if (_switchToAudioBtn != nil && self.switchToAudioBtn.superview != nil) { [self.switchToAudioBtn removeFromSuperview]; } if (_muteBtn != nil && self.muteBtn.superview != nil) { [self.muteBtn removeFromSuperview]; } if (_hangupBtn != nil && self.hangupBtn.superview != nil) { [self.hangupBtn removeFromSuperview]; } if (_handsfreeBtn != nil && self.handsfreeBtn.superview != nil) { [self.handsfreeBtn removeFromSuperview]; } if (_closeCameraBtn != nil && self.closeCameraBtn.superview != nil) { [self.closeCameraBtn removeFromSuperview]; } if (_switchCameraBtn != nil && self.switchCameraBtn.superview != nil) { [self.switchCameraBtn removeFromSuperview]; } if (_audioUserContainerView != nil && self.audioUserContainerView.superview != nil) { [self.audioUserContainerView removeFromSuperview]; } } - (void)configViewWithUserList:(NSArray *)userList sponsor:(CallUserModel *)sponsor { if (sponsor) { self.isClearFlag = YES; self.remoteSponsor = sponsor; self.curCallingState = TUICallingStateOnInvitee; } else { self.remoteSponsor = [userList firstObject]; self.curCallingState = TUICallingStateDailing; } } - (void)configAudioCallView { NSString *showText = @""; if (!self.isCallee && self.curCallingState != TUICallingStateCalling) { // 等待对方接听 showText = TUICallingLocalize(@"Demo.TRTC.Calling.waitaccept"); } if (self.curCallingState == TUICallingStateCalling) { self.callingTime.hidden = NO; } else { self.callingTime.hidden = YES; } // 刷新远程用户信息视图 [self.audioUserContainerView configUserInfoViewWith:self.remoteSponsor showWaitingText:showText]; } - (void)setRemotePreViewWith:(CallUserModel *)user{ if (![user.userId isEqualToString:[[V2TIMManager sharedInstance] getLoginUser]]) { self.remotePreView.hidden = NO; [self.remotePreView configViewWithUserModel:user]; [[TRTCCalling shareInstance] startRemoteView:user.userId view:self.remotePreView]; } } - (void)enterUser:(CallUserModel *)user { self.curCallingState = TUICallingStateCalling; [self updateUser:user animated:YES]; } - (void)updateUser:(CallUserModel *)user animated:(BOOL)animated { self.remotePreView.hidden = !user.isVideoAvaliable; if ([self.remoteSponsor.userId isEqualToString:user.userId]) { self.remoteSponsor = user; } } - (void)updateUserVolume:(CallUserModel *)user { if ([self.remoteSponsor.userId isEqualToString:user.userId]) { [self.remotePreView configViewWithUserModel:user]; } } - (CallUserModel *)getUserById:(NSString *)userId { if ([self.remoteSponsor.userId isEqualToString:userId]) { return self.remoteSponsor; } return nil; } - (void)acceptCalling { self.isClearFlag = YES; self.curCallingState = TUICallingStateCalling; } - (void)refuseCalling { self.localPreView = nil; self.remotePreView = nil; } - (void)setCallingTimeStr:(NSString *)timeStr { if (timeStr && timeStr.length > 0) { self.callingTime.text = timeStr; if (self.isVideo) return; [[TUICallingFloatingWindowManager shareInstance] updateMicroWindowText:timeStr callingState:self.curCallingState]; } } #pragma mark - TUICallingFloatingWindowDelegate - (void)floatingWindowDidClickView { if (!self.isVideo) return; if (self.isLocalPreViewLarge) { self.remotePreView.userInteractionEnabled = YES; self.remotePreView.frame = kCallingViewMicroRenderFrame; self.localPreView.frame = [UIScreen mainScreen].bounds; [self.localPreView removeFromSuperview]; [self.remotePreView removeFromSuperview]; [self insertSubview:self.localPreView atIndex:0]; [self insertSubview:self.remotePreView aboveSubview:self.localPreView]; } else { self.localPreView.userInteractionEnabled = YES; self.remotePreView.frame = [UIScreen mainScreen].bounds; self.localPreView.frame = kCallingViewMicroRenderFrame ; [self.remotePreView removeFromSuperview]; [self.localPreView removeFromSuperview]; [self insertSubview:self.remotePreView atIndex:0]; [self insertSubview:self.localPreView aboveSubview:self.remotePreView]; } } #pragma mark - TUICallingVideoRenderViewDelegete - (void)tapGestureAction:(UITapGestureRecognizer *)tapGesture { if (tapGesture.view.frame.size.width == kSmallVideoViewWidth) { [self switchPreView]; } } - (void)panGestureAction:(UIPanGestureRecognizer *)panGesture { if (!(panGesture.view && panGesture.view.superview && [panGesture.view.superview isKindOfClass:[TUICallingVideoRenderView class]])) { return; } UIView *smallView = panGesture.view.superview; if (smallView.frame.size.width != kSmallVideoViewWidth) { return; } if (panGesture.state == UIGestureRecognizerStateChanged) { CGPoint translation = [panGesture translationInView:self]; CGFloat newCenterX = translation.x + (smallView.center.x); CGFloat newCenterY = translation.y + (smallView.center.y); if ((newCenterX < (smallView.bounds.size.width / 2.0)) || (newCenterX > self.bounds.size.width - (smallView.bounds.size.width) / 2.0)) { return; } if ((newCenterY < (smallView.bounds.size.height) / 2.0) || (newCenterY > self.bounds.size.height - (smallView.bounds.size.height) / 2.0)) { return; } [UIView animateWithDuration:0.1 animations:^{ smallView.center = CGPointMake(newCenterX, newCenterY); }]; [panGesture setTranslation:CGPointZero inView:self]; } } #pragma mark - Event Action - (void)muteTouchEvent:(UIButton *)sender { self.isMicMute = !self.isMicMute; [[TRTCCalling shareInstance] setMicMute:self.isMicMute]; [self.muteBtn configBackgroundImage:[TUICommonUtil getBundleImageWithName:self.isMicMute ? @"ic_mute_on" : @"ic_mute"]]; } - (void)hangupTouchEvent:(UIButton *)sender { if (self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(hangupCalling)]) { [self.actionDelegate hangupCalling]; } } - (void)hangsfreeTouchEvent:(UIButton *)sender { self.isHandsFreeOn = !self.isHandsFreeOn; [[TRTCCalling shareInstance] setHandsFree:self.isHandsFreeOn]; [self.handsfreeBtn configBackgroundImage:[TUICommonUtil getBundleImageWithName:self.isHandsFreeOn ? @"ic_handsfree_on" : @"ic_handsfree"]]; } - (void)switchCameraTouchEvent:(UIButton *)sender { self.isFrontCamera = !self.isFrontCamera; [[TRTCCalling shareInstance] switchCamera:self.isFrontCamera]; } - (void)closeCameraTouchEvent:(UIButton *)sender { self.isCloseCamera = !self.isCloseCamera; [self.closeCameraBtn setUserInteractionEnabled:NO]; [self.closeCameraBtn configBackgroundImage:[TUICommonUtil getBundleImageWithName:self.isCloseCamera ? @"camera_off" : @"camera_on"]]; if (self.isCloseCamera) { [[TRTCCalling shareInstance] closeCamara]; self.localPreView.hidden = YES; } else { [[TRTCCalling shareInstance] openCamera:self.isFrontCamera view:self.localPreView]; self.localPreView.hidden = NO; } dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.closeCameraBtn setUserInteractionEnabled:YES]; }); self.localPreView.hidden = self.isCloseCamera; } - (void)switchToAudioTouchEvent:(UIButton *)sender { [[TRTCCalling shareInstance] switchToAudio]; if (self.curCallingState == TUICallingStateOnInvitee) { if (self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(acceptCalling)]) { [self.actionDelegate acceptCalling]; } } } - (void)floatingWindowTouchEvent:(UIButton *)sender { TUICallingVideoRenderView *renderView = nil; if (self.isVideo) { if ((self.curCallingState == TUICallingStateCalling) && self.remotePreView) { renderView = self.remotePreView; } else { renderView = self.localPreView; } } __weak typeof(self) weakSelf = self; [self showMicroFloatingWindowWithVideoRenderView:renderView callingState:self.curCallingState completion:^(BOOL finished) { weakSelf.localPreView.userInteractionEnabled = NO; weakSelf.remotePreView.userInteractionEnabled = NO; }]; } #pragma mark - Private - (void)switchTo2UserPreView { if (!self.remotePreView || self.isLocalPreViewLarge == NO) return; [self.localPreView setUserInteractionEnabled:YES]; [[self.localPreView.subviews firstObject] setUserInteractionEnabled: NO]; [UIView animateWithDuration:0.3 animations:^{ self.localPreView.frame = kCallingViewMicroRenderFrame; self.remotePreView.frame = self.frame; } completion:^(BOOL finished) { [self.remotePreView removeFromSuperview]; [self insertSubview:self.remotePreView belowSubview:self.localPreView]; self.isLocalPreViewLarge = NO; [[TUICallingFloatingWindowManager shareInstance] updateMicroWindowRenderView:self.remotePreView]; }]; } - (void)switchPreView { if (!self.remotePreView) return; TUICallingVideoRenderView *remoteView = self.remotePreView; if (_isLocalPreViewLarge) { // 本地视图为大图 remoteView.hidden = NO; [UIView animateWithDuration:0.3 animations:^{ remoteView.frame = self.frame; self.localPreView.frame = kCallingViewMicroRenderFrame; } completion:^(BOOL finished) { [remoteView removeFromSuperview]; [self insertSubview:remoteView belowSubview:self.localPreView]; if (self.localPreView.isHidden || remoteView.isHidden) { [self.localPreView setUserInteractionEnabled:NO]; [remoteView setUserInteractionEnabled:NO]; } else { [self.localPreView setUserInteractionEnabled:YES]; } }]; } else { // 本地视图为小图的处理方式 self.localPreView.hidden = NO; [UIView animateWithDuration:0.3 animations:^{ self.localPreView.frame = self.frame; remoteView.frame = kCallingViewMicroRenderFrame; } completion:^(BOOL finished) { [self.localPreView removeFromSuperview]; [self insertSubview:self.localPreView belowSubview:remoteView]; if (self.localPreView.isHidden || remoteView.isHidden) { [self.localPreView setUserInteractionEnabled:NO]; [remoteView setUserInteractionEnabled:NO]; } else { [remoteView setUserInteractionEnabled:YES]; } }]; } self.isLocalPreViewLarge = !_isLocalPreViewLarge; } - (void)bringFloatingWindowWhiteButtonToFront:(BOOL)isWhiteIcon { [self bringSubviewToFront:self.floatingWindowBtn]; [self.floatingWindowBtn setBackgroundImage:[TUICommonUtil getBundleImageWithName:isWhiteIcon? @"ic_min_window_white": @"ic_min_window_dark"] forState:UIControlStateNormal]; } #pragma mark - Lazy - (TUIAudioUserContainerView *)audioUserContainerView { if (!_audioUserContainerView) { _audioUserContainerView = [[TUIAudioUserContainerView alloc] initWithFrame:CGRectZero]; } return _audioUserContainerView; } - (UILabel *)callingTime { if (!_callingTime) { _callingTime = [[UILabel alloc] initWithFrame:CGRectZero]; _callingTime.font = [UIFont boldSystemFontOfSize:14.0f]; [_callingTime setTextColor:[UIColor t_colorWithHexString:@"#333333"]]; [_callingTime setBackgroundColor:[UIColor clearColor]]; [_callingTime setText:@"00:00"]; [_callingTime setTextAlignment:NSTextAlignmentCenter]; } return _callingTime; } - (TUICallingControlButton *)muteBtn { if (!_muteBtn) { __weak typeof(self) weakSelf = self; _muteBtn = [TUICallingControlButton createViewWithFrame:CGRectZero titleText:TUICallingLocalize(@"Demo.TRTC.Calling.mic") buttonAction:^(UIButton * _Nonnull sender) { [weakSelf muteTouchEvent:sender]; } imageSize:kBtnSmallSize]; [_muteBtn configBackgroundImage:[TUICommonUtil getBundleImageWithName:@"ic_mute"]]; } return _muteBtn; } - (TUICallingControlButton *)hangupBtn { if (!_hangupBtn) { __weak typeof(self) weakSelf = self; _hangupBtn = [TUICallingControlButton createViewWithFrame:CGRectZero titleText:TUICallingLocalize(@"Demo.TRTC.Calling.hangup") buttonAction:^(UIButton * _Nonnull sender) { [weakSelf hangupTouchEvent:sender]; } imageSize:kBtnLargeSize]; [_hangupBtn configBackgroundImage:[TUICommonUtil getBundleImageWithName:@"ic_hangup"]]; } return _hangupBtn; } - (TUICallingControlButton *)handsfreeBtn { if (!_handsfreeBtn) { __weak typeof(self) weakSelf = self; _handsfreeBtn = [TUICallingControlButton createViewWithFrame:CGRectZero titleText:TUICallingLocalize(@"Demo.TRTC.Calling.speaker") buttonAction:^(UIButton * _Nonnull sender) { [weakSelf hangsfreeTouchEvent:sender]; } imageSize:kBtnSmallSize]; [_handsfreeBtn configBackgroundImage:[TUICommonUtil getBundleImageWithName:@"ic_handsfree"]]; } return _handsfreeBtn; } - (TUIInvitedContainerView *)invitedContainerView { if (!_invitedContainerView) { _invitedContainerView = [[TUIInvitedContainerView alloc] initWithFrame:CGRectZero]; _invitedContainerView.delegate = self.actionDelegate; } return _invitedContainerView; } #pragma mark - Lazy -- 视频通话相关 - (TUICallingVideoRenderView *)localPreView { if (!_localPreView) { _localPreView = [[TUICallingVideoRenderView alloc] initWithFrame:self.bounds]; _localPreView.backgroundColor = [UIColor t_colorWithHexString:@"#242424"]; _localPreView.frame = self.bounds; _localPreView.delegate = self; [_localPreView setUserInteractionEnabled:NO]; } return _localPreView; } - (TUICallingVideoRenderView *)remotePreView { if (!_remotePreView) { _remotePreView = [[TUICallingVideoRenderView alloc] initWithFrame:CGRectMake(self.bounds.size.width - 120, 74 + 20, 100, 216)]; _remotePreView.backgroundColor = [UIColor t_colorWithHexString:@"#242424"]; _remotePreView.hidden = YES; _remotePreView.delegate = self; } return _remotePreView; } - (UIButton *)switchCameraBtn { if (!_switchCameraBtn) { _switchCameraBtn = [UIButton buttonWithType:UIButtonTypeSystem]; [_switchCameraBtn setBackgroundImage:[TUICommonUtil getBundleImageWithName:@"switch_camera"] forState:UIControlStateNormal]; [_switchCameraBtn addTarget:self action:@selector(switchCameraTouchEvent:) forControlEvents:UIControlEventTouchUpInside]; } return _switchCameraBtn; } - (TUICallingControlButton *)switchToAudioBtn { if (!_switchToAudioBtn) { __weak typeof(self) weakSelf = self; _switchToAudioBtn = [TUICallingControlButton createViewWithFrame:CGRectZero titleText:TUICallingLocalize(@"Demo.TRTC.Calling.switchtoaudio") buttonAction:^(UIButton * _Nonnull sender) { [weakSelf switchToAudioTouchEvent:sender]; } imageSize:CGSizeMake(28, 18)]; [_switchToAudioBtn configTitleColor:[UIColor t_colorWithHexString:@"#FFFFFF"]]; [_switchToAudioBtn configBackgroundImage:[TUICommonUtil getBundleImageWithName:@"switch2audio"]]; } return _switchToAudioBtn; } - (TUIVideoUserContainerView *)videoUserContainerView { if (!_videoUserContainerView) { _videoUserContainerView = [[TUIVideoUserContainerView alloc] initWithFrame:CGRectZero]; } return _videoUserContainerView; } - (TUICallingControlButton *)closeCameraBtn { if (!_closeCameraBtn) { __weak typeof(self) weakSelf = self; _closeCameraBtn = [TUICallingControlButton createViewWithFrame:CGRectZero titleText:TUICallingLocalize(@"Demo.TRTC.Calling.camera") buttonAction:^(UIButton * _Nonnull sender) { [weakSelf closeCameraTouchEvent:sender]; } imageSize:kBtnSmallSize]; [_closeCameraBtn configTitleColor:[UIColor t_colorWithHexString:@"#FFFFFF"]]; [_closeCameraBtn configBackgroundImage:[TUICommonUtil getBundleImageWithName:@"camera_on"]]; } return _closeCameraBtn; } @end