From 6573c0f6fe5aafc266d65b902c09f9442aa86aa8 Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Tue, 24 Jun 2025 16:45:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20XPMineUserInfoHeaderView.m?= =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E=20medalsStackView=20=E5=92=8C=20med?= =?UTF-8?q?alMP4Views=20=E5=B1=9E=E6=80=A7=E4=BB=A5=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8B=8B=E7=AB=A0=E5=B1=95=E7=A4=BA=E9=80=BB=E8=BE=91=EF=BC=9B?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20medalsHeight=20=E6=96=B9=E6=B3=95=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E5=8B=8B=E7=AB=A0=E9=AB=98=E5=BA=A6=EF=BC=9B=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=20setupMedalsArea=20=E6=96=B9=E6=B3=95=E4=BB=A5?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8B=8B=E7=AB=A0=E8=A7=86=E5=9B=BE=EF=BC=9B?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20updateMedalsDisplay=20=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E4=BB=A5=E5=A4=84=E7=90=86=E5=8B=8B=E7=AB=A0=E7=9A=84=20MP4=20?= =?UTF-8?q?=E5=92=8C=E5=9B=BE=E7=89=87=E5=B1=95=E7=A4=BA=EF=BC=8C=E4=BF=9D?= =?UTF-8?q?=E6=8C=81=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84=E4=B8=80=E8=87=B4?= =?UTF-8?q?=E6=80=A7=E3=80=82=E5=90=8C=E6=97=B6=EF=BC=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=20.vscode/settings.json=20=E6=96=87=E4=BB=B6=E4=BB=A5=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=8B=BC=E5=86=99=E6=A3=80=E6=9F=A5=E8=AF=8D=E6=B1=87?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 15 +- .../MineInfo/XPMineUserInfoHeaderView.m | 158 +++++++++++++++++- 2 files changed, 168 insertions(+), 5 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 20240b1f..7f7b46a6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,16 +9,29 @@ "cSpell.words": [ "autoreleasepool", "Autoresizing", + "BGMP", "Bugly", "Commont", + "Contol", + "CPSVGA", + "erban", + "exper", + "Headwear", + "HWDMP", + "Interitem", + "kindof", "MSRTL", "NIMSDK", "Nonnull", "NSEC", + "NSURL", + "Offical", "Procotol", "QGVAP", "Subview", + "subviews", "Superview", - "Uids" + "Uids", + "XNDJTDD" ] } \ No newline at end of file diff --git a/YuMi/Modules/YMMine/View/SubViews/MineInfo/XPMineUserInfoHeaderView.m b/YuMi/Modules/YMMine/View/SubViews/MineInfo/XPMineUserInfoHeaderView.m index 73dcc6c5..ef560909 100644 --- a/YuMi/Modules/YMMine/View/SubViews/MineInfo/XPMineUserInfoHeaderView.m +++ b/YuMi/Modules/YMMine/View/SubViews/MineInfo/XPMineUserInfoHeaderView.m @@ -173,7 +173,8 @@ HWDMP4PlayDelegate> @property (nonatomic, strong) SVGAImageView *personalBGSvga; @property (nonatomic, strong) UIStackView *medalsStackView; -@property (nonatomic, copy) NSArray *userMedals; + +@property (nonatomic, strong) NSArray *medalMP4Views; @end @@ -217,6 +218,14 @@ HWDMP4PlayDelegate> return namePlateHeight; } ++ (CGFloat)medalsHeight:(NSArray *)medalsList { + if (medalsList.count > 0) { + // 勋章高度 30px + 上下间距 12px (6px * 2) + return 30 + 12; + } + return 0; +} + + (CGFloat)headerHeight:(UserInfoModel *)model cps:(NSInteger)cps { CGFloat height = 0; NSInteger numberOfLines = 1; @@ -241,8 +250,8 @@ HWDMP4PlayDelegate> numberOfLines = ceil(textRect.size.height / lineHeight); } - // topAlbum + cp + name plate area + line contents + others - height = kGetScaleWidth(195) + 160 + [self namePlateHeight:model.userNameplateList] + (lineHeight * numberOfLines) + kGetScaleWidth(80); + // topAlbum + cp + name plate area + medals area + line contents + others + height = kGetScaleWidth(195) + 160 + [self namePlateHeight:model.userNameplateList] + [self medalsHeight:model.medalsPic] + (lineHeight * numberOfLines) + kGetScaleWidth(80); if (cps == 0) { cps = 1; } @@ -289,6 +298,8 @@ HWDMP4PlayDelegate> [self setupNameplateArea]; + [self setupMedalsArea]; + [self setupLocateArea]; [self setupCustomDesc]; @@ -524,12 +535,25 @@ HWDMP4PlayDelegate> }]; } +- (void)setupMedalsArea { + [self.userInfoView addSubview:self.medalsStackView]; + [self.medalsStackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.nameplateCollectionView.mas_bottom).offset(6); + make.leading.mas_equalTo(self.userInfoView).offset(kGetScaleWidth(15)); +// make.trailing.mas_equalTo(self.userInfoView).offset(kGetScaleWidth(-15)); + make.height.mas_equalTo(30); + }]; + + // 默认隐藏,有数据时再显示 + self.medalsStackView.hidden = YES; +} + - (void)setupLocateArea { [self.userInfoView addSubview:self.locateLabel]; [self.locateLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.mas_equalTo(self.userInfoView).offset(kGetScaleWidth(15)); make.height.mas_equalTo(18); - make.top.mas_equalTo(self.nameplateCollectionView.mas_bottom).offset(6); + make.top.mas_equalTo(self.medalsStackView.mas_bottom).offset(6); }]; } @@ -870,6 +894,9 @@ HWDMP4PlayDelegate> } else { self.nobleImageView.hidden = YES; } + + // 更新勋章显示 + [self updateMedalsDisplay:userInfo.medalsPic]; } - (void)loadNamePlate:(NSString *)imagePath targetView:(NetImageView *)targetView { @@ -1594,4 +1621,127 @@ HWDMP4PlayDelegate> return _personalBGImageView; } +- (UIStackView *)medalsStackView { + if (!_medalsStackView) { + _medalsStackView = [[UIStackView alloc] init]; + _medalsStackView.backgroundColor = [UIColor clearColor]; + _medalsStackView.axis = UILayoutConstraintAxisHorizontal; + _medalsStackView.distribution = UIStackViewDistributionEqualSpacing; + _medalsStackView.alignment = UIStackViewAlignmentCenter; + _medalsStackView.spacing = 5; + } + return _medalsStackView; +} + +- (NSArray *)medalMP4Views { + if (!_medalMP4Views) { + _medalMP4Views = [NSArray array]; + } + return _medalMP4Views; +} + +- (void)updateMedalsDisplay:(NSArray *)medals { +#if DEBUG + NSMutableArray *arr = [NSMutableArray arrayWithArray:medals]; + [arr addObjectsFromArray:arr.copy]; + [arr addObjectsFromArray:arr.copy]; + [arr addObjectsFromArray:arr.copy]; + [arr addObjectsFromArray:arr.copy]; + [arr addObjectsFromArray:arr.copy]; + [arr addObjectsFromArray:arr.copy]; + medals = arr.copy; +#endif + // 停止并清除之前的播放器 + for (VAPView *mp4View in self.medalMP4Views) { + [mp4View stopHWDMP4]; + } + + // 清空 StackView 中的所有子视图 + for (UIView *subview in self.medalsStackView.arrangedSubviews) { + [self.medalsStackView removeArrangedSubview:subview]; + [subview removeFromSuperview]; + } + + if (medals.count == 0) { + self.medalsStackView.hidden = YES; + return; + } + + self.medalsStackView.hidden = NO; + NSMutableArray *mp4Views = [NSMutableArray array]; + + // 最多显示 10 个勋章 + NSInteger count = MIN(medals.count, 10); + for (NSInteger i = 0; i < count; i++) { + BaseModelVo *medal = medals[i]; + UIView *medalContainer = [[UIView alloc] init]; + medalContainer.backgroundColor = [UIColor clearColor]; + + if ([medal.picUrl.lowercaseString hasSuffix:@".mp4"]) { + // 显示 MP4 - 需要先通过 XPRoomGiftAnimationParser 解析 + VAPView *mp4View = [[VAPView alloc] init]; + mp4View.contentMode = UIViewContentModeScaleAspectFit; + mp4View.hwd_Delegate = self; + + [medalContainer addSubview:mp4View]; + [mp4View mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(medalContainer); + }]; + + [mp4Views addObject:mp4View]; + + // 创建 parser 来解析 MP4 URL + XPRoomGiftAnimationParser *parser = [[XPRoomGiftAnimationParser alloc] init]; + @kWeakify(self); + [parser parseWithURL:[medal.picUrl pureURLString] + completionBlock:^(NSString * _Nullable videoUrl) { + @kStrongify(self); + if (videoUrl.length) { + [mp4View setMute:YES]; + [mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:self]; + } + } failureBlock:^(NSError * _Nullable error) { + // 解析失败,可以显示默认图片或隐藏 + NSLog(@"Medal MP4 parse failed: %@", error); + }]; + } else { + // 显示图片 + NetImageView *imageView = [[NetImageView alloc] init]; + imageView.imageUrl = medal.picUrl; + imageView.contentMode = UIViewContentModeScaleAspectFit; + + [medalContainer addSubview:imageView]; + [imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(medalContainer); + }]; + } + + [self.medalsStackView addArrangedSubview:medalContainer]; + [medalContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(30).priority(UILayoutPriorityRequired); + }]; + + // 设置内容压缩阻力优先级,防止被压缩 + [medalContainer setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; + [medalContainer setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; + + // 设置内容拥抱优先级,防止被拉伸 + [medalContainer setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; + [medalContainer setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; + } + + self.medalMP4Views = [mp4Views copy]; +} + +- (void)stopAllMedalsMP4 { + for (VAPView *mp4View in self.medalMP4Views) { + [mp4View stopHWDMP4]; + } + self.medalMP4Views = @[]; +} + +- (void)dealloc { + [self stopAllMedalsMP4]; +} + @end