201 lines
7.1 KiB
Objective-C
201 lines
7.1 KiB
Objective-C
//
|
||
// AVLiveStreamCell.m
|
||
// AVDemo
|
||
//
|
||
|
||
#import "AVLiveStreamCell.h"
|
||
#import "AVLiveStreamModel.h"
|
||
#import <Masonry/Masonry.h>
|
||
#import <SDWebImage/SDWebImage.h>
|
||
|
||
@interface AVLiveStreamCell ()
|
||
|
||
@property (nonatomic, strong) UIImageView *thumbnailView;
|
||
@property (nonatomic, strong) UIView *overlayView;
|
||
@property (nonatomic, strong) UIImageView *playIcon;
|
||
@property (nonatomic, strong) UILabel *durationLabel;
|
||
@property (nonatomic, strong) UILabel *nameLabel;
|
||
@property (nonatomic, strong) UILabel *liveLabel;
|
||
@property (nonatomic, strong) UILabel *protocolLabel;
|
||
@property (nonatomic, strong) UIImageView *encryptIcon;
|
||
|
||
@end
|
||
|
||
@implementation AVLiveStreamCell
|
||
|
||
- (instancetype)initWithFrame:(CGRect)frame {
|
||
if (self = [super initWithFrame:frame]) {
|
||
[self setupUI];
|
||
}
|
||
return self;
|
||
}
|
||
|
||
- (void)setupUI {
|
||
// 配置 Cell 背景
|
||
self.contentView.backgroundColor = [UIColor secondarySystemBackgroundColor];
|
||
self.contentView.layer.cornerRadius = 8;
|
||
self.contentView.clipsToBounds = YES;
|
||
|
||
// 创建缩略图
|
||
_thumbnailView = [[UIImageView alloc] init];
|
||
_thumbnailView.backgroundColor = [UIColor systemGrayColor];
|
||
_thumbnailView.contentMode = UIViewContentModeScaleAspectFill;
|
||
_thumbnailView.clipsToBounds = YES;
|
||
[self.contentView addSubview:_thumbnailView];
|
||
|
||
// 半透明遮罩层
|
||
_overlayView = [[UIView alloc] init];
|
||
_overlayView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2];
|
||
[_thumbnailView addSubview:_overlayView];
|
||
|
||
// 播放图标
|
||
_playIcon = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"play.circle.fill"]];
|
||
_playIcon.tintColor = [UIColor whiteColor];
|
||
_playIcon.contentMode = UIViewContentModeScaleAspectFit;
|
||
_playIcon.layer.shadowColor = [UIColor blackColor].CGColor;
|
||
_playIcon.layer.shadowOffset = CGSizeMake(0, 2);
|
||
_playIcon.layer.shadowOpacity = 0.3;
|
||
_playIcon.layer.shadowRadius = 4;
|
||
[_thumbnailView addSubview:_playIcon];
|
||
|
||
// 直播时长标签
|
||
_durationLabel = [[UILabel alloc] init];
|
||
_durationLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightMedium];
|
||
_durationLabel.textColor = [UIColor whiteColor];
|
||
_durationLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
|
||
_durationLabel.textAlignment = NSTextAlignmentCenter;
|
||
_durationLabel.layer.cornerRadius = 4;
|
||
_durationLabel.clipsToBounds = YES;
|
||
[_thumbnailView addSubview:_durationLabel];
|
||
|
||
// 流名称标签
|
||
_nameLabel = [[UILabel alloc] init];
|
||
_nameLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold];
|
||
_nameLabel.textColor = [UIColor labelColor];
|
||
_nameLabel.numberOfLines = 1;
|
||
[self.contentView addSubview:_nameLabel];
|
||
|
||
// 底部信息容器
|
||
UIView *infoContainerView = [[UIView alloc] init];
|
||
[self.contentView addSubview:infoContainerView];
|
||
|
||
// 直播状态标签
|
||
_liveLabel = [[UILabel alloc] init];
|
||
_liveLabel.text = @"🔴 直播中";
|
||
_liveLabel.font = [UIFont systemFontOfSize:11 weight:UIFontWeightMedium];
|
||
_liveLabel.textColor = [UIColor systemRedColor];
|
||
[infoContainerView addSubview:_liveLabel];
|
||
|
||
// 协议标签
|
||
_protocolLabel = [[UILabel alloc] init];
|
||
_protocolLabel.font = [UIFont systemFontOfSize:10 weight:UIFontWeightMedium];
|
||
_protocolLabel.textColor = [UIColor whiteColor];
|
||
_protocolLabel.backgroundColor = [UIColor systemBlueColor];
|
||
_protocolLabel.textAlignment = NSTextAlignmentCenter;
|
||
_protocolLabel.layer.cornerRadius = 3;
|
||
_protocolLabel.clipsToBounds = YES;
|
||
[infoContainerView addSubview:_protocolLabel];
|
||
|
||
// 布局
|
||
[_thumbnailView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.top.left.right.equalTo(self.contentView);
|
||
// 使用较低优先级的宽高比约束 3:4,允许它在必要时被压缩
|
||
make.height.equalTo(_thumbnailView.mas_width).multipliedBy(4.0 / 3.0).priority(750);
|
||
}];
|
||
|
||
[_overlayView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.edges.equalTo(_thumbnailView);
|
||
}];
|
||
|
||
[_playIcon mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.center.equalTo(_thumbnailView);
|
||
make.width.height.equalTo(@50);
|
||
}];
|
||
|
||
[_durationLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.bottom.equalTo(_thumbnailView).offset(-8);
|
||
make.right.equalTo(_thumbnailView).offset(-8);
|
||
make.height.equalTo(@20);
|
||
make.width.greaterThanOrEqualTo(@50);
|
||
}];
|
||
|
||
[_nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.top.equalTo(_thumbnailView.mas_bottom).offset(8);
|
||
make.left.equalTo(self.contentView).offset(8);
|
||
make.right.equalTo(self.contentView).offset(-8);
|
||
}];
|
||
|
||
[infoContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.top.equalTo(_nameLabel.mas_bottom).offset(4);
|
||
make.left.equalTo(self.contentView).offset(8);
|
||
make.right.lessThanOrEqualTo(self.contentView).offset(-8);
|
||
make.bottom.lessThanOrEqualTo(self.contentView).offset(-8).priority(750);
|
||
// 移除 height 的硬性约束,让它根据内容自适应
|
||
}];
|
||
|
||
[_liveLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.left.top.bottom.equalTo(infoContainerView);
|
||
}];
|
||
|
||
[_protocolLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.left.equalTo(_liveLabel.mas_right).offset(8);
|
||
make.centerY.equalTo(_liveLabel);
|
||
make.height.equalTo(@16);
|
||
make.width.greaterThanOrEqualTo(@40);
|
||
}];
|
||
|
||
// 加密图标
|
||
_encryptIcon = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"lock.shield.fill"]];
|
||
_encryptIcon.tintColor = [UIColor systemOrangeColor];
|
||
_encryptIcon.contentMode = UIViewContentModeScaleAspectFit;
|
||
_encryptIcon.hidden = YES;
|
||
[infoContainerView addSubview:_encryptIcon];
|
||
|
||
[_encryptIcon mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.left.equalTo(_protocolLabel.mas_right).offset(6);
|
||
make.centerY.equalTo(_liveLabel);
|
||
make.width.height.equalTo(@20);
|
||
make.right.lessThanOrEqualTo(infoContainerView);
|
||
}];
|
||
}
|
||
|
||
- (void)configureWithModel:(AVLiveStreamModel *)model {
|
||
// 设置流名称
|
||
_nameLabel.text = model.displayName;
|
||
|
||
// 设置时长
|
||
_durationLabel.text = model.durationString;
|
||
|
||
// 设置协议标签
|
||
_protocolLabel.text = model.play_protocol.uppercaseString;
|
||
|
||
// 加密图标
|
||
_encryptIcon.hidden = (model.xorKey.length == 0);
|
||
|
||
// 使用 SDWebImage 加载预览图
|
||
if (model.preview_image.length > 0) {
|
||
NSURL *imageURL = [NSURL URLWithString:model.preview_image];
|
||
|
||
[_thumbnailView sd_setImageWithURL:imageURL];
|
||
} else {
|
||
// 没有预览图,清空图片
|
||
_thumbnailView.image = nil;
|
||
}
|
||
}
|
||
|
||
- (void)prepareForReuse {
|
||
[super prepareForReuse];
|
||
|
||
// 取消之前的图片加载任务
|
||
[_thumbnailView sd_cancelCurrentImageLoad];
|
||
|
||
// 清空数据,防止复用时显示错误内容
|
||
_thumbnailView.image = nil;
|
||
_nameLabel.text = @"";
|
||
_durationLabel.text = @"";
|
||
_protocolLabel.text = @"";
|
||
_encryptIcon.hidden = YES;
|
||
}
|
||
|
||
@end
|