Files
peko-ios/YuMi/Modules/YMMine/View/Medals/MedalsCollectionViewCell.m

336 lines
11 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MedalsCollectionViewCell.m
// YuMi
//
// Created by P on 2025/6/18.
//
#import "MedalsCollectionViewCell.h"
#import "MedalsModel.h"
#import <QGVAPWrapView.h>
#import "XPRoomGiftAnimationParser.h"
#import "MedalsLevelIndicatorView.h"
@interface MedalsCollectionViewCell ()
@property(nonatomic, copy) NSString *imagePath;
@property(nonatomic, copy) NSString *mp4Path;
@property(nonatomic, strong) NetImageView *imageView;
@property(nonatomic, strong) VAPView *mp4View;
@property(nonatomic, strong) XPRoomGiftAnimationParser *mp4Parser;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *subLabel;
@property (nonatomic, strong) MedalsLevelIndicatorView *levelIndicatorView;
@property (nonatomic, strong) MedalVo *displayModel;
@property (nonatomic, strong) MedalSeriesItemVo *currentItemVo;
@property (nonatomic, assign) BOOL isVisible; // 跟踪 cell 是否可见
@end
@implementation MedalsCollectionViewCell
+ (NSString *)cellID {
return NSStringFromClass([MedalsCollectionViewCell class]);
}
+ (void)registerTo:(UICollectionView *)collectionView {
[collectionView registerClass:[self class] forCellWithReuseIdentifier:[self cellID]];
}
+ (instancetype)cellFor:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)index {
MedalsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:[self cellID]
forIndexPath:index];
return cell;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self.contentView addGradientBackgroundWithColors:@[
UIColorFromRGB(0x41007b),
UIColorFromRGB(0x290858)
] startPoint:CGPointMake(0.5, 0) endPoint:CGPointMake(0.5, 1) cornerRadius:8];
[self.contentView setAllCornerRadius:8
borderWidth:1
borderColor:UIColorFromRGB(0xa166bf)];
self.imageView = [[NetImageView alloc] init];
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
[self.contentView addSubview:self.imageView];
[self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.contentView);
make.top.mas_equalTo(13);
make.leading.trailing.mas_equalTo(self.contentView).inset(13);
make.height.mas_equalTo(self.imageView.mas_width);
}];
[self.contentView addSubview:self.mp4View];
[self.mp4View mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self.imageView);
}];
self.titleLabel = [UILabel labelInitWithText:@"" font:kFontMedium(14) textColor:[UIColor whiteColor]];
self.subLabel = [UILabel labelInitWithText:@"" font:kFontRegular(11) textColor:[UIColor colorWithWhite:1 alpha:0.6]];
self.titleLabel.textAlignment = NSTextAlignmentCenter;
self.subLabel.textAlignment = NSTextAlignmentCenter;
[self.contentView addSubview:self.titleLabel];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.contentView);
make.top.mas_equalTo(self.imageView.mas_bottom).offset(3);
make.leading.trailing.mas_equalTo(self.contentView).inset(13);
}];
[self.contentView addSubview:self.subLabel];
[self.subLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.contentView);
make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(7);
make.leading.trailing.mas_equalTo(self.contentView).inset(3);
}];
// 添加等级指示器
self.levelIndicatorView = [[MedalsLevelIndicatorView alloc] init];
[self.contentView addSubview:self.levelIndicatorView];
[self.levelIndicatorView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.contentView);
make.bottom.mas_equalTo(self.contentView).offset(-8);
make.leading.trailing.mas_greaterThanOrEqualTo(self.contentView).inset(8);
make.height.mas_equalTo(26); // 增加高度以适应圆点和文本
}];
// 设置等级选择回调
@kWeakify(self);
self.levelIndicatorView.levelSelectedBlock = ^(NSInteger level) {
@kStrongify(self);
// 处理等级选择事件
if (self.currentItemVo && level <= self.currentItemVo.medalVos.count) {
MedalVo *selectedMedalVo = [self.currentItemVo.medalVos xpSafeObjectAtIndex:level - 1];
if (selectedMedalVo) {
self.displayModel = selectedMedalVo;
[self updateDisplayWithCurrentModel];
}
}
};
// 设置通知监听
[self setupNotifications];
}
return self;
}
- (void)setupNotifications {
// 监听应用进入后台和恢复前台的通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appDidEnterBackground)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appWillEnterForeground)
name:UIApplicationWillEnterForegroundNotification
object:nil];
// 监听内存警告通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didReceiveMemoryWarning)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
}
- (void)prepareForReuse {
[super prepareForReuse];
// 停止播放
[self stopMP4Playback];
// 隐藏 mp4 视图
self.mp4View.hidden = YES;
self.imageView.hidden = NO;
// 重置状态
self.mp4Path = nil;
self.imagePath = nil;
self.isVisible = NO;
// 清空文本
self.titleLabel.text = @"";
self.subLabel.text = @"";
}
- (void)updateCell:(MedalSeriesVo *)model {
MedalSeriesItemVo *itemVos = [model.medalSeries xpSafeObjectAtIndex:0];
self.currentItemVo = itemVos;
self.displayModel = [itemVos.medalVos xpSafeObjectAtIndex:0];
// 配置等级指示器
[self.levelIndicatorView setupWithMaxLevel:itemVos.medalLevel];
[self.levelIndicatorView setSelectedLevel:1 animated:NO];
// 设置指示器类型为带图片
self.levelIndicatorView.indicatorType = MedalsLevelIndicatorTypeNormal;
// 为每个等级设置对应的图片
for (NSInteger i = 0; i < itemVos.medalVos.count; i++) {
MedalVo *medalVo = [itemVos.medalVos xpSafeObjectAtIndex:i];
if (medalVo) {
[self.levelIndicatorView setImageUrl:medalVo.picUrl forLevel:i + 1];
}
}
[self updateDisplayWithCurrentModel];
}
- (void)updateDisplayWithCurrentModel {
if (self.displayModel) {
if ([self.displayModel.picUrl hasSuffix:@"mp4"]) {
[self setMp4Path:self.displayModel.picUrl];
} else {
[self setImagePath:self.displayModel.picUrl];
}
self.titleLabel.text = self.displayModel.name;
if (self.displayModel.expireSeconds == 0) {
self.subLabel.text = YMLocalizedString(@"20.20.61_text_9");
} else {
self.subLabel.text = [NSString stringWithFormat:YMLocalizedString(@"20.20.61_text_8"),
[NSDate timestampSwitchTime:self.displayModel.expireSeconds
formatter:@"yyyy/mm/dd"]];
}
}
}
- (void)setImagePath:(NSString *)imagePath {
// 停止之前的 mp4 播放
[self stopMP4Playback];
_imagePath = imagePath;
self.mp4View.hidden = YES;
self.imageView.hidden = NO;
self.imageView.imageUrl = imagePath;
}
- (void)setMp4Path:(NSString *)mp4Path {
// 如果是相同的 mp4 路径,不需要重新加载
if ([_mp4Path isEqualToString:mp4Path]) {
return;
}
// 停止之前的 mp4 播放
[self stopMP4Playback];
_mp4Path = mp4Path;
self.mp4View.hidden = NO;
self.imageView.hidden = YES;
if (!_mp4Parser) {
self.mp4Parser = [[XPRoomGiftAnimationParser alloc] init];
}
@kWeakify(self);
[self.mp4Parser parseWithURL:mp4Path
completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (![NSString isEmpty:videoUrl]) {
// 只有当 cell 可见时才播放
if (self.isVisible) {
[self.mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:nil];
} else {
// 存储 URL但不立即播放
self.mp4View.tag = 1; // 标记已准备好播放
}
}
} failureBlock:^(NSError * _Nullable error) {
NSLog(@"Failed to parse mp4: %@", error);
}];
}
#pragma mark - MP4 播放控制
- (void)stopMP4Playback {
if (self.mp4View) {
[self.mp4View stopHWDMP4];
self.mp4View.tag = 0; // 重置播放状态标记
}
}
- (void)pauseMP4Playback {
if (self.mp4View && !self.mp4View.hidden) {
[self.mp4View pauseHWDMP4];
}
}
- (void)resumeMP4Playback {
if (self.mp4View && !self.mp4View.hidden && self.mp4Path) {
if (self.mp4View.tag == 1) { // 已准备好但尚未播放
@kWeakify(self);
[self.mp4Parser parseWithURL:self.mp4Path
completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (![NSString isEmpty:videoUrl] && self.isVisible) {
[self.mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:nil];
}
} failureBlock:nil];
} else {
[self.mp4View resumeHWDMP4];
}
}
}
#pragma mark - 可见性管理
- (void)willDisplay {
self.isVisible = YES;
[self resumeMP4Playback];
}
- (void)didEndDisplaying {
self.isVisible = NO;
[self pauseMP4Playback];
}
#pragma mark - 通知处理
- (void)appDidEnterBackground {
[self pauseMP4Playback];
}
- (void)appWillEnterForeground {
if (self.isVisible) {
[self resumeMP4Playback];
}
}
- (void)didReceiveMemoryWarning {
// 内存警告时停止播放
if (!self.isVisible) {
[self stopMP4Playback];
}
}
#pragma mark - 生命周期
- (void)dealloc {
// 停止播放
[self stopMP4Playback];
// 移除通知观察者
[[NSNotificationCenter defaultCenter] removeObserver:self];
// 清理资源
self.mp4Parser = nil;
NSLog(@"MedalsCollectionViewCell dealloc");
}
- (VAPView *)mp4View {
if (!_mp4View) {
_mp4View = [[VAPView alloc] init];
_mp4View.contentMode = UIViewContentModeScaleAspectFit;
}
return _mp4View;
}
@end