Files
featherVoice/QXLive/Mine(音域)/View/爵位/QXNobilityContentView.m
2025-11-11 17:19:21 +08:00

438 lines
17 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.

//
// QXNobilityContentView.m
// QXLive
//
// Created by 启星 on 2025/11/7.
//
#import "QXNobilityContentView.h"
@interface QXNobilityContentView()<UIScrollViewDelegate>
@property (nonatomic, strong) NSMutableArray *privilegeTitles;
@property (nonatomic, assign) NSInteger rowCount;
@property (nonatomic, strong) NSMutableArray *rowHeaders;
@property (nonatomic, assign) CGFloat rowHeaderWidth;
@property (nonatomic, assign) CGFloat columnHeaderHeight;
@property (nonatomic, assign) CGFloat cellWidth;
@property (nonatomic, assign) CGFloat cellHeight;
// 滚动视图
@property (nonatomic, strong) UIScrollView *verticalScrollView; // 处理垂直滚动
@property (nonatomic, strong) UIScrollView *horizontalScrollView; // 处理水平滚动
@property (nonatomic, strong) UIScrollView *contentScrollView; // 内容区域滚动
@property (nonatomic, strong) UIScrollView *rowHeaderScrollView; // 行标题垂直滚动
// 固定视图
@property (nonatomic, strong) UIView *cornerView; // 左上角
@property (nonatomic, strong) UIView *columnHeaderView; // 列标题(第一行)
@property (nonatomic, strong)UILabel *cornerLabel;
// 内容容器
@property (nonatomic, strong) UIView *contentContainer;
@property (nonatomic, strong) UIView *rowHeaderContainer;
@property (nonatomic, strong) UIView *borderView;
@property (nonatomic, assign) BOOL isSyncingScroll;
@property (nonatomic, assign) NSInteger currentIndex;
@end
@implementation QXNobilityContentView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)setup {
self.clipsToBounds = YES;
int itemWidth = (self.width/4);
self.rowHeaderWidth = itemWidth;
self.columnHeaderHeight = 50;
self.cellWidth = itemWidth;
self.cellHeight = 42;
self.isSyncingScroll = NO;
[self createScrollViews];
[self createFixedViews];
[self createContentViews];
[self bringSubviewToFront:self.horizontalScrollView];
[self bringSubviewToFront:self.rowHeaderScrollView];
[self bringSubviewToFront:self.cornerView];
[self bringSubviewToFront:self.contentScrollView];
}
- (void)createScrollViews {
// 主垂直滚动视图 - 占据整个视图,但只处理垂直滚动
self.verticalScrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
self.verticalScrollView.delegate = self;
self.verticalScrollView.bounces = NO;
self.verticalScrollView.alwaysBounceVertical = YES;
self.verticalScrollView.showsVerticalScrollIndicator = YES;
self.verticalScrollView.showsHorizontalScrollIndicator = NO;
[self addSubview:self.verticalScrollView];
// 主水平滚动视图 - 占据整个视图,但只处理水平滚动
self.horizontalScrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
self.horizontalScrollView.delegate = self;
self.horizontalScrollView.bounces = NO;
self.horizontalScrollView.alwaysBounceHorizontal = YES;
self.horizontalScrollView.showsHorizontalScrollIndicator = YES;
self.horizontalScrollView.showsVerticalScrollIndicator = NO;
[self addSubview:self.horizontalScrollView];
// 内容滚动视图 - 只显示内容区域(不包括固定行列)
CGRect contentFrame = CGRectMake(self.rowHeaderWidth, self.columnHeaderHeight,
self.bounds.size.width - self.rowHeaderWidth,
self.bounds.size.height - self.columnHeaderHeight);
self.contentScrollView = [[UIScrollView alloc] initWithFrame:contentFrame];
self.contentScrollView.delegate = self;
self.contentScrollView.bounces = NO;
self.contentScrollView.alwaysBounceVertical = YES;
self.contentScrollView.alwaysBounceHorizontal = YES;
self.contentScrollView.showsVerticalScrollIndicator = NO;
self.contentScrollView.showsHorizontalScrollIndicator = NO;
[self addSubview:self.contentScrollView];
// 行标题滚动视图 - 支持垂直滚动
CGRect rowHeaderFrame = CGRectMake(0, self.columnHeaderHeight, self.rowHeaderWidth, self.bounds.size.height - self.columnHeaderHeight);
self.rowHeaderScrollView = [[UIScrollView alloc] initWithFrame:rowHeaderFrame];
self.rowHeaderScrollView.delegate = self;
self.rowHeaderScrollView.bounces = NO;
self.rowHeaderScrollView.alwaysBounceVertical = YES;
self.rowHeaderScrollView.showsVerticalScrollIndicator = NO;
self.rowHeaderScrollView.showsHorizontalScrollIndicator = NO;
[self addSubview:self.rowHeaderScrollView];
self.borderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.cellWidth, 0)];
[self.borderView addRoundedCornersWithRadius:6];
self.borderView.layer.borderWidth = 1;
self.borderView.layer.borderColor = RGB16(0xF5E9D1).CGColor;
self.borderView.hidden = YES;
}
- (void)createFixedViews {
// 左上角固定区域 - 永远固定在左上角
self.cornerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.rowHeaderWidth, self.columnHeaderHeight)];
self.cornerView.backgroundColor = [UIColor clearColor];
self.cornerView.backgroundColor = RGB16(0x2A2A4E);
self.cornerView.userInteractionEnabled = NO; // 禁止交互,让滚动视图可以接收触摸
UILabel *cornerLabel = [[UILabel alloc] initWithFrame:self.cornerView.bounds];
cornerLabel.textAlignment = NSTextAlignmentCenter;
cornerLabel.textColor = UIColor.whiteColor;
cornerLabel.font = [UIFont boldSystemFontOfSize:14];
self.cornerLabel = cornerLabel;
[self.cornerView addSubview:cornerLabel];
[self addSubview:self.cornerView];
// 列标题固定区域 - 永远固定在第一行
self.columnHeaderView = [[UIView alloc] initWithFrame:CGRectMake(self.rowHeaderWidth, 0, self.bounds.size.width - self.rowHeaderWidth, self.columnHeaderHeight)];
self.columnHeaderView.backgroundColor = [UIColor clearColor];
self.columnHeaderView.backgroundColor = RGB16(0x2A2A4E);
self.columnHeaderView.userInteractionEnabled = NO;
[self insertSubview:self.columnHeaderView belowSubview:self.cornerView];
}
- (void)createContentViews {
if (self.privilegeTitles.count == 0) {
return;
}
NSArray *columnTitles = self.privilegeTitles;
NSInteger columnCount = columnTitles.count - 1; // 减去第一列
// 计算内容总尺寸
CGFloat contentWidth = self.cellWidth * columnCount;
CGFloat contentHeight = self.cellHeight * self.rowCount;
// 设置滚动视图内容大小
self.verticalScrollView.contentSize = CGSizeMake(self.bounds.size.width, self.columnHeaderHeight + contentHeight);
self.horizontalScrollView.contentSize = CGSizeMake(self.rowHeaderWidth + contentWidth, self.bounds.size.height);
self.contentScrollView.contentSize = CGSizeMake(contentWidth, contentHeight);
self.rowHeaderScrollView.contentSize = CGSizeMake(self.rowHeaderWidth, contentHeight);
self.borderView.height = self.columnHeaderHeight + contentHeight;
// 创建内容容器
self.contentContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, contentWidth, contentHeight)];
[self.contentScrollView addSubview:self.contentContainer];
// 创建行标题容器
self.rowHeaderContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.rowHeaderWidth, contentHeight)];
[self.rowHeaderScrollView addSubview:self.rowHeaderContainer];
// 创建列标题
[self createColumnHeaders:columnTitles];
// 创建行标题
[self createRowHeaders];
// 创建内容单元格
[self createContentCells:columnTitles];
}
- (void)createColumnHeaders:(NSArray *)columnTitles {
// 清除旧内容
for (UIView *view in self.columnHeaderView.subviews) {
[view removeFromSuperview];
}
CGFloat totalHeaderWidth = self.cellWidth * (columnTitles.count - 1);
for (int i = 0; i < columnTitles.count - 1; i++) {
UIView *headerCell = [[UIView alloc] initWithFrame:CGRectMake(i * self.cellWidth, 0, self.cellWidth, self.columnHeaderHeight)];
UILabel *label = [[UILabel alloc] initWithFrame:headerCell.bounds];
label.text = columnTitles[i + 1]; // 跳过第一列
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont boldSystemFontOfSize:12];
label.textColor = UIColor.whiteColor;
label.numberOfLines = 0;
[headerCell addSubview:label];
[self.columnHeaderView addSubview:headerCell];
}
// 设置列标题容器的内容大小
self.columnHeaderView.frame = CGRectMake(self.rowHeaderWidth, 0, totalHeaderWidth, self.columnHeaderHeight);
}
- (void)createRowHeaders {
// 清除旧内容
for (UIView *view in self.rowHeaderContainer.subviews) {
[view removeFromSuperview];
}
for (int i = 0; i < self.rowHeaders.count; i++) {
QXUserNobility *titleData = self.rowHeaders[i];
UIView *headerCell = [[UIView alloc] initWithFrame:CGRectMake(0, i * self.cellHeight, self.rowHeaderWidth, self.cellHeight)];
// headerCell.layer.borderWidth = 0.5;
// headerCell.layer.borderColor = [UIColor lightGrayColor].CGColor;
UILabel *label = [[UILabel alloc] initWithFrame:headerCell.bounds];
label.text = [NSString stringWithFormat:@"%@", titleData.name];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = UIColor.whiteColor;
label.font = [UIFont systemFontOfSize:12];
[headerCell addSubview:label];
if (i%2==0) {
headerCell.backgroundColor = RGB16A(0x323252, 1);
}else{
headerCell.backgroundColor = RGB16A(0x2A2A4E, 1);
}
// 高亮当前用户
// if (titleData.isCurrentUser) {
// headerCell.backgroundColor = [UIColor colorWithRed:0.8 green:0.9 blue:1.0 alpha:1.0];
// headerCell.layer.borderWidth = 2;
// headerCell.layer.borderColor = [UIColor systemBlueColor].CGColor;
// }
[self.rowHeaderContainer addSubview:headerCell];
}
}
- (void)createContentCells:(NSArray *)columnTitles {
// // 清除旧内容
for (UIView *view in self.contentContainer.subviews) {
[view removeFromSuperview];
}
for (int col = 0; col < columnTitles.count - 1; col++) {
QXNobilityLevel *model = self.model.nobility_power_list[col+1];
for (int row = 0; row < self.rowHeaders.count; row++) {
// UIView *cell = [[UIView alloc] initWithFrame:CGRectMake(col * self.cellWidth, row * self.cellHeight, self.cellWidth, self.cellHeight)];
// cell.layer.borderWidth = 0.5;
// cell.layer.borderColor = [UIColor lightGrayColor].CGColor;
//
// UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, self.cellWidth - 10, self.cellHeight)];
// label.font = [UIFont systemFontOfSize:12];
// label.numberOfLines = 0;
// label.textColor = UIColor.whiteColor;
QXUserNobility *md = model.nobility_list[row];
// label.text = md.status.intValue == 1?@"开":@"关";
// [cell addSubview:label];;
// [self.contentContainer addSubview:cell];
QXNobilityContentColView *colView = [[QXNobilityContentColView alloc] initWithFrame:CGRectMake(col * self.cellWidth, row * self.cellHeight, self.cellWidth, self.cellHeight)];
colView.model = md;
if (row%2==0) {
colView.backgroundColor = RGB16A(0x323252, 1);
}else{
colView.backgroundColor = RGB16A(0x2A2A4E, 1);
}
[self.contentContainer addSubview:colView];
}
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.isSyncingScroll) return;
self.isSyncingScroll = YES;
if (scrollView == self.verticalScrollView) {
// 垂直滚动时,同步内容区域和行标题的垂直滚动
CGFloat offsetY = scrollView.contentOffset.y;
self.contentScrollView.contentOffset = CGPointMake(self.contentScrollView.contentOffset.x, offsetY);
self.rowHeaderScrollView.contentOffset = CGPointMake(0, offsetY);
} else if (scrollView == self.horizontalScrollView) {
// 水平滚动时,同步内容区域的水平滚动
CGFloat offsetX = scrollView.contentOffset.x;
self.contentScrollView.contentOffset = CGPointMake(offsetX, self.contentScrollView.contentOffset.y);
} else if (scrollView == self.contentScrollView) {
// 内容区域滚动时,同步主滚动视图
CGFloat offsetX = scrollView.contentOffset.x;
CGFloat offsetY = scrollView.contentOffset.y;
self.verticalScrollView.contentOffset = CGPointMake(self.verticalScrollView.contentOffset.x, offsetY);
self.horizontalScrollView.contentOffset = CGPointMake(offsetX, self.horizontalScrollView.contentOffset.y);
self.rowHeaderScrollView.contentOffset = CGPointMake(0, offsetY);
} else if (scrollView == self.rowHeaderScrollView) {
// 行标题滚动时,同步垂直滚动
CGFloat offsetY = scrollView.contentOffset.y;
self.verticalScrollView.contentOffset = CGPointMake(self.verticalScrollView.contentOffset.x, offsetY);
self.contentScrollView.contentOffset = CGPointMake(self.contentScrollView.contentOffset.x, offsetY);
}
// 更新固定视图的位置
[self updateFixedViewsPosition];
self.isSyncingScroll = NO;
}
- (void)updateFixedViewsPosition {
CGFloat offsetX = self.horizontalScrollView.contentOffset.x;
CGFloat offsetY = self.verticalScrollView.contentOffset.y;
// 固定视图的位置应该始终在可视区域内
// 左上角:始终在 (0, 0)
self.cornerView.frame = CGRectMake(0, 0, self.rowHeaderWidth, self.columnHeaderHeight);
// 列标题:水平跟随滚动,垂直固定在顶部
self.columnHeaderView.frame = CGRectMake(self.rowHeaderWidth - offsetX, 0, self.columnHeaderView.frame.size.width, self.columnHeaderHeight);
// 行标题滚动视图水平固定在左侧垂直位置由自己的contentOffset控制
self.rowHeaderScrollView.frame = CGRectMake(0, self.columnHeaderHeight, self.rowHeaderWidth, self.bounds.size.height - self.columnHeaderHeight);
}
-(void)setModel:(QXNobilityModel *)model{
_model = model;
[self.privilegeTitles removeAllObjects];
[self.rowHeaders removeAllObjects];
for (int i = 0; i < model.nobility_power_list.count;i++ ) {
QXNobilityLevel*md = model.nobility_power_list[i];
[self.privilegeTitles addObject:md.name];
self.rowCount = md.nobility_list.count;
if (i == 0) {
self.cornerLabel.text = md.name;
[self.rowHeaders addObjectsFromArray:md.nobility_list];
}
}
self.currentIndex = 3;
}
- (void)reloadData {
[self createContentViews];
[self scrollToCurrentUser];
}
- (void)scrollToCurrentUser {
if (self.currentIndex == -1) {
return;
}
// self.borderView.hidden = NO;
// self.borderView.x = ((self.width/4)*(self.currentIndex));
// [self.horizontalScrollView addSubview:self.borderView];
// [self.horizontalScrollView bringSubviewToFront:self.borderView];
if (self.currentIndex<3) {
return;
}
[self.horizontalScrollView setContentOffset:CGPointMake(((self.width/4)*(self.currentIndex-2)),0 ) animated:YES];
}
-(NSMutableArray *)privilegeTitles{
if (!_privilegeTitles) {
_privilegeTitles = [NSMutableArray array];
}
return _privilegeTitles;
}
-(NSMutableArray *)rowHeaders{
if (!_rowHeaders) {
_rowHeaders = [NSMutableArray array];
}
return _rowHeaders;
}
@end
@implementation QXNobilityContentColView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self initSubviews];
}
return self;
}
-(void)setModel:(QXUserNobility *)model{
if (model.type.intValue == 1) {
if (model.status.intValue == 1) {
self.imageView.image = [UIImage imageNamed:@"nobility_power_on"];
}else{
self.imageView.image = [UIImage imageNamed:@"nobility_power_off"];
}
}else{
if ([model.nick_name_color_name isExist]) {
self.titleLabel.textColor = [UIColor colorWithHexString:model.nick_name_color];
self.titleLabel.text = model.nick_name_color_name;
}
}
}
-(void)initSubviews{
self.colorView = [[UIView alloc] init];
[self.colorView addRoundedCornersWithRadius:11];
[self addSubview:self.colorView];
[self.colorView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.centerY.equalTo(self);
make.width.height.mas_equalTo(22);
}];
self.titleLabel = [[UILabel alloc] init];
self.titleLabel.textColor = RGB16(0xffffff);
self.titleLabel.font = [UIFont systemFontOfSize:14];
self.titleLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:self.titleLabel];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
self.imageView = [[UIImageView alloc] init];
self.imageView.contentMode = UIViewContentModeScaleToFill;
[self addSubview:self.imageView];
[self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.centerY.equalTo(self);
make.width.height.mas_equalTo(22);
}];
}
@end