445 lines
16 KiB
Objective-C
445 lines
16 KiB
Objective-C
//
|
||
// RoomHighValueGiftBanner.m
|
||
// YuMi
|
||
//
|
||
// Created by P on 2024/11/1.
|
||
//
|
||
|
||
#import "RoomHighValueGiftBannerAnimation.h"
|
||
|
||
#import <POP.h>
|
||
#import "SVGA.h"
|
||
#import "AttachmentModel.h"
|
||
#import "GiftReceiveInfoModel.h"
|
||
#import "XCCurrentVCStackManager.h"
|
||
#import "XPRoomViewController.h"
|
||
#import "RoomHostDelegate.h"
|
||
#import "RoomInfoModel.h"
|
||
#import "XPSkillCardPlayerManager.h"
|
||
|
||
@interface RoomHighValueGiftBannerAnimation ()
|
||
|
||
///背景
|
||
@property (nonatomic,strong) UIImageView *backImageView;
|
||
@property (nonatomic, strong) SVGAImageView *svgaImageView;
|
||
///赠送者头像
|
||
@property(nonatomic,strong) NetImageView *senderAvatarView;
|
||
///赠送内容,who send who
|
||
@property(nonatomic,strong) MarqueeLabel *senderScrollLabel;
|
||
///房间名称
|
||
@property(nonatomic,strong) MarqueeLabel *roomNameScrollLabel;
|
||
///礼物
|
||
@property (nonatomic,strong) NetImageView *giftImageView;
|
||
///礼物内容
|
||
@property (nonatomic,strong) UILabel *giftNameLabel;
|
||
@property (nonatomic,strong) UILabel *giftCountLabel;
|
||
///去围观
|
||
@property(nonatomic,strong) UIButton *goButton;
|
||
@property (nonatomic, assign) NSInteger roomUid;
|
||
@property (nonatomic, copy) NSString *bgSourceName;
|
||
|
||
@property (nonatomic, copy) void(^animationComplete)(void);
|
||
|
||
@end
|
||
|
||
@implementation RoomHighValueGiftBannerAnimation
|
||
|
||
+ (void)display:(UIView *)superView
|
||
with:(AttachmentModel *)attachment
|
||
complete:(void(^)(void))complete {
|
||
|
||
NSInteger height = kGetScaleWidth(110);
|
||
NSInteger y = 0;
|
||
|
||
GiftReceiveInfoModel *giftNotifyInfo = [GiftReceiveInfoModel modelWithJSON:attachment.data];
|
||
|
||
__block RoomHighValueGiftBannerAnimation *banner = [[RoomHighValueGiftBannerAnimation alloc] initWithFrame:CGRectMake(KScreenWidth, y, KScreenWidth, height)];
|
||
banner.animationComplete = complete;
|
||
banner.senderAvatarView.imageUrl = giftNotifyInfo.sendUserAvatar;
|
||
banner.giftImageView.imageUrl = giftNotifyInfo.giftUrl;
|
||
banner.roomNameScrollLabel.text = giftNotifyInfo.roomTitle;
|
||
banner.senderScrollLabel.text = [NSString stringWithFormat:@"%@ %@ %@", giftNotifyInfo.sendUserNick, YMLocalizedString(@"XPSessionFindNewGreetListView3"), giftNotifyInfo.recvUserNick];
|
||
banner.giftNameLabel.text = giftNotifyInfo.giftName;
|
||
banner.giftCountLabel.text = [NSString stringWithFormat:@"x %ld", (long)giftNotifyInfo.giftNum];
|
||
banner.roomUid = giftNotifyInfo.roomUid;
|
||
|
||
switch (giftNotifyInfo.bgLevel) {
|
||
case 1:
|
||
banner.bgSourceName = @"gift_normal_1";
|
||
break;
|
||
case 2:
|
||
banner.bgSourceName = @"gift_normal_2";
|
||
break;
|
||
case 3:
|
||
banner.bgSourceName = @"gift_normal_3";
|
||
break;
|
||
case 4:
|
||
banner.bgSourceName = @"gift_VIP_1";
|
||
break;
|
||
case 5:
|
||
banner.bgSourceName = @"gift_VIP_2";
|
||
break;
|
||
case 6:
|
||
banner.bgSourceName = @"gift_VIP_3";
|
||
break;
|
||
|
||
default:
|
||
banner.bgSourceName = @"gift_normal_1";
|
||
break;
|
||
}
|
||
|
||
|
||
[superView addSubview:banner];
|
||
|
||
@kWeakify(banner);
|
||
// 使用 POP 动画移动 banner 到目标位置
|
||
[banner popEnterAnimation:^(BOOL finished) {
|
||
@kStrongify(banner);
|
||
[banner addNotification];
|
||
if (finished) {
|
||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||
[banner popLeaveAnimation:^(bool finished) {
|
||
if (banner.animationComplete) {
|
||
banner.animationComplete();
|
||
}
|
||
[banner removeNotification];
|
||
[banner removeFromSuperview];
|
||
}];
|
||
});
|
||
}
|
||
}];
|
||
}
|
||
|
||
- (void)dealloc {
|
||
[self.svgaImageView stopAnimation];
|
||
}
|
||
|
||
- (void)handleSwipeNotification {
|
||
[self dismissBanner];
|
||
}
|
||
|
||
- (void)handleTapNotification:(NSNotification *)note {
|
||
NSValue *value = note.userInfo[@"point"];
|
||
CGPoint point = [value CGPointValue];
|
||
|
||
// 将 banner 中的点转换为屏幕坐标系
|
||
CGPoint screenPoint = [self convertPoint:point toView:nil];
|
||
|
||
// 发送通知给 FunctionContainer 处理,传递屏幕坐标
|
||
[[NSNotificationCenter defaultCenter] postNotificationName:@"BannerTapToFunctionContainer"
|
||
object:nil
|
||
userInfo:@{@"point": [NSValue valueWithCGPoint:screenPoint]}];
|
||
}
|
||
|
||
- (void)addNotification {
|
||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||
selector:@selector(handleSwipeNotification)
|
||
name:@"SwipeOutBanner"
|
||
object:nil];
|
||
|
||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||
selector:@selector(handleTapNotification:)
|
||
name:@"TapBanner"
|
||
object:nil];
|
||
}
|
||
|
||
- (void)removeNotification {
|
||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||
}
|
||
|
||
- (void)dismissBanner {
|
||
NSLog(@"🚨 RoomHighValueGiftBannerAnimation dismissBanner 被调用");
|
||
[self pop_removeAllAnimations]; // 停止所有动画
|
||
|
||
[self popLeaveAnimation:^(bool finished) {
|
||
NSLog(@"🚨 RoomHighValueGiftBannerAnimation 动画完成,调用回调");
|
||
if (self.animationComplete) {
|
||
self.animationComplete();
|
||
} else {
|
||
NSLog(@"🚨 警告: animationComplete 回调为空");
|
||
}
|
||
[self removeFromSuperview];
|
||
}];
|
||
}
|
||
|
||
- (void)popEnterAnimation:(void(^)(BOOL finished))finish {
|
||
NSInteger height = kGetScaleWidth(110);
|
||
POPSpringAnimation *enterAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
|
||
enterAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, KScreenWidth, height)];
|
||
enterAnimation.springBounciness = 10; // 弹性系数
|
||
enterAnimation.springSpeed = 12; // 动画速度
|
||
enterAnimation.completionBlock = ^(POPAnimation *anim, BOOL finished) {
|
||
if (finish) {
|
||
finish(finished);
|
||
}
|
||
};
|
||
[self pop_addAnimation:enterAnimation forKey:@"enterAnimation"];
|
||
}
|
||
|
||
- (void)popLeaveAnimation:(void(^)(bool finished))finish {
|
||
NSInteger height = kGetScaleWidth(110);
|
||
POPBasicAnimation *exitAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewFrame];
|
||
exitAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(-KScreenWidth, 0, KScreenWidth, height)];
|
||
exitAnimation.duration = 0.25; // 动画持续时间
|
||
exitAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
||
exitAnimation.completionBlock = ^(POPAnimation *anim, BOOL finished) {
|
||
if (finish) {
|
||
finish(finished);
|
||
}
|
||
};
|
||
[self pop_addAnimation:exitAnimation forKey:@"exitAnimation"];
|
||
}
|
||
|
||
- (void)handleTapGo {
|
||
// 找到當前房間
|
||
UIViewController * controllerView = [XCCurrentVCStackManager shareManager].getCurrentVC;
|
||
__block XPRoomViewController<RoomHostDelegate> *roomVC = nil;
|
||
[controllerView.navigationController.viewControllers enumerateObjectsUsingBlock:^(__kindof UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||
if ([obj isKindOfClass:[XPRoomViewController class]]) {
|
||
[controllerView.navigationController popToRootViewControllerAnimated:NO];
|
||
roomVC = obj;
|
||
*stop = YES;
|
||
}
|
||
}];
|
||
|
||
if (roomVC) {
|
||
// 是否相同房間
|
||
if ([roomVC getRoomInfo].uid == self.roomUid) {
|
||
return;
|
||
}
|
||
|
||
__block NSString *targetRoomUid = @(self.roomUid).stringValue;
|
||
[TTPopup alertWithMessage:YMLocalizedString(@"Combo_10") confirmHandler:^{
|
||
[roomVC exitRoom];
|
||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||
[XPRoomViewController openRoom:targetRoomUid
|
||
viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
|
||
});
|
||
} cancelHandler:^{}];
|
||
|
||
} else {
|
||
[XPRoomViewController openRoom:@(self.roomUid).stringValue
|
||
viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
|
||
}
|
||
}
|
||
|
||
- (instancetype)initWithFrame:(CGRect)frame {
|
||
if (self = [super initWithFrame:frame]) {
|
||
[self setupUI];
|
||
}
|
||
return self;
|
||
}
|
||
|
||
- (void)setBgSourceName:(NSString *)bgSourceName {
|
||
_bgSourceName = bgSourceName;
|
||
@kWeakify(self);
|
||
SVGAParser *parser = [[SVGAParser alloc] init];
|
||
[parser parseWithNamed:self.bgSourceName
|
||
inBundle:[NSBundle mainBundle]
|
||
completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) {
|
||
@kStrongify(self);
|
||
self.svgaImageView.videoItem = videoItem;
|
||
[self.svgaImageView startAnimation];
|
||
} failureBlock:^(NSError * _Nonnull error) {
|
||
@kStrongify(self);
|
||
if (self.animationComplete) {
|
||
self.animationComplete();
|
||
}
|
||
}];
|
||
}
|
||
|
||
- (void)setupUI {
|
||
[self addSubview:self.backImageView];
|
||
[self.backImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.edges.mas_equalTo(self);
|
||
}];
|
||
|
||
[self addSubview:self.svgaImageView];
|
||
[self.svgaImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.edges.mas_equalTo(self);
|
||
}];
|
||
|
||
[self addSubview:self.senderAvatarView];
|
||
[self.senderAvatarView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.centerY.mas_equalTo(self);
|
||
make.leading.mas_equalTo(kGetScaleWidth(38));
|
||
make.size.mas_equalTo(CGSizeMake(36, 36));
|
||
}];
|
||
|
||
[self addSubview:self.giftImageView];
|
||
[self.giftImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.centerY.mas_equalTo(self);
|
||
make.trailing.mas_equalTo(kGetScaleWidth(-106));
|
||
make.size.mas_equalTo(CGSizeMake(46, 46));
|
||
}];
|
||
|
||
[self addSubview:self.senderScrollLabel];
|
||
[self.senderScrollLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.top.mas_equalTo(40);
|
||
make.leading.mas_equalTo(self.senderAvatarView.mas_trailing).offset(4);
|
||
make.trailing.mas_equalTo(self.giftImageView.mas_leading).offset(-4);
|
||
make.height.mas_equalTo(16);
|
||
}];
|
||
|
||
[self addSubview:self.giftNameLabel];
|
||
[self.giftNameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.top.mas_equalTo(self.senderScrollLabel.mas_bottom).offset(8);
|
||
make.leading.mas_equalTo(self.senderAvatarView.mas_trailing).offset(4);
|
||
make.height.mas_equalTo(16);
|
||
}];
|
||
|
||
[self addSubview:self.giftCountLabel];
|
||
[self.giftCountLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.bottom.mas_equalTo(self.giftNameLabel);
|
||
make.leading.mas_equalTo(self.giftNameLabel.mas_trailing).offset(7);
|
||
make.height.mas_equalTo(22);
|
||
}];
|
||
|
||
UIImageView *room = [[UIImageView alloc] initWithImage:kImage(@"gift_banner_room")];
|
||
[self addSubview:room];
|
||
[room mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.leading.mas_equalTo(self.giftImageView.mas_trailing).offset(2);
|
||
make.top.mas_equalTo(self.giftImageView);
|
||
make.width.height.mas_equalTo(16);
|
||
}];
|
||
|
||
[self addSubview:self.roomNameScrollLabel];
|
||
[self.roomNameScrollLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.centerY.mas_equalTo(room);
|
||
make.leading.mas_equalTo(room.mas_trailing).offset(2);
|
||
make.trailing.mas_equalTo(self).offset(-34);
|
||
}];
|
||
|
||
[self addSubview:self.goButton];
|
||
[self.goButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.leading.mas_equalTo(self.giftImageView.mas_trailing).offset(8);
|
||
make.top.mas_equalTo(self.roomNameScrollLabel.mas_bottom).offset(4);
|
||
make.size.mas_equalTo(CGSizeMake(55, 20));
|
||
}];
|
||
}
|
||
|
||
|
||
#pragma mark -
|
||
- (UIImageView *)backImageView {
|
||
if (!_backImageView) {
|
||
_backImageView = [[UIImageView alloc] init];
|
||
}
|
||
return _backImageView;
|
||
}
|
||
|
||
- (SVGAImageView *)svgaImageView {
|
||
if (!_svgaImageView) {
|
||
_svgaImageView = [[SVGAImageView alloc] init];
|
||
_svgaImageView.clearsAfterStop = YES;
|
||
}
|
||
return _svgaImageView;
|
||
}
|
||
|
||
- (NetImageView *)senderAvatarView {
|
||
if (!_senderAvatarView) {
|
||
NetImageConfig * config = [[NetImageConfig alloc] init];
|
||
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
|
||
config.imageType = ImageTypeUserIcon;
|
||
_senderAvatarView = [[NetImageView alloc] initWithConfig:config];
|
||
_senderAvatarView.layer.masksToBounds = YES;
|
||
_senderAvatarView.layer.cornerRadius = 18;
|
||
_senderAvatarView.contentMode = UIViewContentModeScaleAspectFill;
|
||
}
|
||
return _senderAvatarView;
|
||
}
|
||
|
||
- (MarqueeLabel *)senderScrollLabel{
|
||
if(!_senderScrollLabel){
|
||
_senderScrollLabel = [[MarqueeLabel alloc] init];
|
||
_senderScrollLabel.scrollDuration = 6.0;
|
||
_senderScrollLabel.textColor = [UIColor whiteColor];
|
||
_senderScrollLabel.fadeLength = 8.0f;
|
||
_senderScrollLabel.font = kFontMedium(11);
|
||
_senderScrollLabel.textAlignment = NSTextAlignmentLeft;
|
||
}
|
||
return _senderScrollLabel;
|
||
}
|
||
|
||
- (MarqueeLabel *)roomNameScrollLabel{
|
||
if(!_roomNameScrollLabel){
|
||
_roomNameScrollLabel = [[MarqueeLabel alloc] init];
|
||
_roomNameScrollLabel.textColor = [UIColor whiteColor];
|
||
_roomNameScrollLabel.scrollDuration = 6.0;
|
||
_roomNameScrollLabel.fadeLength = 8.0f;
|
||
_roomNameScrollLabel.font = kFontMedium(11);
|
||
_roomNameScrollLabel.textAlignment = NSTextAlignmentLeft;
|
||
}
|
||
return _roomNameScrollLabel;
|
||
}
|
||
|
||
- (NetImageView *)giftImageView {
|
||
if (!_giftImageView) {
|
||
NetImageConfig * config = [[NetImageConfig alloc] init];
|
||
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
|
||
config.imageType = ImageTypeUserIcon;
|
||
_giftImageView = [[NetImageView alloc] initWithConfig:config];
|
||
_giftImageView.layer.masksToBounds = YES;
|
||
_giftImageView.layer.cornerRadius = 4;
|
||
_giftImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||
}
|
||
return _giftImageView;
|
||
}
|
||
|
||
- (UILabel *)giftNameLabel {
|
||
if (!_giftNameLabel) {
|
||
_giftNameLabel = [[UILabel alloc] init];
|
||
_giftNameLabel.textColor = UIColorFromRGB(0xFFE468);
|
||
_giftNameLabel.font = kFontMedium(11);
|
||
}
|
||
return _giftNameLabel;
|
||
}
|
||
|
||
- (UILabel *)giftCountLabel {
|
||
if (!_giftCountLabel) {
|
||
_giftCountLabel = [[UILabel alloc] init];
|
||
_giftCountLabel.textColor = UIColorFromRGB(0xFFE468);
|
||
_giftCountLabel.font = kFontMedium(17);
|
||
}
|
||
return _giftCountLabel;
|
||
}
|
||
|
||
- (UIButton *)goButton{
|
||
if(!_goButton){
|
||
_goButton = [UIButton new];
|
||
[_goButton setTitle:YMLocalizedString(@"XPAcrossRoomPKPanelView3") forState:UIControlStateNormal];
|
||
[_goButton setTitleColor:UIColorFromRGB(0x442a00) forState:UIControlStateNormal];
|
||
_goButton.titleLabel.font = kFontRegular(10);
|
||
_goButton.layer.cornerRadius = kGetScaleWidth(20)/2;
|
||
_goButton.layer.masksToBounds = YES;
|
||
// 创建渐变图层
|
||
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
|
||
gradientLayer.colors = @[(__bridge id)UIColorFromRGB(0xFFFADE).CGColor,
|
||
(__bridge id)UIColorFromRGB(0xFFE184).CGColor];
|
||
gradientLayer.startPoint = CGPointMake(0.0, 0.5); // 顶部中央
|
||
gradientLayer.endPoint = CGPointMake(1.0, 0.5); // 底部中央
|
||
gradientLayer.frame = CGRectMake(0, 0, 55, 20); // 设置渐变图层大小
|
||
|
||
// 将渐变图层添加到按钮图层
|
||
[_goButton.layer insertSublayer:gradientLayer atIndex:0];
|
||
[_goButton addTarget:self
|
||
action:@selector(handleTapGo)
|
||
forControlEvents:UIControlEventTouchUpInside];
|
||
}
|
||
return _goButton;
|
||
}
|
||
|
||
// ========== 事件穿透实现 ==========
|
||
//- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
||
// if (!self.userInteractionEnabled || self.hidden || self.alpha <= 0.01) {
|
||
// return nil;
|
||
// }
|
||
// CGPoint goButtonPoint = [self.goButton convertPoint:point fromView:self];
|
||
// if ([self.goButton pointInside:goButtonPoint withEvent:event]) {
|
||
// return self.goButton;
|
||
// }
|
||
// // 其他区域返回self,允许触摸事件被父视图的手势识别器处理
|
||
// return self;
|
||
//}
|
||
|
||
@end
|