更新 XPMineUserInfoHeaderView.m,调整勋章显示逻辑,允许最多显示 10 个勋章;在 UserRoomCardViewController.m 中新增 UserRoomCardMedalCell 以支持勋章的展示,优化勋章区域的高度计算和更新逻辑,保持代码结构一致性。
This commit is contained in:
@@ -1693,7 +1693,7 @@ HWDMP4PlayDelegate>
|
||||
NSMutableArray<VAPView *> *mp4Views = [NSMutableArray array];
|
||||
|
||||
// 最多显示 10 个勋章
|
||||
NSInteger count = MIN(medals.count, 2);
|
||||
NSInteger count = MIN(medals.count, 10);
|
||||
for (NSInteger i = 0; i < count; i++) {
|
||||
BaseModelVo *medal = medals[i];
|
||||
UIView *medalContainer = [[UIView alloc] init];
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#import "XPUserCardPresenter.h"
|
||||
#import "XPRoomGiftAnimationParser.h"
|
||||
#import <UIImageView+WebCache.h>
|
||||
|
||||
#import "XPSendGiftView.h"
|
||||
#import "XPRoomSendTextView.h"
|
||||
@@ -419,6 +420,213 @@
|
||||
|
||||
@end
|
||||
|
||||
@interface UserRoomCardMedalCell : UICollectionViewCell
|
||||
|
||||
@property(nonatomic, strong) UserInfoModel *userInfo;
|
||||
@property(nonatomic, strong) UIScrollView *medalsScrollView;
|
||||
@property(nonatomic, strong) UIStackView *medalsStackView;
|
||||
@property(nonatomic, strong) NSArray<VAPView *> *medalMP4Views;
|
||||
@property(nonatomic, strong) MASConstraint *scrollViewWidthConstraint;
|
||||
|
||||
+ (void)registerTo:(UICollectionView *)collectionView;
|
||||
+ (UserRoomCardMedalCell *)cellFor:(UICollectionView *)collectionView
|
||||
indexPath:(NSIndexPath *)indexPath
|
||||
userInfo:(UserInfoModel *)userInfo;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UserRoomCardMedalCell
|
||||
|
||||
+ (void)registerTo:(UICollectionView *)collectionView {
|
||||
[collectionView registerClass:[self class]
|
||||
forCellWithReuseIdentifier:NSStringFromClass([self class])];
|
||||
}
|
||||
|
||||
+ (UserRoomCardMedalCell *)cellFor:(UICollectionView *)collectionView
|
||||
indexPath:(NSIndexPath *)indexPath
|
||||
userInfo:(UserInfoModel *)userInfo {
|
||||
UserRoomCardMedalCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([self class])
|
||||
forIndexPath:indexPath];
|
||||
[cell.contentView setBackgroundColor:[UIColor clearColor]];
|
||||
cell.userInfo = userInfo;
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
[self.contentView addSubview:self.medalsScrollView];
|
||||
|
||||
// 计算 ScrollView 的宽度:最多显示5个勋章的宽度,但不超过父视图宽度减去边距
|
||||
CGFloat maxMedalsWidth = kGetScaleWidth(30) * 5 + 4 * 5; // 5个勋章,4个间距
|
||||
|
||||
[self.medalsScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self.contentView);
|
||||
make.centerY.mas_equalTo(self.contentView);
|
||||
make.height.mas_equalTo(kGetScaleWidth(30));
|
||||
// 初始设置一个默认宽度,后续会动态更新
|
||||
self.scrollViewWidthConstraint = make.width.mas_equalTo(maxMedalsWidth);
|
||||
// 确保不超出父视图边界
|
||||
make.leading.mas_greaterThanOrEqualTo(self.contentView).offset(15);
|
||||
make.trailing.mas_lessThanOrEqualTo(self.contentView).offset(-15);
|
||||
}];
|
||||
|
||||
[self.medalsScrollView addSubview:self.medalsStackView];
|
||||
[self.medalsStackView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.bottom.leading.mas_equalTo(self.medalsScrollView);
|
||||
make.height.mas_equalTo(self.medalsScrollView);
|
||||
// 当内容宽度小于 ScrollView 时,居中显示
|
||||
make.centerX.mas_equalTo(self.medalsScrollView).priority(UILayoutPriorityDefaultLow);
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setUserInfo:(UserInfoModel *)userInfo {
|
||||
_userInfo = userInfo;
|
||||
[self updateMedalsDisplay];
|
||||
}
|
||||
|
||||
- (void)updateMedalsDisplay {
|
||||
// 清除旧的勋章视图
|
||||
for (UIView *subview in self.medalsStackView.arrangedSubviews) {
|
||||
[self.medalsStackView removeArrangedSubview:subview];
|
||||
[subview removeFromSuperview];
|
||||
}
|
||||
|
||||
// 停止之前的MP4播放
|
||||
if (self.medalMP4Views) {
|
||||
for (VAPView *mp4View in self.medalMP4Views) {
|
||||
[mp4View stopHWDMP4];
|
||||
}
|
||||
}
|
||||
|
||||
NSArray *medals = self.userInfo.medalsPic;
|
||||
|
||||
if (medals.count == 0) {
|
||||
self.medalsScrollView.hidden = YES;
|
||||
return;
|
||||
} else {
|
||||
#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];
|
||||
medals = arr.copy;
|
||||
#endif
|
||||
}
|
||||
|
||||
self.medalsScrollView.hidden = NO;
|
||||
|
||||
NSMutableArray<VAPView *> *mp4Views = [NSMutableArray array];
|
||||
NSInteger count = medals.count; // 显示所有勋章,但界面只显示5个
|
||||
|
||||
for (NSInteger i = 0; i < count; i++) {
|
||||
BaseModelVo *medal = medals[i];
|
||||
|
||||
UIView *medalContainer = [[UIView alloc] init];
|
||||
medalContainer.backgroundColor = [UIColor clearColor];
|
||||
|
||||
[self.medalsStackView addArrangedSubview:medalContainer];
|
||||
[medalContainer mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.height.mas_equalTo(kGetScaleWidth(30)).priority(UILayoutPriorityRequired);
|
||||
}];
|
||||
|
||||
// 根据 picUrl 后缀判断是 MP4 还是图片
|
||||
if (![NSString isEmpty:medal.picUrl]) {
|
||||
BOOL isMP4 = [[medal.picUrl.lowercaseString pathExtension] isEqualToString:@"mp4"];
|
||||
|
||||
if (isMP4) {
|
||||
// 显示 MP4 动画
|
||||
VAPView *mp4View = [[VAPView alloc] init];
|
||||
mp4View.contentMode = UIViewContentModeScaleAspectFit;
|
||||
mp4View.userInteractionEnabled = NO;
|
||||
[medalContainer addSubview:mp4View];
|
||||
[mp4View mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(medalContainer);
|
||||
}];
|
||||
|
||||
[mp4Views addObject:mp4View];
|
||||
|
||||
XPRoomGiftAnimationParser *parser = [[XPRoomGiftAnimationParser alloc] init];
|
||||
[parser parseWithURL:medal.picUrl
|
||||
completionBlock:^(NSString * _Nullable videoUrl) {
|
||||
if (videoUrl.length > 0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[mp4View setMute:YES];
|
||||
[mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:nil];
|
||||
});
|
||||
}
|
||||
} failureBlock:nil];
|
||||
} else {
|
||||
// 显示图片
|
||||
NetImageView *imageView = [[NetImageView alloc] init];
|
||||
imageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
imageView.userInteractionEnabled = NO;
|
||||
[medalContainer addSubview:imageView];
|
||||
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(medalContainer);
|
||||
}];
|
||||
[imageView loadImageWithUrl:medal.picUrl completion:nil fail:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 延迟更新 ScrollView 的宽度和 contentSize,确保布局完成
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.medalsStackView layoutIfNeeded];
|
||||
CGFloat stackViewWidth = self.medalsStackView.frame.size.width;
|
||||
if (stackViewWidth == 0) {
|
||||
// 如果 StackView 还没有布局,计算预期宽度
|
||||
CGFloat expectedWidth = count * kGetScaleWidth(30) + (count - 1) * 5;
|
||||
stackViewWidth = expectedWidth;
|
||||
}
|
||||
|
||||
// 计算实际需要的 ScrollView 宽度:如果内容少于最大宽度,使用内容宽度;否则使用最大宽度
|
||||
CGFloat maxDisplayWidth = kGetScaleWidth(30) * 5 + 4 * 5; // 5个勋章的最大显示宽度
|
||||
CGFloat scrollViewWidth = MIN(stackViewWidth, maxDisplayWidth);
|
||||
|
||||
// 更新 ScrollView 的宽度约束
|
||||
[self.scrollViewWidthConstraint uninstall];
|
||||
[self.medalsScrollView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
self.scrollViewWidthConstraint = make.width.mas_equalTo(scrollViewWidth);
|
||||
}];
|
||||
|
||||
self.medalsScrollView.contentSize = CGSizeMake(stackViewWidth, kGetScaleWidth(30));
|
||||
[self.contentView layoutIfNeeded];
|
||||
});
|
||||
|
||||
self.medalMP4Views = [mp4Views copy];
|
||||
}
|
||||
|
||||
- (UIScrollView *)medalsScrollView {
|
||||
if (!_medalsScrollView) {
|
||||
_medalsScrollView = [[UIScrollView alloc] init];
|
||||
_medalsScrollView.backgroundColor = [UIColor clearColor];
|
||||
_medalsScrollView.showsHorizontalScrollIndicator = NO;
|
||||
_medalsScrollView.showsVerticalScrollIndicator = NO;
|
||||
_medalsScrollView.scrollEnabled = YES;
|
||||
_medalsScrollView.bounces = YES;
|
||||
_medalsScrollView.alwaysBounceHorizontal = NO;
|
||||
}
|
||||
return _medalsScrollView;
|
||||
}
|
||||
|
||||
- (UIStackView *)medalsStackView {
|
||||
if (!_medalsStackView) {
|
||||
_medalsStackView = [[UIStackView alloc] init];
|
||||
_medalsStackView.backgroundColor = [UIColor clearColor];
|
||||
_medalsStackView.axis = UILayoutConstraintAxisHorizontal;
|
||||
_medalsStackView.distribution = UIStackViewDistributionFill;
|
||||
_medalsStackView.alignment = UIStackViewAlignmentCenter;
|
||||
_medalsStackView.spacing = 5;
|
||||
}
|
||||
return _medalsStackView;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface UserRoomCardUserActionCell : UICollectionViewCell
|
||||
|
||||
@property(nonatomic, strong) UserInfoModel *userInfo;
|
||||
@@ -1299,6 +1507,9 @@
|
||||
|
||||
#pragma mark -
|
||||
- (void)onGetUserInfoSuccess:(UserInfoModel *)userInfo {
|
||||
#if DEBUG
|
||||
// userInfo.medalsPic = @[];
|
||||
#endif
|
||||
self.userInfoModel = userInfo;
|
||||
self.avatar.userInfo = userInfo;
|
||||
@kWeakify(self);
|
||||
@@ -1307,6 +1518,9 @@
|
||||
[self gotoUserInfoVC];
|
||||
}];
|
||||
|
||||
// 立即更新卡片高度
|
||||
[self updateCollectionViewFrame];
|
||||
|
||||
[self.collectionView reloadData];
|
||||
|
||||
BOOL needLoadVIPbg = true;
|
||||
@@ -1416,18 +1630,8 @@
|
||||
self.micActions = temp;
|
||||
[self reloadAllUI];
|
||||
|
||||
if (self.micActions.count == 0) {
|
||||
self.collectionHeight = 120 + 30 + 60 + ([self configRoomDatingPickHeart] ? 68 : 0) + kSafeAreaBottomHeight;
|
||||
} else {
|
||||
self.collectionHeight = 120 + 30 + 60 + 66 + ([self configRoomDatingPickHeart] ? 68 : 0) + kSafeAreaBottomHeight;
|
||||
}
|
||||
CGFloat space_top = KScreenHeight - self.collectionHeight;
|
||||
[UIView animateWithDuration:0.25 animations:^{
|
||||
self.collectionView.frame = CGRectMake(0, space_top, KScreenWidth, self.collectionHeight);
|
||||
} completion:^(BOOL finished) {
|
||||
self.view.alpha = 1;
|
||||
[XNDJTDDLoadingTool hideHUD];
|
||||
}];
|
||||
// 重新计算高度,因为micActions数量可能影响高度
|
||||
[self updateCollectionViewFrame];
|
||||
}
|
||||
|
||||
-(void)onGetFollowDataSccess{
|
||||
@@ -1715,7 +1919,7 @@
|
||||
|
||||
#pragma mark -
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
||||
return 4;
|
||||
return 5;
|
||||
}
|
||||
|
||||
- (CGSize)collectionView:(UICollectionView *)collectionView
|
||||
@@ -1729,9 +1933,13 @@
|
||||
return CGSizeMake(self.collectionViewWidth, 30);
|
||||
break;
|
||||
case 2:
|
||||
return CGSizeMake(self.collectionViewWidth, 60);
|
||||
return CGSizeMake(self.collectionViewWidth,
|
||||
self.userInfoModel.medalsPic.count == 0 ? 0 : 40);
|
||||
break;
|
||||
case 3:
|
||||
return CGSizeMake(self.collectionViewWidth, 60);
|
||||
break;
|
||||
case 4:
|
||||
if (self.micActions.count > 0) {
|
||||
return CGSizeMake(self.collectionViewWidth, 38 + 16 + 12 + ([self configRoomDatingPickHeart] ? 36 + 32 : 0));
|
||||
} else {
|
||||
@@ -1800,6 +2008,14 @@
|
||||
}
|
||||
break;
|
||||
case 2: {
|
||||
// 勋章显示 Cell
|
||||
UserRoomCardMedalCell *cell = [UserRoomCardMedalCell cellFor:collectionView
|
||||
indexPath:indexPath
|
||||
userInfo:self.userInfoModel];
|
||||
return cell;
|
||||
}
|
||||
break;
|
||||
case 3: {
|
||||
@kWeakify(self);
|
||||
UserRoomCardUserActionCell *cell = [UserRoomCardUserActionCell cellFor:collectionView
|
||||
indexPath:indexPath
|
||||
@@ -1812,7 +2028,7 @@
|
||||
return cell;
|
||||
}
|
||||
break;
|
||||
case 3: {
|
||||
case 4: {
|
||||
@kWeakify(self);
|
||||
UserRoomCardMicActionCell *cell = [UserRoomCardMicActionCell cellFor:collectionView
|
||||
indexPath:indexPath
|
||||
@@ -1858,9 +2074,12 @@
|
||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||
layout.minimumLineSpacing = 0;
|
||||
layout.minimumInteritemSpacing = 0;
|
||||
self.collectionHeight = 120 + kSafeAreaBottomHeight + 30 + ([self configRoomDatingPickHeart] ? 68 : 0) + kSafeAreaBottomHeight;
|
||||
|
||||
// 初始化时使用基础高度,后续会根据实际数据更新
|
||||
self.collectionHeight = [self calculateCollectionViewHeight];
|
||||
CGFloat space_top = KScreenHeight - self.collectionHeight;
|
||||
self.collectionViewWidth = KScreenWidth;
|
||||
|
||||
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0,
|
||||
space_top,
|
||||
KScreenWidth,
|
||||
@@ -1879,10 +2098,9 @@
|
||||
_collectionView.clipsToBounds = NO;
|
||||
[UserRoomCardInfoCell registerTo:_collectionView];
|
||||
[UserRoomCardNameplateCell registerTo:_collectionView];
|
||||
[UserRoomCardMedalCell registerTo:_collectionView];
|
||||
[UserRoomCardUserActionCell registerTo:_collectionView];
|
||||
[UserRoomCardMicActionCell registerTo:_collectionView];
|
||||
|
||||
// _collectionView.hidden = YES;
|
||||
}
|
||||
return _collectionView;
|
||||
}
|
||||
@@ -1922,4 +2140,52 @@
|
||||
return _avatar;
|
||||
}
|
||||
|
||||
#pragma mark - Height Calculation
|
||||
- (CGFloat)calculateCollectionViewHeight {
|
||||
// 基础高度组成:
|
||||
// Cell 0 (用户信息): 120
|
||||
// Cell 1 (铭牌): 30
|
||||
// Cell 2 (勋章): 根据勋章数量决定,0或40
|
||||
// Cell 3 (用户操作): 60
|
||||
// Cell 4 (麦克风操作): 根据数量决定,0或66
|
||||
// 相亲模式额外高度: 68或0
|
||||
// 底部安全区域: kSafeAreaBottomHeight
|
||||
|
||||
CGFloat baseHeight = 120 + 30 + 60; // 固定部分
|
||||
|
||||
// 勋章区域高度
|
||||
CGFloat medalHeight = 0;
|
||||
if (self.userInfoModel && self.userInfoModel.medalsPic.count > 0) {
|
||||
medalHeight = 40;
|
||||
}
|
||||
|
||||
// 麦克风操作区域高度
|
||||
CGFloat micActionHeight = 0;
|
||||
if (self.micActions.count > 0) {
|
||||
micActionHeight = 66;
|
||||
}
|
||||
|
||||
// 相亲模式额外高度
|
||||
CGFloat datingHeight = [self configRoomDatingPickHeart] ? 68 : 0;
|
||||
|
||||
return baseHeight + medalHeight + micActionHeight + datingHeight + kSafeAreaBottomHeight;
|
||||
}
|
||||
|
||||
- (void)updateCollectionViewFrame {
|
||||
CGFloat newHeight = [self calculateCollectionViewHeight];
|
||||
if (ABS(self.collectionHeight - newHeight) > 0.1) { // 只有高度确实变化时才更新
|
||||
self.collectionHeight = newHeight;
|
||||
CGFloat space_top = KScreenHeight - self.collectionHeight;
|
||||
|
||||
[UIView animateWithDuration:0.25 animations:^{
|
||||
self.collectionView.frame = CGRectMake(0, space_top, KScreenWidth, self.collectionHeight);
|
||||
} completion:^(BOOL finished) {
|
||||
if (self.userInfoModel) { // 只有用户信息加载完成后才显示
|
||||
self.view.alpha = 1;
|
||||
[XNDJTDDLoadingTool hideHUD];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
Reference in New Issue
Block a user