// // JHTableChart.m // JHChartDemo // // Created by 简豪 on 16/8/24. // Copyright © 2016年 JH. All rights reserved. // #import "JHTableChart.h" #import "JHTableDataRowModel.h" @interface JHTableChart () @property (nonatomic,assign)CGFloat tableWidth; @property (nonatomic,assign) CGFloat tableHeight; @property (nonatomic,assign) CGFloat lastY; @property (nonatomic,assign) CGFloat bodyHeight; @property (nonatomic,strong)NSMutableArray * dataModelArr; @end @implementation JHTableChart -(instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) { _minHeightItems = 40; _beginSpace = 15.0; _tableChartTitleItemsHeight = 50.0; _lineColor = [UIColor darkGrayColor]; _tableTitleFont = [UIFont systemFontOfSize:15]; _tableTitleColor = [UIColor darkGrayColor]; _tableWidth = 100; _lastY = _beginSpace; _bodyHeight = 0; _bodyTextColor = [UIColor darkGrayColor]; } return self; } -(void)setBeginSpace:(CGFloat)beginSpace{ _beginSpace = beginSpace; _lastY = beginSpace; } -(void)setDataArr:(NSArray *)dataArr{ _dataArr = dataArr; _dataModelArr = [NSMutableArray array]; for (NSInteger i = 0; i<_dataArr.count; i++) { JHTableDataRowModel *model = [JHTableDataRowModel new]; model.maxCount = 1; for (id obj in _dataArr[i]) { if ([obj isKindOfClass:[NSArray class]]) { if (model.maxCount<=[obj count]) { model.maxCount = [obj count]; } } } model.dataArr = dataArr[i]; [_dataModelArr addObject:model]; } } /** * CoreGraphic 绘图 * * @param rect */ -(void)drawRect:(CGRect)rect{ CGContextRef context = UIGraphicsGetCurrentContext(); /* 表格四周线条 */ /* 上 */ [self drawLineWithContext:context andStarPoint:P_M(_beginSpace, _beginSpace) andEndPoint:P_M(CGRectGetWidth(self.frame) - _beginSpace , _beginSpace) andIsDottedLine:NO andColor:_lineColor]; /* 下 */ [self drawLineWithContext:context andStarPoint:P_M(_beginSpace, _beginSpace + _tableHeight) andEndPoint:P_M(CGRectGetWidth(self.frame) - _beginSpace ,_beginSpace + _tableHeight) andIsDottedLine:NO andColor:_lineColor]; NSLog(@"视图大小%@\n",NSStringFromCGRect(self.frame)); NSLog(@"起始点:%f\n",_beginSpace); /* 左 */ [self drawLineWithContext:context andStarPoint:P_M(_beginSpace, _beginSpace) andEndPoint:P_M(_beginSpace, _beginSpace + _tableHeight) andIsDottedLine:NO andColor:_lineColor]; /* 右 */ [self drawLineWithContext:context andStarPoint:P_M(CGRectGetWidth(self.frame) - _beginSpace, _beginSpace) andEndPoint:P_M(CGRectGetWidth(self.frame) - _beginSpace, _beginSpace + _tableHeight) andIsDottedLine:NO andColor:_lineColor]; /* 表头 */ if (_tableTitleString.length>0) { [self drawLineWithContext:context andStarPoint:P_M(_beginSpace, _beginSpace +_tableChartTitleItemsHeight) andEndPoint:P_M(CGRectGetWidth(self.frame) - _beginSpace , _beginSpace+_tableChartTitleItemsHeight) andIsDottedLine:NO andColor:_lineColor]; CGSize size = [self sizeOfStringWithMaxSize:CGSizeMake(_tableWidth, _tableChartTitleItemsHeight) textFont:_tableTitleFont.pointSize aimString:_tableTitleString]; [self drawText:_tableTitleString context:context atPoint:CGRectMake(CGRectGetWidth(self.frame)/2.0 - size.width / 2, _beginSpace + _tableChartTitleItemsHeight/2 - size.height / 2.0, _tableWidth, _tableChartTitleItemsHeight) WithColor:_tableTitleColor font:_tableTitleFont]; _lastY = _beginSpace + _tableChartTitleItemsHeight; } /* 绘制列的分割线 */ if (_colTitleArr.count>0) { BOOL hasSetColWidth = 0; /* 如果指定了列的宽度 */ if (_colTitleArr.count == _colWidthArr.count) { hasSetColWidth = YES; }else{ hasSetColWidth = NO; } CGFloat lastX = _beginSpace; for (NSInteger i = 0; i<_colTitleArr.count; i++) { CGFloat wid = (hasSetColWidth?[_colWidthArr[i] floatValue]:_tableWidth / _colTitleArr.count); NSLog(@"第%d列 宽度 为 %f\n",i,wid); CGSize size = [self sizeOfStringWithMaxSize:CGSizeMake(wid, _minHeightItems) textFont:14 aimString:_colTitleArr[i]]; if (i==0) { NSArray *firArr = [_colTitleArr[0] componentsSeparatedByString:@"|"]; if (firArr.count>=2) { [self drawLineWithContext:context andStarPoint:P_M(lastX, _lastY) andEndPoint:P_M(lastX + wid, _lastY + _minHeightItems) andIsDottedLine:NO andColor:_lineColor]; size = [self sizeOfStringWithMaxSize:CGSizeMake(wid, _minHeightItems) textFont:14 aimString:firArr[0]]; [self drawText:firArr[0] context:context atPoint:CGRectMake(lastX + wid / 2.0 + wid / 4.0 - size.width / 2, _lastY + _minHeightItems / 4.0 -size.height / 2.0, wid, _minHeightItems / 2.0) WithColor:_bodyTextColor font:_tableTitleFont]; size = [self sizeOfStringWithMaxSize:CGSizeMake(wid, _minHeightItems) textFont:14 aimString:firArr[1]]; [self drawText:firArr[1] context:context atPoint:CGRectMake(lastX + wid / 4.0 - size.width / 2.0, _lastY + _minHeightItems / 2.0 + _minHeightItems / 4.0 - size.height / 2.0, size.width+5, _minHeightItems / 2.0) WithColor:_bodyTextColor font:_tableTitleFont]; }else{ [self drawText:_colTitleArr[i] context:context atPoint:CGRectMake(lastX + wid / 2.0 - size.width / 2, _lastY + _minHeightItems / 2.0 -size.height / 2.0, wid, size.height) WithColor:_bodyTextColor font:[UIFont systemFontOfSize:14]];; } }else{ [self drawText:_colTitleArr[i] context:context atPoint:CGRectMake(lastX + wid / 2.0 - size.width / 2, _lastY + _minHeightItems / 2.0 -size.height / 2.0, wid, _minHeightItems) WithColor:_bodyTextColor font:[UIFont systemFontOfSize:14]];; } lastX += wid; if (i==_colTitleArr.count - 1) { }else [self drawLineWithContext:context andStarPoint:P_M(lastX, _lastY) andEndPoint:P_M(lastX, _lastY + _bodyHeight) andIsDottedLine:NO andColor:_lineColor]; } _lastY += _minHeightItems; } /* 列名分割线 */ [self drawLineWithContext:context andStarPoint:P_M(_beginSpace, _lastY ) andEndPoint:P_M(_beginSpace + _tableWidth, _lastY ) andIsDottedLine:NO andColor:_lineColor]; BOOL hasSetColWidth = 0; /* 如果指定了列的宽度 */ if (_colTitleArr.count == _colWidthArr.count && _colTitleArr.count>0) { hasSetColWidth = YES; }else{ hasSetColWidth = NO; } /* 绘制具体的行数据 */ for (NSInteger i = 0; i<_dataModelArr.count; i++) { JHTableDataRowModel *model = _dataModelArr[i]; [self drawLineWithContext:context andStarPoint:P_M(_beginSpace, _lastY + model.maxCount * _minHeightItems) andEndPoint:P_M(_beginSpace + _tableWidth, _lastY + model.maxCount * _minHeightItems) andIsDottedLine:NO andColor:_lineColor]; CGFloat lastX = _beginSpace; for (NSInteger j = 0; j< model.dataArr.count; j++) { id rowItems = model.dataArr[j]; CGFloat wid = (hasSetColWidth?[_colWidthArr[j] floatValue]:_tableWidth / _colTitleArr.count); if ([rowItems isKindOfClass:[NSArray class]]) { CGFloat perItemsHeightByMaxCount = model.maxCount * _minHeightItems / [rowItems count]; /* 具体某一列有多个元素时 */ for (NSInteger n = 0; n<[rowItems count]; n++) { [self drawLineWithContext:context andStarPoint:P_M(lastX, _lastY + (n+1) * perItemsHeightByMaxCount) andEndPoint:P_M(lastX + wid, _lastY + (n+1) * perItemsHeightByMaxCount) andIsDottedLine:NO andColor:_lineColor]; CGSize size = [self sizeOfStringWithMaxSize:CGSizeMake(wid, perItemsHeightByMaxCount) textFont:_tableTitleFont.pointSize aimString:rowItems[n]]; // P_M(lastX + wid / 2 - size.width / 2.0, _lastY + (n+1) * perItemsHeightByMaxCount - perItemsHeightByMaxCount / 2.0 - size.height / 2.0) [self drawText:rowItems[n] context:context atPoint:CGRectMake(lastX + wid / 2 - size.width / 2.0, _lastY + (n+1) * perItemsHeightByMaxCount - perItemsHeightByMaxCount / 2.0 - size.height / 2.0, size.width, size.height) WithColor:_bodyTextColor font:_tableTitleFont]; } }else{ CGSize size = [self sizeOfStringWithMaxSize:CGSizeMake(wid, model.maxCount * _minHeightItems) textFont:_tableTitleFont.pointSize aimString:rowItems]; [self drawText:rowItems context:context atPoint:CGRectMake(lastX + wid / 2 - size.width / 2.0, _lastY + model.maxCount * _minHeightItems - model.maxCount * _minHeightItems / 2.0 - size.height / 2.0, size.width, size.height) WithColor:_bodyTextColor font:_tableTitleFont]; } lastX += wid; } _lastY += model.maxCount * _minHeightItems; } } /** * 绘图前数据构建 */ - (void)configBaseData{ _tableWidth = CGRectGetWidth(self.frame) - _beginSpace * 2; [self configColWidthArr]; [self countTableHeight]; } /** * 重构列数据 */ - (void)configColWidthArr{ CGFloat wid = 0; if (_colTitleArr.count>0&&_colTitleArr.count == _colWidthArr.count) { NSMutableArray *arr = [NSMutableArray array]; for (NSInteger i = 0; i<_colWidthArr.count; i++) { if (wid>_tableWidth) { arr = nil; }else{ if (i==_colWidthArr.count-1) { [arr addObject:[NSNumber numberWithFloat:(_tableWidth - wid)]]; }else [arr addObject:_colWidthArr[i]]; } wid += [_colWidthArr[i] floatValue]; } _colWidthArr = [arr copy]; }else{ _colWidthArr = nil; } } /** * 计算表格总高度和表格体高度 */ - (void)countTableHeight{ NSInteger rowCount = 0; for (NSArray * itemsArr in _dataArr) { NSInteger nowCount = 1; for (id obj in itemsArr) { if ([obj isKindOfClass:[NSArray class]]) { if (nowCount<=[obj count]) { nowCount = [obj count]; } } } rowCount += nowCount; } _bodyHeight = rowCount * _minHeightItems + (_colTitleArr.count>0?_minHeightItems:0); _tableHeight = 0; _tableHeight += (_tableTitleString.length>0?_tableChartTitleItemsHeight:0) + _bodyHeight; } /** * 绘制图形 */ -(void)showAnimation{ [self configBaseData]; [self setNeedsDisplay]; } /** * 返回该图表所需的高度 * * @return 高度 */ - (CGFloat)heightFromThisDataSource{ [self countTableHeight]; return _tableHeight + _beginSpace * 2; } @end