#import "BravoGiftBannerView.h" #import "UserInfoModel.h" #import "AttachmentModel.h" #import #import #import "XPRoomViewController.h" #import "XCCurrentVCStackManager.h" //{"data":"{\"times\":\"1.65\",\"sender\":{\"avatar\":\"https://image.pekolive.com/14a8039a-df7f-4a4b-a6b9-99c6d3f9918e.gif\",\"erbanNo\":6228657,\"gender\":1,\"nick\":\"Molistar\",\"uid\":3224},\"coins\":\"1650.0\",\"giftPic\":\"https://image.pekolive.com/1000.png\",\"giftNameMap\":{\"ar\":\"lucky1000\",\"en\":\"lucky1000\",\"zh\":\"lucky1000\",\"tr\":\"lucky1000\"},\"roomUid\":3224}","first":106,"second":1066} @interface BravoGiftBannerViewModel : PIBaseModel @property (nonatomic, assign, readonly) CGFloat times; @property (nonatomic, assign, readonly) CGFloat coins; @property (nonatomic, copy, readonly) NSString *giftPic; @property (nonatomic, copy, readonly) NSDictionary *giftNameMap; @property (nonatomic, copy) NSNumber *roomUid; @property (nonatomic, strong, readonly) UserInfoModel *sender; @end @implementation BravoGiftBannerViewModel @end @interface BravoGiftBannerView () @property (nonatomic, strong) BravoGiftBannerViewModel *model; @property (nonatomic, strong) NetImageView *sendAvatarImageView; @property (nonatomic, strong) NetImageView *giftImageView; @property (nonatomic, strong) UILabel *goldNumLabel; //@property (nonatomic, strong) UIImageView *backgroundImageView; @property (nonatomic, strong) UIImageView *moneyIconImageView; @property(nonatomic, strong) SVGAImageView *svgaView; @property (nonatomic, assign) NSInteger currentRoomUid; @property (nonatomic, copy) void(^completeDisplay)(void); @property (nonatomic, copy) void(^exitCurrentRoom)(void); @end @implementation BravoGiftBannerView + (void)display:(UIView *)superView inRoomUid:(NSInteger)roomUid with:(AttachmentModel *)attachment complete:(void (^)(void))complete exitCurrentRoom:(void(^)(void))exit { BravoGiftBannerViewModel *model = [BravoGiftBannerViewModel modelWithDictionary:attachment.data]; CGRect frame = CGRectMake(KScreenWidth, 0, KScreenWidth, kGetScaleWidth(90)); BravoGiftBannerView *banner = [[BravoGiftBannerView alloc] initWithFrame:frame]; banner.model = model; banner.currentRoomUid = roomUid; banner.completeDisplay = complete; banner.exitCurrentRoom = exit; [banner addNotification]; [superView addSubview:banner]; NSInteger time = 3; @kWeakify(banner); [banner popEnterAnimation:^(BOOL finished) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ @kStrongify(banner); [banner popLeaveAnimation:^(bool finished) { if (banner.completeDisplay) { banner.completeDisplay(); } [banner removeFromSuperview]; }]; }); }]; } - (void)addNotification { @kWeakify(self); [[NSNotificationCenter defaultCenter] addObserverForName:@"SwipeOutBanner" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull notification) { @kStrongify(self); [self dismissBanner]; }]; } - (void)setModel:(BravoGiftBannerViewModel *)model { _model = model; self.sendAvatarImageView.imageUrl = model.sender.avatar; self.giftImageView.imageUrl = model.giftPic; self.goldNumLabel.text = [NSString stringByRemovingRedundantZeros:@(model.coins).stringValue]; } - (void)dismissBanner { [self pop_removeAllAnimations]; // 停止所有动画 [self popLeaveAnimation:^(bool finished) { if (self.completeDisplay) { self.completeDisplay(); } [self removeFromSuperview]; }]; } - (void)popEnterAnimation:(void(^)(BOOL finished))finish { POPSpringAnimation *enterAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame]; enterAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, KScreenWidth, kGetScaleWidth(100))]; 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 { POPBasicAnimation *exitAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewFrame]; exitAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(-KScreenWidth, 0, KScreenWidth, kGetScaleWidth(100))]; 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"]; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setupUI]; self.userInteractionEnabled = NO; UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom]; [self addSubview:b]; [b mas_remakeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self); }]; [b addTarget:self action:@selector(handelTap) forControlEvents:UIControlEventTouchUpInside]; } return self; } - (void)handelTap { if (self.model.roomUid.integerValue == self.currentRoomUid) { return; } // 在弹框显示前保存必要数据,避免依赖banner对象 NSNumber *targetRoomUid = self.model.roomUid; void(^exitCurrentRoomBlock)(void) = self.exitCurrentRoom; @kWeakify(self); [TTPopup alertWithMessage:YMLocalizedString(@"Combo_10") confirmHandler:^{ @kStrongify(self); // 检查banner是否还存在 if (!self) { NSLog(@"⚠️ BravoGiftBannerView: banner已被移除,但弹框回调仍在执行"); // 即使banner被移除,仍然执行跳转逻辑 if (exitCurrentRoomBlock) { exitCurrentRoomBlock(); } dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [XPRoomViewController openRoom:targetRoomUid.stringValue viewController:[XCCurrentVCStackManager shareManager].getCurrentVC]; }); return; } // banner还存在,正常执行 if (self.exitCurrentRoom) { self.exitCurrentRoom(); } dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [XPRoomViewController openRoom:targetRoomUid.stringValue viewController:[XCCurrentVCStackManager shareManager].getCurrentVC]; }); } cancelHandler:^{}]; } - (void)setupUI { // 设置背景图 self.svgaView = [[SVGAImageView alloc] init]; self.svgaView.loops = 0; self.svgaView.clearsAfterStop = YES; [self addSubview:self.svgaView]; [self.svgaView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self); }]; SVGAParser *p = [[SVGAParser alloc] init]; @kWeakify(self); [p parseWithNamed:@"brove_gift" inBundle:[NSBundle mainBundle] completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) { @kStrongify(self); if (videoItem) { self.svgaView.videoItem = videoItem; [self.svgaView startAnimation]; } } failureBlock:^(NSError * _Nonnull error) { @kStrongify(self); if (self.completeDisplay) { self.completeDisplay(); } }]; UILabel *sendLabel = [self sendLabel]; UILabel *winLabel = [self winLabel]; // 发送者头像 NetImageConfig * config = [[NetImageConfig alloc]init]; config.imageType = ImageTypeUserIcon; config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; self.sendAvatarImageView = [[NetImageView alloc] initWithConfig:config]; [self.sendAvatarImageView setCornerRadius:kGetScaleWidth(15)]; // 礼物头像 self.giftImageView = [[NetImageView alloc] initWithConfig:config]; [self.giftImageView setCornerRadius:2]; // 金币数量 self.goldNumLabel = [[UILabel alloc] init]; self.goldNumLabel.font = kFontSemibold(18); self.goldNumLabel.textColor = UIColorFromRGB(0xffec6f); // 金币图标 self.moneyIconImageView = [[UIImageView alloc] init]; self.moneyIconImageView.image = kImage(@"moli_money_icon"); UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[ self.sendAvatarImageView, sendLabel, self.giftImageView, winLabel, self.goldNumLabel, self.moneyIconImageView ]]; stackView.spacing = 4; stackView.alignment = UIStackViewAlignmentCenter; [self addSubview:stackView]; [stackView mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.mas_equalTo(self); make.top.mas_equalTo(self).offset(kGetScaleWidth(28)); }]; [sendLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(24); }]; [winLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(24); }]; [self.sendAvatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.height.mas_equalTo(kGetScaleWidth(30)); }]; [self.giftImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.height.mas_equalTo(kGetScaleWidth(32)); }]; [self.moneyIconImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.height.mas_equalTo(kGetScaleWidth(24)); }]; } - (UILabel *)sendLabel { return [UILabel labelInitWithText:YMLocalizedString(@"Combo_0") font:kFontRegular(14) textColor:[UIColor whiteColor]]; } - (UILabel *)winLabel { return [UILabel labelInitWithText:YMLocalizedString(@"Combo_4") font:kFontRegular(14) textColor:[UIColor whiteColor]]; } @end