我想要一个用于在其中呈现简单图表的类(没有复杂的东西)。我的想法是:
- 子类化
UIView
--> 我们称它为Grapher
- 在其中实现我所有的方法(
drawBarGraph
、drawProgressBar
、drawLineGraph
) - 将其包含在所需的 View Controller 中,创建
Grapher
的实例,调用所需的方法 - 将该实例作为 subview 添加到我的主视图。
让我们进入一些代码,因为我不确定如何解释它。这是 grapher.h
:
@interface Grapher : UIView
{
CGContextRef context; //for passing it in via constructor
//UIColor *backgroundColor;
UIColor *graphColor; //foreground color
}
- (id)initWithFrame:(CGRect)frm inContext:(CGContextRef)ctx;
- (void)setGraphColor:(UIColor*)color;
- (void)drawHistogramWithItems:(NSArray*)items;
//- (void)drawLineChartWithItems:(NSArray*)items;
- (void)drawProgressLineWithPercentage:(float)percent;
以及对应的grapher.m
:
@implementation Grapher
- (id)initWithFrame:(CGRect)frm inContext:(CGContextRef)ctx
{
self = [super initWithFrame:frm];
if (self)
{
context = ctx;
}
return self;
}
#pragma Mark main draw methods
- (void)drawHistogramWithItems:(NSArray *)items
{
//[backgroundColor set];
//UIRectFill(frame);
[graphColor set];
int itemWidth = 20;
if (items.count == 0) return;
float max = -1;
for (SFGraphItem *item in items)
if (item.value > max)
max = item.value;
float spacing = (frame.size.width - (itemWidth * items.count)) / (items.count + 1);
float xPos = spacing;
for (int i = 0; i < items.count; i++)
{
CGFloat itemHeight = ((SFGraphItem*)[items objectAtIndex:i]).value / max * frame.size.height;
CGRect bar = CGRectMake(xPos, frame.origin.y + frame.size.height - itemHeight, itemWidth, itemHeight);
CGContextAddRect(context, bar);
CGContextDrawPath(context, kCGPathFill);
xPos += spacing + itemWidth;
}
}
- (void)drawProgressLineWithPercentage:(float)percent
{
//[backgroundColor set];
//UIRectFill(frame);
[graphColor set];
UIRectFill(CGRectMake(frame.origin.x, frame.origin.y, frame.size.width / 100 * percent, frame.size.height));
}
#pragma Mark setters/getters
- (void)setGraphColor:(UIColor *)color
{
graphColor = color;
}
@end
漂亮又简单。如果我将它子类化为 NSObject
,然后在另一个文件中子类化 UIView
(我们称它为 GraphArea
),覆盖 drawRect
在那里,alloc-init
Grapher
并在其中传递 UIGraphicsGetCurrentContext()
工作得很好。
但我不希望对此有“中间观点”。我想将 UIView
子类化为 Grapher
并这样做:
Grapher *graph = [[Grapher alloc] initWithFrame:CGRectMake(5, 65, winSize.width - 10, 20)]; //some random frame
[graph setGraphColor:[UIColor redColor]];
[graph drawProgressLineWithPercentage:50];
graph.backgroundColor = [UIColor grayColor];
[someview addSubview:graph];
如果我使用 CGContextRef
或这个调用构造函数并尝试获取那里的上下文,它始终为 null。如何在当前上下文中传递?我做错了什么以及如何解决这个问题?
如果我解释得太草率,请告诉我,我会更加努力。
干杯,一月
最佳答案
What am I doing wrong and how to fix this?
如果我没理解错的话,你误解了 View 的作用。
View 在自己的空间中管理自己的绘图。你不给它一个上下文,你让它根据需要创建或设置一个上下文并在它自己的坐标系中绘制。听起来您正在尝试创建一个在另一个 View 的上下文中绘制的 View ,我想不出这样做的一个很好的理由。来自 UIView 的文档,就在页面顶部:
The UIView class defines a rectangular area on the screen and the interfaces for managing the content in that area. At runtime, a view object handles the rendering of any content in its area and also handles any interactions with that content.
如果您试图创建一个仅在另一个 View 中绘制某些内容的 View ,那您就错了。将绘图方法封装在某个类中并使用该类的实例在 View 中绘制图形可能没问题,但如果这是您想要的,则不应将该类设为 UIView 的子类。
If I subclass it as a NSObject then subclass UIView in another file (lets call it GraphArea), override drawRect there, alloc-init the Grapher and pass the UIGraphicsGetCurrentContext() in it works just fine.
子类化 UIView 很好,但是 UIView 子类尝试在其他 View 的空间中绘制是不行的。如果你想创建一个可以作为内容添加到其他 View 的图表,而不是让图表成为它自己的 View ,那么你可以看看 CALayer。使用图层,您可以覆盖 -drawInContext:
来进行绘图。您可以创建图层并将它们添加到现有 View 中。绘图系统会将您的图层与 View 的其他图层合成。
关于ios - 用于自定义绘图的子类 UIView,上下文为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18083430/