New file |
| | |
| | | // |
| | | // 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 |