I am trying to draw grid on a UIView on a UIScrollView.
The width of UIView is about 1000 pixels. However, I can draw lines only
about first 340 pixels of the UIView. Can anyone help me on this?
The drawGrid function is
- (void)drawRect:(CGRect)rect
{
NSInteger width = 25 * 5 * 10;
NSInteger height = (10 * 2 + 10) * 12;
NSInteger i;
//Get the CGContext from this view
CGContextRef context = UIGraphicsGetCurrentContext();
// Draw rectangle with a blue stroke color and white fill color
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 2.0);
CGContextAddRect(context, CGRectMake(0.0, 0.0, width, height));
CGContextFillPath(context);
// Draw grid with red color
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
// Set the width of the pen mark
CGContextSetLineWidth(context, 0.2);
for (i = 0; i < height; i += 5)
{
if (i % 25 == 0)
{
CGContextSetLineWidth(context, 0.4);
// Draw a line
CGContextMoveToPoint(context, i, 0.0);
CGContextAddLineToPoint(context, i, width);
CGContextStrokePath(context);
CGContextSetLineWidth(context, 0.2);
}
else
{
// Draw a line
CGContextMoveToPoint(context, i, 0.0);
CGContextAddLineToPoint(context, i, width);
CGContextStrokePath(context);
}
}
for (i = 0; i < width; i += 5)
{
if (i % 25 == 0)
{
CGContextSetLineWidth(context, 0.4);
// Draw a line
CGContextMoveToPoint(context, 0.0, i);
CGContextAddLineToPoint(context, height, i);
CGContextStrokePath(context);
CGContextSetLineWidth(context, 0.2);
}
else
{
// Draw a line
CGContextMoveToPoint(context, 0.0, i);
CGContextAddLineToPoint(context, height, i);
CGContextStrokePath(context);
}
}
}
I am also setting up the UIScrollView and UIView as follows:
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
waveScrollView = [[WaveScrollView alloc] initWithFrame:frame];
CGRect waveframe = CGRectMake(0, 0, 25 * 5 * 10, (10 * 2 + 10) * 12);
EKGWaveView *ekgWaveView = [[EKGWaveView alloc] initWithFrame:waveframe];
waveScrollView.contentSize = CGSizeMake(waveframe.size.width, waveframe.size.height);
waveScrollView.maximumZoomScale = 4.0;
waveScrollView.minimumZoomScale = 0.75;
waveScrollView.clipsToBounds = YES;
waveScrollView.aView = ekgWaveView;
[waveScrollView addSubview:ekgWaveView];
waveScrollView.delegate = self;
[self.view addSubview:waveScrollView];
}
I appreciate any help. Thanks.
I'm pretty sure you've got some of your variables mixed up.
You're looping i from 0 to height but then you're using i as your x parameter when creating lines, and using width as your y parameter.
Related
I'm new to cocoa. I thought I could set the UITableViewCell background view to my own custom subclass in order to display a loading bar in the background of the cell, but it seems that calling setNeedsDisplay when I want to update the bar is not fast enough for my needs. Right now I'm updating it (by that I mean updating data in the UIView and then calling setNeedsDisplay) every .1 seconds and only seeing it actual update every 30-40 seconds. Is this normal? Is there any way to speed it up? If not are there other options for what I'm trying to do?
This is my code for draw rect (there's a helper methode above it) and updateBarAt, which is what is called to update it:
-(void) updateBarAt: (float) playHead {
self.playHead = playHead;
NSLog(#"%f", self.playHead);
[self setNeedsDisplay];
}
-(void) drawBackground: (CGRect) rect{
double totalTime = self.playFor + self.wait;
double waitPercentage = self.wait / totalTime;
double playForPercentage = (self.playFor - self.fadeIn - self.fadeOut) / totalTime;
double fadeInPercentage = self.fadeIn / totalTime;
double fadeOutPercentage = self.fadeOut / totalTime;
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect blueRect = CGRectMake((waitPercentage+fadeInPercentage)*rect.size.width, 0, playForPercentage*rect.size.width, rect.size.height);
CGContextSetRGBFillColor(context, .639, .737, 1, 1.0);
CGContextFillRect(context, blueRect);
CGRect greenRect = CGRectMake(0, 0, waitPercentage*rect.size.width, rect.size.height);
CGContextSetRGBFillColor(context, .843, 1, .651, 1.0);
CGContextFillRect(context, greenRect);
CGRect purpleRect = CGRectMake(waitPercentage*rect.size.width+.1, 0, fadeInPercentage*rect.size.width, rect.size.height);
CGContextSetRGBFillColor(context, .7451, .639, 1.0, 1.0);
CGContextFillRect(context, purpleRect);
CGRect purpleR = CGRectMake((1.0 - fadeOutPercentage)*rect.size.width - .5, 0, fadeOutPercentage*rect.size.width + .5, rect.size.height);
CGContextFillRect(context, purpleR);
}
- (void)drawRect:(CGRect)rect { //just does blue and green, need to add purple. Research
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, rect);
if (self.playHead == -1)
return;
[super drawRect:rect];
double totalTime = self.playFor + self.wait;
double playedPercentage = self.playHead / totalTime;
double waitPercentage = self.wait / totalTime;
double playForPercentage = (self.playFor - self.fadeIn - self.fadeOut) / totalTime;
double fadeInPercentage = self.fadeIn / totalTime;
double fadeOutPercentage = self.fadeOut / totalTime;
NSLog(#"Played: %f Wait: %f Play: %f Fade In: %f Fade Out: %f", playedPercentage, waitPercentage, playForPercentage, fadeInPercentage, fadeOutPercentage);
if (playedPercentage <= waitPercentage) {
waitPercentage = playedPercentage;
playForPercentage = 0;
fadeInPercentage = 0;
fadeOutPercentage = 0;
} else if (playedPercentage <= waitPercentage+fadeInPercentage) {
playForPercentage = 0;
fadeInPercentage = playedPercentage - waitPercentage;
fadeOutPercentage = 0;
} else if (playedPercentage <= waitPercentage+fadeInPercentage + playForPercentage) {
playForPercentage = playedPercentage - waitPercentage - fadeInPercentage;
fadeOutPercentage = 0;
} else {
fadeOutPercentage = playedPercentage - waitPercentage - playForPercentage;
}
//[self drawBackground:rect];
CGRect blueRect = CGRectMake((waitPercentage+fadeInPercentage)*rect.size.width, 0, playForPercentage*rect.size.width, rect.size.height);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextFillRect(context, blueRect);
CGRect greenRect = CGRectMake(0, 0, waitPercentage*rect.size.width, rect.size.height);
CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 1.0);
CGContextFillRect(context, greenRect);
CGRect purpleRect = CGRectMake(waitPercentage*rect.size.width+.1, 0, fadeInPercentage*rect.size.width, rect.size.height);
CGContextSetRGBFillColor(context, 0.33, 0.1, .55, 1.0);
CGContextFillRect(context, purpleRect);
CGRect purpleR = CGRectMake((1.0 - fadeOutPercentage)*rect.size.width - .5, 0, fadeOutPercentage*rect.size.width + .5, rect.size.height);
CGContextFillRect(context, purpleR);
}
Most UIKit use needs to be done on the main thread. Most likely your updateBarAt: method isn't being called on the main thread which means your call to setNeedsDisplay is being done on some background thread.
One possible solution would be this:
- (void)updateBarAt:(float)playHead {
self.playHead = playHead;
NSLog(#"%f", self.playHead);
dispatch_async(dispatch_get_main_queue(), ^{
[self setNeedsDisplay];
});
}
Another option would be to wrap the call to updateBarAt: in the dispatch_async call.
I write a msg background in tableviewcell, but when scrolling, the view become different. seems like the "context" store some state.
The code draw a round rect with a arrow.The arrow size should be fixed,but in fact it will change sometimes then scrolling.
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
CGFloat arrowHeight = 10;
CGFloat arrowWidth = 5;
CGFloat arrowOffset = 5;
CGFloat radius = 5;
CGFloat shadowHeight = 2;
CGFloat shadowOffset = 4;
CGColorRef shadowColor = [UIColor colorWithRed:0.2f
green:0.2f
blue:0.2f
alpha:0.5f].CGColor;
CGColorRef color;
color = [UIColor whiteColor].CGColor;
CGContextSaveGState(context);
CGContextMoveToPoint(context, width/2, 0);
CGContextAddArcToPoint(context, width - arrowWidth, 0, width - arrowWidth, height - shadowOffset, radius);
CGContextAddLineToPoint(context, width - arrowWidth, arrowOffset);
CGContextAddLineToPoint(context, width, arrowOffset + arrowHeight/2);
CGContextAddLineToPoint(context, width - arrowWidth, arrowOffset + arrowHeight);
CGContextAddArcToPoint(context, width - arrowWidth, height - shadowOffset, shadowOffset, height - shadowOffset, radius);
CGContextAddArcToPoint(context, shadowOffset, height - shadowOffset, shadowOffset, 0, radius);
CGContextAddArcToPoint(context, shadowOffset, 0, width, 0, radius);
CGContextSetShadowWithColor(context, CGSizeMake(0, shadowHeight), 3.0, shadowColor);
CGContextSetFillColorWithColor(context, color);
CGContextFillPath(context);
CGContextRestoreGState(context);
}
the effect like this:
I find the problem. the view should redraw when cell is reused,or the view will use the view in last cell to show.
so, just call [theView setNeedsDisplay] to let the view call drawRect again.
I want to make UIView which is originally rectangular to Hexagon shape to be used in my application.
Please help me something on this.
Thanks in advance.
Subclass UView and override drawRect to draw a hexagon like so:
- (void)drawRect:(CGRect)rect
{
float polySize = 60; // change this
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGAffineTransform t0 = CGContextGetCTM(context);
t0 = CGAffineTransformInvert(t0);
CGContextConcatCTM(context, t0);
//Begin drawing setup
CGContextBeginPath(context);
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
CGContextSetLineWidth(context, 2.0);
CGPoint center;
//Start drawing polygon
center = CGPointMake(160, 90.0);
CGContextMoveToPoint(context, center.x, center.y + polySize);
for(int i = 1; i < 6; ++i)
{
CGFloat x = polySize * sinf(i * 2.0 * M_PI / 6);
CGFloat y = polySize * cosf(i * 2.0 * M_PI / 6);
CGContextAddLineToPoint(context, center.x + x, center.y + y);
}
//Finish Drawing
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathStroke);
CGContextRestoreGState(context);
}
You can create a subclass of UIView and in it's -(void)drawRect: method draw a hexagon. Or Use UIImageView with image of hexagon
I want to draw a gradient inside a polygon using core graphics. I am able to draw a hexagon using the code below but i don't know how to fill this hexagon with a gradient color. Any help will be really appreciated.
- (void)drawRect:(CGRect)rect
{
// Drawing code.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 2.0);
CGPoint center;
center = CGPointMake(210.0, 90.0);
CGContextMoveToPoint(context, center.x, center.y + 60.0);
for(int i = 1; i < 6; ++i)
{
CGFloat x = 60.0 * sinf(i * 2.0 * M_PI / 6.0);
CGFloat y = 60.0 * cosf(i * 2.0 * M_PI / 6.0);
CGContextAddLineToPoint(context, center.x + x, center.y + y);
}
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
}
Use following code for Gradient fill
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
CGFloat colors[] =
{
0.62890625, 0.859375, 10.9921875, 1.00,
0.65625, 0.8046875, 0.9453125, 1.00,
};
CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4));
CGColorSpaceRelease(rgb);
// now we can actually create the shape and fill it
CGPoint start, end;
CGContextSetRGBFillColor(context, 0, 0, 0.6, 0.1);
CGContextFillEllipseInRect(context, CGRectMake(0.0, 0.0, 100.0, 100.0));
CGContextStrokeEllipseInRect(context, CGRectMake(0.0, 0.0, 100.0, 100.0));
// Gradient
CGRect myrect = CGRectMake(0.0, 0.0, rect.size.width, rect.size.height);
CGContextSaveGState(context);
CGContextClipToRect(context, myrect);
start = CGPointMake(myrect.origin.x, myrect.origin.y + myrect.size.height * 0.25);
end = CGPointMake(myrect.origin.x, myrect.origin.y + myrect.size.height * 1.0);
CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation);
CGContextRestoreGState(context);
I'm trying to recreate the look of a UINavigationBar. The background of the bar is drawn using a gradient, but it's unclear exactly what the default colors and points are in it. Has anyone done anything in this area?
From one of my projects. Adjust the colors to your liking. It also can show a background image if you want (imageReady), else it draws the navbar like Apple's
// #Lighter r,g,b,a #Darker r,g,b,a
#define MAIN_COLOR_COMPONENTS { 0.153, 0.306, 0.553, 1.0, 0.122, 0.247, 0.482, 1.0 }
#define LIGHT_COLOR_COMPONENTS { 0.478, 0.573, 0.725, 1.0, 0.216, 0.357, 0.584, 1.0 }
#implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
if (imageReady) {
UIImage *img = [UIImage imageNamed: #"navigation_background.png"];
[img drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
} else {
// Render yourself instead.
// You will need to adjust the MAIN_COLOR_COMPONENTS and LIGHT_COLOR_COMPONENTS to match your app
// emulate the tint colored bar
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat locations[2] = { 0.0, 1.0 };
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
CGFloat topComponents[8] = LIGHT_COLOR_COMPONENTS;
CGGradientRef topGradient = CGGradientCreateWithColorComponents(myColorspace, topComponents, locations, 2);
CGContextDrawLinearGradient(context, topGradient, CGPointMake(0, 0), CGPointMake(0,self.frame.size.height/2), 0);
CGGradientRelease(topGradient);
CGFloat botComponents[8] = MAIN_COLOR_COMPONENTS;
CGGradientRef botGradient = CGGradientCreateWithColorComponents(myColorspace, botComponents, locations, 2);
CGContextDrawLinearGradient(context, botGradient,
CGPointMake(0,self.frame.size.height/2), CGPointMake(0, self.frame.size.height), 0);
CGGradientRelease(botGradient);
CGColorSpaceRelease(myColorspace);
// top Line
CGContextSetRGBStrokeColor(context, 1, 1, 1, 1.0);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, self.frame.size.width, 0);
CGContextStrokePath(context);
// bottom line
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1.0);
CGContextMoveToPoint(context, 0, self.frame.size.height);
CGContextAddLineToPoint(context, self.frame.size.width, self.frame.size.height);
CGContextStrokePath(context);
}
}
#end