438 lines
17 KiB
Objective-C
438 lines
17 KiB
Objective-C
//
|
||
// 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
|