新增 MedalsDetailView 和 MedalsLevelIndicatorView 组件,更新 MedalsCollectionViewCell 以支持 MP4 播放控制和可见性管理,优化相关逻辑以提升用户体验,保持代码结构一致性。
This commit is contained in:
@@ -486,6 +486,8 @@
|
||||
23FF42792AA6E19C0055733C /* HomeMenuSourceModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 23FF42782AA6E19C0055733C /* HomeMenuSourceModel.m */; };
|
||||
23FF428E2AAB2D3A0055733C /* XPCandyTreeBuyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 23FF428D2AAB2D3A0055733C /* XPCandyTreeBuyView.m */; };
|
||||
4C0A5B842E02675300955219 /* MedalsCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A5B832E02675300955219 /* MedalsCollectionViewCell.m */; };
|
||||
4C0A5B872E02BB1100955219 /* MedalsLevelIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A5B862E02BB1100955219 /* MedalsLevelIndicatorView.m */; };
|
||||
4C0A5B8A2E02BC3900955219 /* MedalsDetailView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A5B892E02BC3900955219 /* MedalsDetailView.m */; };
|
||||
4C1064882E0014CF007E1586 /* NSMutableArray+Safe.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1064872E0014CF007E1586 /* NSMutableArray+Safe.m */; };
|
||||
4C1119722DD7218300C18416 /* MyEventsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1119712DD7218300C18416 /* MyEventsViewController.m */; };
|
||||
4C1392932D6D963700A6DFB5 /* SubRechargersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1392922D6D963600A6DFB5 /* SubRechargersViewController.m */; };
|
||||
@@ -2637,6 +2639,10 @@
|
||||
23FF428D2AAB2D3A0055733C /* XPCandyTreeBuyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPCandyTreeBuyView.m; sourceTree = "<group>"; };
|
||||
4C0A5B822E02675300955219 /* MedalsCollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MedalsCollectionViewCell.h; sourceTree = "<group>"; };
|
||||
4C0A5B832E02675300955219 /* MedalsCollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MedalsCollectionViewCell.m; sourceTree = "<group>"; };
|
||||
4C0A5B852E02BB1100955219 /* MedalsLevelIndicatorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MedalsLevelIndicatorView.h; sourceTree = "<group>"; };
|
||||
4C0A5B862E02BB1100955219 /* MedalsLevelIndicatorView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MedalsLevelIndicatorView.m; sourceTree = "<group>"; };
|
||||
4C0A5B882E02BC3900955219 /* MedalsDetailView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MedalsDetailView.h; sourceTree = "<group>"; };
|
||||
4C0A5B892E02BC3900955219 /* MedalsDetailView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MedalsDetailView.m; sourceTree = "<group>"; };
|
||||
4C1064862E0014CF007E1586 /* NSMutableArray+Safe.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+Safe.h"; sourceTree = "<group>"; };
|
||||
4C1064872E0014CF007E1586 /* NSMutableArray+Safe.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+Safe.m"; sourceTree = "<group>"; };
|
||||
4C1119702DD7218300C18416 /* MyEventsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyEventsViewController.h; sourceTree = "<group>"; };
|
||||
@@ -6848,6 +6854,10 @@
|
||||
4C886BE72E013C55006F0BA7 /* MedalsViewController.m */,
|
||||
4C0A5B822E02675300955219 /* MedalsCollectionViewCell.h */,
|
||||
4C0A5B832E02675300955219 /* MedalsCollectionViewCell.m */,
|
||||
4C0A5B852E02BB1100955219 /* MedalsLevelIndicatorView.h */,
|
||||
4C0A5B862E02BB1100955219 /* MedalsLevelIndicatorView.m */,
|
||||
4C0A5B882E02BC3900955219 /* MedalsDetailView.h */,
|
||||
4C0A5B892E02BC3900955219 /* MedalsDetailView.m */,
|
||||
);
|
||||
path = Medals;
|
||||
sourceTree = "<group>";
|
||||
@@ -12589,6 +12599,7 @@
|
||||
23E9E99E2A80C7AF00B792F2 /* XPMineGuildPersonalBillRecordItemView.m in Sources */,
|
||||
E87DF4F52A42CC49009C1185 /* HomeMenuInfoModel.m in Sources */,
|
||||
9BD63FAB277EE885006EB744 /* Api+RoomRadio.m in Sources */,
|
||||
4C0A5B8A2E02BC3900955219 /* MedalsDetailView.m in Sources */,
|
||||
E8A30BF328534B17003B4873 /* Api+FindNew.m in Sources */,
|
||||
E852D7412863249F001465ED /* XPMonentsReplyTableViewCell.m in Sources */,
|
||||
237B94BC2A984DA7007853E3 /* XPTrumpetPresenter.m in Sources */,
|
||||
@@ -13178,6 +13189,7 @@
|
||||
545831A02C2AEFAF00364026 /* TenMicStageView.m in Sources */,
|
||||
9BE9F0FF27FED76500667200 /* XPAnchorFansTaskModel.m in Sources */,
|
||||
E85E7BAA2A4EC99300B6D00A /* XPMineGiveDiamondPwdView.m in Sources */,
|
||||
4C0A5B872E02BB1100955219 /* MedalsLevelIndicatorView.m in Sources */,
|
||||
23FF428E2AAB2D3A0055733C /* XPCandyTreeBuyView.m in Sources */,
|
||||
E88C72922828EA4E0047FB2B /* Music+CoreDataClass.m in Sources */,
|
||||
E84A2EA52A5288CB00D6AF8A /* XPGoldDetailsChooseRoomView.m in Sources */,
|
||||
|
@@ -16,6 +16,18 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)updateCell:(MedalSeriesVo *)model;
|
||||
|
||||
/**
|
||||
* 当 cell 将要显示时调用
|
||||
* 用于恢复 mp4 播放
|
||||
*/
|
||||
- (void)willDisplay;
|
||||
|
||||
/**
|
||||
* 当 cell 结束显示时调用
|
||||
* 用于暂停 mp4 播放
|
||||
*/
|
||||
- (void)didEndDisplaying;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@@ -9,241 +9,8 @@
|
||||
#import "MedalsModel.h"
|
||||
#import <QGVAPWrapView.h>
|
||||
#import "XPRoomGiftAnimationParser.h"
|
||||
#import "MedalsLevelIndicatorView.h"
|
||||
|
||||
// 等级指示器视图
|
||||
@interface LevelItemView : UIView
|
||||
|
||||
@property (nonatomic, strong) UILabel *levelLabel;
|
||||
@property (nonatomic, strong) UIView *dotView; // 圆点视图
|
||||
@property (nonatomic, assign) BOOL isSelected;
|
||||
@property (nonatomic, assign) NSInteger level;
|
||||
|
||||
- (instancetype)initWithLevel:(NSInteger)level;
|
||||
- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LevelItemView
|
||||
|
||||
- (instancetype)initWithLevel:(NSInteger)level {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_level = level;
|
||||
_isSelected = NO;
|
||||
|
||||
// 创建圆点视图
|
||||
_dotView = [[UIView alloc] init];
|
||||
_dotView.backgroundColor = UIColorFromRGB(0x8B54E8);
|
||||
_dotView.layer.cornerRadius = 3; // 圆点半径
|
||||
_dotView.clipsToBounds = YES;
|
||||
[self addSubview:_dotView];
|
||||
|
||||
// 创建等级标签
|
||||
self.levelLabel = [UILabel labelInitWithText:[NSString stringWithFormat:@"LV%ld", (long)level]
|
||||
font:kFontMedium(10)
|
||||
textColor:UIColorFromRGB(0x8B54E8)];
|
||||
self.levelLabel.textAlignment = NSTextAlignmentCenter;
|
||||
[self addSubview:self.levelLabel];
|
||||
|
||||
// 布局
|
||||
[_dotView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(self);
|
||||
make.width.height.mas_equalTo(6); // 圆点大小
|
||||
}];
|
||||
|
||||
[self.levelLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(_dotView.mas_bottom).offset(4); // 圆点和文字的间距
|
||||
make.leading.trailing.bottom.mas_equalTo(self);
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
|
||||
if (_isSelected == selected) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isSelected = selected;
|
||||
|
||||
void (^updateBlock)(void) = ^{
|
||||
UIColor *color = selected ? [UIColor whiteColor] : UIColorFromRGB(0x8B54E8);
|
||||
self.levelLabel.textColor = color;
|
||||
self.dotView.backgroundColor = color;
|
||||
};
|
||||
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.2 animations:updateBlock];
|
||||
} else {
|
||||
updateBlock();
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// 等级指示器容器视图
|
||||
@interface LevelIndicatorView : UIView
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray<LevelItemView *> *levelItems;
|
||||
@property (nonatomic, strong) NSMutableArray<UIView *> *connectionLines; // 连接线数组
|
||||
@property (nonatomic, assign) NSInteger maxLevel;
|
||||
@property (nonatomic, assign) NSInteger selectedLevel;
|
||||
@property (nonatomic, copy) void (^levelSelectedBlock)(NSInteger level);
|
||||
|
||||
@end
|
||||
|
||||
@implementation LevelIndicatorView
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_levelItems = [NSMutableArray array];
|
||||
_connectionLines = [NSMutableArray array];
|
||||
_selectedLevel = 1;
|
||||
|
||||
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
|
||||
[self addGestureRecognizer:tapGesture];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupWithMaxLevel:(NSInteger)maxLevel {
|
||||
if (maxLevel < 0) {
|
||||
maxLevel = 1;
|
||||
}
|
||||
if (_maxLevel == maxLevel && _levelItems.count == maxLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
_maxLevel = maxLevel;
|
||||
|
||||
// 清除现有的等级指示器和连接线
|
||||
for (UIView *view in _levelItems) {
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
[_levelItems removeAllObjects];
|
||||
|
||||
for (UIView *line in _connectionLines) {
|
||||
[line removeFromSuperview];
|
||||
}
|
||||
[_connectionLines removeAllObjects];
|
||||
|
||||
// 创建新的等级指示器
|
||||
CGFloat itemWidth = 25.0; // 每个等级指示器的宽度
|
||||
CGFloat spacing = 15.0; // 等级指示器之间的间距
|
||||
CGFloat totalWidth = itemWidth * maxLevel + spacing * (maxLevel - 1);
|
||||
CGFloat startX = (self.bounds.size.width - totalWidth) / 2;
|
||||
|
||||
for (NSInteger i = 1; i <= maxLevel; i++) {
|
||||
// 创建等级指示器
|
||||
LevelItemView *levelItem = [[LevelItemView alloc] initWithLevel:i];
|
||||
[self addSubview:levelItem];
|
||||
[_levelItems addObject:levelItem];
|
||||
|
||||
// 设置位置
|
||||
CGFloat x = startX + (i - 1) * (itemWidth + spacing);
|
||||
[levelItem mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.mas_equalTo(itemWidth);
|
||||
make.height.mas_equalTo(self);
|
||||
make.centerY.mas_equalTo(self);
|
||||
make.leading.mas_equalTo(self).offset(x);
|
||||
}];
|
||||
|
||||
// 如果不是第一个,添加连接线
|
||||
if (i > 1) {
|
||||
UIView *line = [[UIView alloc] init];
|
||||
line.backgroundColor = UIColorFromRGB(0x8B54E8); // 默认非选中颜色
|
||||
[self insertSubview:line atIndex:0];
|
||||
[_connectionLines addObject:line];
|
||||
|
||||
// 连接线位置:从上一个圆点到当前圆点
|
||||
[line mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.height.mas_equalTo(1); // 线的高度
|
||||
make.centerY.mas_equalTo(levelItem.dotView);
|
||||
make.leading.mas_equalTo(_levelItems[i-2].dotView.mas_centerX);
|
||||
make.trailing.mas_equalTo(levelItem.dotView.mas_centerX);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
// 默认选中LV1
|
||||
[self setSelectedLevel:1 animated:NO];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
|
||||
if (_maxLevel > 0 && _levelItems.count > 0) {
|
||||
// 重新计算布局,确保居中显示
|
||||
CGFloat itemWidth = 25.0;
|
||||
CGFloat spacing = 15.0;
|
||||
CGFloat totalWidth = itemWidth * _maxLevel + spacing * (_maxLevel - 1);
|
||||
CGFloat startX = (self.bounds.size.width - totalWidth) / 2;
|
||||
|
||||
for (NSInteger i = 0; i < _levelItems.count; i++) {
|
||||
LevelItemView *item = _levelItems[i];
|
||||
CGFloat x = startX + i * (itemWidth + spacing);
|
||||
[item mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.leading.mas_equalTo(self).offset(x);
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setSelectedLevel:(NSInteger)level animated:(BOOL)animated {
|
||||
if (level < 1 || level > _maxLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
_selectedLevel = level;
|
||||
|
||||
// 更新等级指示器状态
|
||||
for (NSInteger i = 0; i < _levelItems.count; i++) {
|
||||
LevelItemView *item = _levelItems[i];
|
||||
[item setSelected:(i + 1) <= level animated:animated];
|
||||
}
|
||||
|
||||
// 更新连接线状态
|
||||
for (NSInteger i = 0; i < _connectionLines.count; i++) {
|
||||
UIView *line = _connectionLines[i];
|
||||
// 连接线的状态取决于它连接的两个等级指示器是否都被选中
|
||||
// 如果连接线两端的等级指示器都被选中,则连接线也被选中
|
||||
BOOL isSelected = (i + 2) <= level;
|
||||
|
||||
void (^updateBlock)(void) = ^{
|
||||
line.backgroundColor = isSelected ? [UIColor whiteColor] : UIColorFromRGB(0x8B54E8);
|
||||
};
|
||||
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.2 animations:updateBlock];
|
||||
} else {
|
||||
updateBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleTap:(UITapGestureRecognizer *)gesture {
|
||||
CGPoint location = [gesture locationInView:self];
|
||||
|
||||
for (NSInteger i = 0; i < _levelItems.count; i++) {
|
||||
LevelItemView *item = _levelItems[i];
|
||||
CGPoint itemLocation = [self convertPoint:location toView:item];
|
||||
|
||||
if (CGRectContainsPoint(item.bounds, itemLocation)) {
|
||||
NSInteger level = i + 1;
|
||||
[self setSelectedLevel:level animated:YES];
|
||||
|
||||
if (_levelSelectedBlock) {
|
||||
_levelSelectedBlock(level);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface MedalsCollectionViewCell ()
|
||||
|
||||
@@ -255,10 +22,12 @@
|
||||
@property(nonatomic, strong) XPRoomGiftAnimationParser *mp4Parser;
|
||||
@property (nonatomic, strong) UILabel *titleLabel;
|
||||
@property (nonatomic, strong) UILabel *subLabel;
|
||||
@property (nonatomic, strong) LevelIndicatorView *levelIndicatorView;
|
||||
@property (nonatomic, strong) MedalsLevelIndicatorView *levelIndicatorView;
|
||||
|
||||
@property (nonatomic, strong) MedalVos *displayModel;
|
||||
@property (nonatomic, strong) MedalSeriesItemVo *currentItemVo;
|
||||
@property (nonatomic, assign) BOOL isVisible; // 跟踪 cell 是否可见
|
||||
|
||||
@end
|
||||
|
||||
@implementation MedalsCollectionViewCell
|
||||
@@ -323,12 +92,12 @@
|
||||
}];
|
||||
|
||||
// 添加等级指示器
|
||||
self.levelIndicatorView = [[LevelIndicatorView alloc] init];
|
||||
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.left.right.mas_greaterThanOrEqualTo(self.contentView).inset(8);
|
||||
make.leading.trailing.mas_greaterThanOrEqualTo(self.contentView).inset(8);
|
||||
make.height.mas_equalTo(26); // 增加高度以适应圆点和文本
|
||||
}];
|
||||
|
||||
@@ -345,10 +114,52 @@
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 设置通知监听
|
||||
[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;
|
||||
@@ -356,7 +167,6 @@
|
||||
|
||||
// 配置等级指示器
|
||||
[self.levelIndicatorView setupWithMaxLevel:itemVos.medalLevel];
|
||||
|
||||
[self.levelIndicatorView setSelectedLevel:1 animated:NO];
|
||||
|
||||
[self updateDisplayWithCurrentModel];
|
||||
@@ -371,9 +181,6 @@
|
||||
}
|
||||
|
||||
self.titleLabel.text = self.displayModel.name;
|
||||
#if DEBUG
|
||||
self.displayModel.expireSeconds = 1750233926;
|
||||
#endif
|
||||
if (self.displayModel.expireSeconds == 0) {
|
||||
self.subLabel.text = YMLocalizedString(@"20.20.61_text_9");
|
||||
} else {
|
||||
@@ -385,6 +192,9 @@
|
||||
}
|
||||
|
||||
- (void)setImagePath:(NSString *)imagePath {
|
||||
// 停止之前的 mp4 播放
|
||||
[self stopMP4Playback];
|
||||
|
||||
_imagePath = imagePath;
|
||||
self.mp4View.hidden = YES;
|
||||
self.imageView.hidden = NO;
|
||||
@@ -392,24 +202,117 @@
|
||||
}
|
||||
|
||||
- (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]) {
|
||||
[self.mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:nil];
|
||||
// 只有当 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];
|
||||
|
18
YuMi/Modules/YMMine/View/Medals/MedalsDetailView.h
Normal file
18
YuMi/Modules/YMMine/View/Medals/MedalsDetailView.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// MedalsDetailView.h
|
||||
// YuMi
|
||||
//
|
||||
// Created by P on 2025/6/18.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@class MedalSeriesVo;
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MedalsDetailView : UIView
|
||||
|
||||
@property (nonatomic, strong) MedalSeriesVo *detailItemVo;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
219
YuMi/Modules/YMMine/View/Medals/MedalsDetailView.m
Normal file
219
YuMi/Modules/YMMine/View/Medals/MedalsDetailView.m
Normal file
@@ -0,0 +1,219 @@
|
||||
//
|
||||
// MedalsDetailView.m
|
||||
// YuMi
|
||||
//
|
||||
// Created by P on 2025/6/18.
|
||||
//
|
||||
|
||||
#import "MedalsDetailView.h"
|
||||
#import "MedalsModel.h"
|
||||
#import <QGVAPWrapView.h>
|
||||
#import "XPRoomGiftAnimationParser.h"
|
||||
#import "MedalsLevelIndicatorView.h"
|
||||
|
||||
@interface MedalsDetailView ()
|
||||
|
||||
@property (nonatomic, strong) UIImageView *bgLightImageView;
|
||||
@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) MedalSeriesItemVo *currentSeriesItemVO;
|
||||
@property (nonatomic, strong) MedalVos *displayModel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MedalsDetailView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self setupUI];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupUI {
|
||||
self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.8];
|
||||
|
||||
[self addSubview:self.bgLightImageView];
|
||||
[self.bgLightImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.leading.trailing.mas_equalTo(self);
|
||||
make.height.mas_equalTo(self.bgLightImageView.mas_width);
|
||||
}];
|
||||
|
||||
self.imageView = [[NetImageView alloc] init];
|
||||
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
[self addSubview:self.imageView];
|
||||
[self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(kGetScaleWidth(135));
|
||||
make.size.mas_equalTo(CGSizeMake(228, 228));
|
||||
}];
|
||||
|
||||
[self addSubview:self.mp4View];
|
||||
[self.mp4View mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(self.imageView);
|
||||
}];
|
||||
|
||||
self.titleLabel = [UILabel labelInitWithText:@"" font:kFontSemibold(20) textColor:[UIColor whiteColor]];
|
||||
self.subLabel = [UILabel labelInitWithText:@"" font:kFontRegular(12) textColor:[UIColor colorWithWhite:1 alpha:0.6]];
|
||||
self.titleLabel.textAlignment = NSTextAlignmentCenter;
|
||||
self.subLabel.textAlignment = NSTextAlignmentCenter;
|
||||
self.subLabel.numberOfLines = 2;
|
||||
[self addSubview:self.titleLabel];
|
||||
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(self.imageView.mas_bottom).offset(8);
|
||||
make.leading.trailing.mas_equalTo(self).inset(13);
|
||||
}];
|
||||
[self addSubview:self.subLabel];
|
||||
[self.subLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(12);
|
||||
make.leading.trailing.mas_equalTo(self).inset(3);
|
||||
}];
|
||||
|
||||
// 添加等级指示器
|
||||
self.levelIndicatorView = [[MedalsLevelIndicatorView alloc] init];
|
||||
[self addSubview:self.levelIndicatorView];
|
||||
[self.levelIndicatorView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(self.subLabel).offset(24);
|
||||
make.leading.trailing.mas_greaterThanOrEqualTo(self).inset(8);
|
||||
make.height.mas_equalTo(26); // 增加高度以适应圆点和文本
|
||||
}];
|
||||
|
||||
// 设置等级选择回调
|
||||
@kWeakify(self);
|
||||
self.levelIndicatorView.levelSelectedBlock = ^(NSInteger level) {
|
||||
@kStrongify(self);
|
||||
// 处理等级选择事件
|
||||
if (self.currentSeriesItemVO && level <= self.currentSeriesItemVO.medalVos.count) {
|
||||
MedalVos *selectedMedalVo = [self.currentSeriesItemVO.medalVos xpSafeObjectAtIndex:level - 1];
|
||||
if (selectedMedalVo) {
|
||||
self.displayModel = selectedMedalVo;
|
||||
[self updateDisplayWithCurrentModel];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
- (void)setDetailItemVo:(MedalSeriesVo *)detailItemVo {
|
||||
_detailItemVo = detailItemVo;
|
||||
self.currentSeriesItemVO = [detailItemVo.medalSeries xpSafeObjectAtIndex:0];
|
||||
self.displayModel = [self.currentSeriesItemVO.medalVos xpSafeObjectAtIndex:0];
|
||||
|
||||
[self.levelIndicatorView setupWithMaxLevel:self.currentSeriesItemVO.medalLevel];
|
||||
[self.levelIndicatorView setSelectedLevel:1 animated:NO];
|
||||
|
||||
[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;
|
||||
self.subLabel.text = self.displayModel.medalDesc;
|
||||
}
|
||||
}
|
||||
|
||||
- (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]) {
|
||||
[self.mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:nil];
|
||||
}
|
||||
} 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.mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:nil];
|
||||
}
|
||||
} failureBlock:nil];
|
||||
} else {
|
||||
[self.mp4View resumeHWDMP4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
- (UIImageView *)bgLightImageView {
|
||||
if (!_bgLightImageView) {
|
||||
_bgLightImageView = [[UIImageView alloc] initWithImage:kImage(@"medals_lights")];
|
||||
}
|
||||
return _bgLightImageView;
|
||||
}
|
||||
|
||||
- (VAPView *)mp4View {
|
||||
if (!_mp4View) {
|
||||
_mp4View = [[VAPView alloc] init];
|
||||
_mp4View.contentMode = UIViewContentModeScaleAspectFit;
|
||||
}
|
||||
return _mp4View;
|
||||
}
|
||||
|
||||
@end
|
21
YuMi/Modules/YMMine/View/Medals/MedalsLevelIndicatorView.h
Normal file
21
YuMi/Modules/YMMine/View/Medals/MedalsLevelIndicatorView.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// MedalsLevelIndicatorView.h
|
||||
// YuMi
|
||||
//
|
||||
// Created by P on 2025/6/18.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MedalsLevelIndicatorView : UIView
|
||||
|
||||
@property (nonatomic, copy) void (^levelSelectedBlock)(NSInteger level);
|
||||
|
||||
- (void)setupWithMaxLevel:(NSInteger)maxLevel;
|
||||
- (void)setSelectedLevel:(NSInteger)level animated:(BOOL)animated;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
242
YuMi/Modules/YMMine/View/Medals/MedalsLevelIndicatorView.m
Normal file
242
YuMi/Modules/YMMine/View/Medals/MedalsLevelIndicatorView.m
Normal file
@@ -0,0 +1,242 @@
|
||||
//
|
||||
// MedalsLevelIndicatorView.m
|
||||
// YuMi
|
||||
//
|
||||
// Created by P on 2025/6/18.
|
||||
//
|
||||
|
||||
#import "MedalsLevelIndicatorView.h"
|
||||
|
||||
// 等级指示器视图
|
||||
@interface LevelItemView : UIView
|
||||
|
||||
@property (nonatomic, strong) UILabel *levelLabel;
|
||||
@property (nonatomic, strong) UIView *dotView; // 圆点视图
|
||||
@property (nonatomic, assign) BOOL isSelected;
|
||||
@property (nonatomic, assign) NSInteger level;
|
||||
|
||||
- (instancetype)initWithLevel:(NSInteger)level;
|
||||
- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LevelItemView
|
||||
|
||||
- (instancetype)initWithLevel:(NSInteger)level {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_level = level;
|
||||
_isSelected = NO;
|
||||
|
||||
// 创建圆点视图
|
||||
_dotView = [[UIView alloc] init];
|
||||
_dotView.backgroundColor = UIColorFromRGB(0x8B54E8);
|
||||
_dotView.layer.cornerRadius = 3; // 圆点半径
|
||||
_dotView.clipsToBounds = YES;
|
||||
[self addSubview:_dotView];
|
||||
|
||||
// 创建等级标签
|
||||
self.levelLabel = [UILabel labelInitWithText:[NSString stringWithFormat:@"LV%ld", (long)level]
|
||||
font:kFontMedium(10)
|
||||
textColor:UIColorFromRGB(0x8B54E8)];
|
||||
self.levelLabel.textAlignment = NSTextAlignmentCenter;
|
||||
[self addSubview:self.levelLabel];
|
||||
|
||||
// 布局
|
||||
[_dotView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(self);
|
||||
make.width.height.mas_equalTo(6); // 圆点大小
|
||||
}];
|
||||
|
||||
[self.levelLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(_dotView.mas_bottom).offset(4); // 圆点和文字的间距
|
||||
make.leading.trailing.bottom.mas_equalTo(self);
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
|
||||
if (_isSelected == selected) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isSelected = selected;
|
||||
|
||||
void (^updateBlock)(void) = ^{
|
||||
UIColor *color = selected ? [UIColor whiteColor] : UIColorFromRGB(0x8B54E8);
|
||||
self.levelLabel.textColor = color;
|
||||
self.dotView.backgroundColor = color;
|
||||
};
|
||||
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.2 animations:updateBlock];
|
||||
} else {
|
||||
updateBlock();
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// 等级指示器容器视图
|
||||
@interface MedalsLevelIndicatorView()
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray<LevelItemView *> *levelItems;
|
||||
@property (nonatomic, strong) NSMutableArray<UIView *> *connectionLines; // 连接线数组
|
||||
@property (nonatomic, assign) NSInteger maxLevel;
|
||||
@property (nonatomic, assign) NSInteger selectedLevel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MedalsLevelIndicatorView
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_levelItems = [NSMutableArray array];
|
||||
_connectionLines = [NSMutableArray array];
|
||||
_selectedLevel = 1;
|
||||
|
||||
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
|
||||
[self addGestureRecognizer:tapGesture];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupWithMaxLevel:(NSInteger)maxLevel {
|
||||
if (maxLevel < 0) {
|
||||
maxLevel = 1;
|
||||
}
|
||||
if (_maxLevel == maxLevel && _levelItems.count == maxLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
_maxLevel = maxLevel;
|
||||
|
||||
// 清除现有的等级指示器和连接线
|
||||
for (UIView *view in _levelItems) {
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
[_levelItems removeAllObjects];
|
||||
|
||||
for (UIView *line in _connectionLines) {
|
||||
[line removeFromSuperview];
|
||||
}
|
||||
[_connectionLines removeAllObjects];
|
||||
|
||||
// 创建新的等级指示器
|
||||
CGFloat itemWidth = 25.0; // 每个等级指示器的宽度
|
||||
CGFloat spacing = 15.0; // 等级指示器之间的间距
|
||||
CGFloat totalWidth = itemWidth * maxLevel + spacing * (maxLevel - 1);
|
||||
CGFloat startX = (self.bounds.size.width - totalWidth) / 2;
|
||||
|
||||
for (NSInteger i = 1; i <= maxLevel; i++) {
|
||||
// 创建等级指示器
|
||||
LevelItemView *levelItem = [[LevelItemView alloc] initWithLevel:i];
|
||||
[self addSubview:levelItem];
|
||||
[_levelItems addObject:levelItem];
|
||||
|
||||
// 设置位置
|
||||
CGFloat x = startX + (i - 1) * (itemWidth + spacing);
|
||||
[levelItem mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.mas_equalTo(itemWidth);
|
||||
make.height.mas_equalTo(self);
|
||||
make.centerY.mas_equalTo(self);
|
||||
make.leading.mas_equalTo(self).offset(x);
|
||||
}];
|
||||
|
||||
// 如果不是第一个,添加连接线
|
||||
if (i > 1) {
|
||||
UIView *line = [[UIView alloc] init];
|
||||
line.backgroundColor = UIColorFromRGB(0x8B54E8); // 默认非选中颜色
|
||||
[self insertSubview:line atIndex:0];
|
||||
[_connectionLines addObject:line];
|
||||
|
||||
// 连接线位置:从上一个圆点到当前圆点
|
||||
[line mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.height.mas_equalTo(1); // 线的高度
|
||||
make.centerY.mas_equalTo(levelItem.dotView);
|
||||
make.leading.mas_equalTo(_levelItems[i-2].dotView.mas_centerX);
|
||||
make.trailing.mas_equalTo(levelItem.dotView.mas_centerX);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
// 默认选中LV1
|
||||
[self setSelectedLevel:1 animated:NO];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
|
||||
if (_maxLevel > 0 && _levelItems.count > 0) {
|
||||
// 重新计算布局,确保居中显示
|
||||
CGFloat itemWidth = 25.0;
|
||||
CGFloat spacing = 15.0;
|
||||
CGFloat totalWidth = itemWidth * _maxLevel + spacing * (_maxLevel - 1);
|
||||
CGFloat startX = (self.bounds.size.width - totalWidth) / 2;
|
||||
|
||||
for (NSInteger i = 0; i < _levelItems.count; i++) {
|
||||
LevelItemView *item = _levelItems[i];
|
||||
CGFloat x = startX + i * (itemWidth + spacing);
|
||||
[item mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||
make.leading.mas_equalTo(self).offset(x);
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setSelectedLevel:(NSInteger)level animated:(BOOL)animated {
|
||||
if (level < 1 || level > _maxLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
_selectedLevel = level;
|
||||
|
||||
// 更新等级指示器状态
|
||||
for (NSInteger i = 0; i < _levelItems.count; i++) {
|
||||
LevelItemView *item = _levelItems[i];
|
||||
[item setSelected:(i + 1) <= level animated:animated];
|
||||
}
|
||||
|
||||
// 更新连接线状态
|
||||
for (NSInteger i = 0; i < _connectionLines.count; i++) {
|
||||
UIView *line = _connectionLines[i];
|
||||
// 连接线的状态取决于它连接的两个等级指示器是否都被选中
|
||||
// 如果连接线两端的等级指示器都被选中,则连接线也被选中
|
||||
BOOL isSelected = (i + 2) <= level;
|
||||
|
||||
void (^updateBlock)(void) = ^{
|
||||
line.backgroundColor = isSelected ? [UIColor whiteColor] : UIColorFromRGB(0x8B54E8);
|
||||
};
|
||||
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.2 animations:updateBlock];
|
||||
} else {
|
||||
updateBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleTap:(UITapGestureRecognizer *)gesture {
|
||||
CGPoint location = [gesture locationInView:self];
|
||||
|
||||
for (NSInteger i = 0; i < _levelItems.count; i++) {
|
||||
LevelItemView *item = _levelItems[i];
|
||||
CGPoint itemLocation = [self convertPoint:location toView:item];
|
||||
|
||||
if (CGRectContainsPoint(item.bounds, itemLocation)) {
|
||||
NSInteger level = i + 1;
|
||||
[self setSelectedLevel:level animated:YES];
|
||||
|
||||
if (_levelSelectedBlock) {
|
||||
_levelSelectedBlock(level);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@@ -10,8 +10,9 @@
|
||||
#import "UserInfoModel.h"
|
||||
#import "TYCyclePagerView.h"
|
||||
#import "MedalsCollectionViewCell.h"
|
||||
#import "MedalsDetailView.h"
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
typedef enum : NSInteger {
|
||||
MedalsCenterTab_TaskMedals = 1,
|
||||
MedalsCenterTab_ActivityMedals = 2,
|
||||
MedalsCenterTab_GloryMedals = 3,
|
||||
@@ -263,7 +264,7 @@ typedef enum : NSUInteger {
|
||||
if (self.isForMyMedals) {
|
||||
[self.presenter userMedals:self.userInfo.uid
|
||||
page:tabPage
|
||||
type:tabPage];
|
||||
type:tabType];
|
||||
} else {
|
||||
[self.presenter squareMedals:tabPage
|
||||
type:tabType];
|
||||
@@ -354,27 +355,8 @@ typedef enum : NSUInteger {
|
||||
b.selected = NO;
|
||||
}
|
||||
sender.selected = YES;
|
||||
|
||||
switch (sender.tag) {
|
||||
case MedalsCenterTab_TaskMedals:
|
||||
[self.presenter userMedals:self.userInfo.uid
|
||||
page:1
|
||||
type:1];
|
||||
break;
|
||||
case MedalsCenterTab_ActivityMedals:
|
||||
[self.presenter userMedals:self.userInfo.uid
|
||||
page:1
|
||||
type:2];
|
||||
break;
|
||||
case MedalsCenterTab_GloryMedals:
|
||||
[self.presenter userMedals:self.userInfo.uid
|
||||
page:1
|
||||
type:3];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
self.currentTabType = sender.tag;
|
||||
[self loadMedalsList:self.currentTabType page:1];
|
||||
}
|
||||
|
||||
#pragma mark - UICollectionView DataSource & Delegate
|
||||
@@ -395,24 +377,46 @@ typedef enum : NSUInteger {
|
||||
}
|
||||
|
||||
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
MedalsCollectionViewCell *cell = [MedalsCollectionViewCell cellFor:collectionView atIndexPath:indexPath];
|
||||
[cell updateCell:[self loadModel:indexPath.item]];
|
||||
return cell;
|
||||
}
|
||||
|
||||
// 处理 cell 的可见性
|
||||
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if ([cell isKindOfClass:[MedalsCollectionViewCell class]]) {
|
||||
[(MedalsCollectionViewCell *)cell willDisplay];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if ([cell isKindOfClass:[MedalsCollectionViewCell class]]) {
|
||||
[(MedalsCollectionViewCell *)cell didEndDisplaying];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
MedalsDetailView *view = [[MedalsDetailView alloc] initWithFrame:self.view.bounds];
|
||||
view.detailItemVo = [self loadModel:indexPath.item];
|
||||
[self.view addSubview:view];
|
||||
}
|
||||
|
||||
- (MedalSeriesVo *)loadModel:(NSInteger)row {
|
||||
MedalSeriesVo *model = nil;
|
||||
switch (self.currentTabType) {
|
||||
case MedalsCenterTab_TaskMedals:
|
||||
model = [self.datasourceTaskMedals xpSafeObjectAtIndex:indexPath.item];
|
||||
model = [self.datasourceTaskMedals xpSafeObjectAtIndex:row];
|
||||
break;
|
||||
case MedalsCenterTab_ActivityMedals:
|
||||
model = [self.datasourceActivityMedals xpSafeObjectAtIndex:indexPath.item];
|
||||
model = [self.datasourceActivityMedals xpSafeObjectAtIndex:row];
|
||||
break;
|
||||
case MedalsCenterTab_GloryMedals:
|
||||
model = [self.datasourceGloryMedals xpSafeObjectAtIndex:indexPath.item];
|
||||
model = [self.datasourceGloryMedals xpSafeObjectAtIndex:row];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
MedalsCollectionViewCell *cell = [MedalsCollectionViewCell cellFor:collectionView atIndexPath:indexPath];
|
||||
[cell updateCell:model];
|
||||
return cell;
|
||||
return model;
|
||||
}
|
||||
|
||||
#pragma mark - Lazy load
|
||||
|
Reference in New Issue
Block a user