0

I'm having trouble drawing atop an image in a UIImageView, I've already looked at "Draw another image on a UIImage" But it was only so much help. Here's my scenario: I have a UIPopoverController with a UITableView in it and I want to display a triangle pointing up when the user is at the bottom of scrollable table view.

My code:

- (UIImage *) drawTriangleInViewForSize:(CGSize)sizeOfView
                     imageToDrawOn:(UIImage *)underImage
                           isAtTop:(BOOL)top{
CGPoint firstPoint;
CGPoint secondPoint;
CGPoint thirdPoint;

if(!top){
 //I want to draw a equilateral triangle (side length 10) in the center of the image in
 //the imageView, these are the coordinates I am using.
    firstPoint = CGPointMake(underImage.size.width * 0.5 + 5, underImage.size.height * 0.5 - 5);
    secondPoint = CGPointMake((firstPoint.x - 10), firstPoint.y);
    thirdPoint = CGPointMake(underImage.size.width * 0.5,
                             underImage.size.width * 0.5 + 5);

}
*/
**DISREGARD**
else{
    firstPoint = CGPointMake(sizeOfView.width * 0.5 + 5,
                             self.tableViewChoices.rowHeight * 0.5 - 5);
    secondPoint = CGPointMake((firstPoint.x - 10), firstPoint.y);
    thirdPoint = CGPointMake(sizeOfView.width * 0.5,
                             self.tableViewChoices.rowHeight * 0.5 + 5);
}*/
//get the size of the image for the drawInRect: method
CGFloat imageViewWidth = sizeOfView.width;
CGFloat imageViewHeight = self.tableViewChoices.rowHeight;

//set the graphics context to be the size of the image
UIGraphicsBeginImageContextWithOptions(underImage.size, YES, 0.0);

[underImage drawInRect:CGRectMake(0.0, 0.0, imageViewWidth, imageViewHeight)];

//set the line attributes
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(ctx, [UIColor blackColor].CGColor);
CGContextSetFillColorWithColor(ctx, [UIColor clearColor].CGColor);
CGContextSetLineWidth(ctx, 0.05);

UIGraphicsPushContext(ctx);
    //draw the triangle
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, firstPoint.x, firstPoint.y);
CGContextAddLineToPoint(ctx, secondPoint.x, secondPoint.y);
CGContextAddLineToPoint(ctx, thirdPoint.x, thirdPoint.y);
CGContextAddLineToPoint(ctx, firstPoint.x, firstPoint.y);
CGContextClosePath(ctx);

UIGraphicsPopContext();

//get the image
UIImage *rslt = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return rslt;
}

I can't quite seem to draw to the triangle to the UIImage in the imageView, the end result is either a completely black ImageView (the UIImage is just a white.png), or one line at the top of the imageview (depending on whether I use drawInRect: or drawAtPoint: and what coordinates I use). All I need to do is draw a triangle pointing up, not a hard thing, and it really looks like I'm doing it "by the book."

Community
  • 1
  • 1
Sakiboy
  • 7,252
  • 7
  • 52
  • 69
  • I'm not sure, but I think you'd have to put the triangle in it's own view and add it to the imageView. – Jamie Jul 22 '13 at 06:05

2 Answers2

2

Here is my completed code to draw a triangle onto a UIImage in a UIImageView.

//draws triangle up or down on a UIImage.
+(UIImage *) drawTriangleInViewForSize:(CGSize)sizeOfView
                     imageToDrawOn:(UIImage *)underImage
                           isAtTop:(BOOL)top
{
CGFloat rowHeight = underImage.size.height; //44; //self.tableViewChoices.rowHeight;
CGPoint firstPoint;
CGPoint secondPoint;
CGPoint thirdPoint;

CGFloat imageViewWidth = sizeOfView.width;
CGFloat imageViewHeight = rowHeight;


if(!top){
    //draw a upward facing triangle in the center of the view.
    firstPoint = CGPointMake(imageViewWidth * 0.5 + 15, imageViewHeight * 0.5 - 5);
    secondPoint = CGPointMake((firstPoint.x - 30), firstPoint.y);
    thirdPoint = CGPointMake(imageViewWidth * 0.5,
                             imageViewHeight * 0.5 + 5);

}else{
    //disregard this 'else'
    firstPoint = CGPointMake(sizeOfView.width * 0.5 + 15,
                             rowHeight * 0.5 - 5);
    secondPoint = CGPointMake((firstPoint.x - 10), firstPoint.y);
    thirdPoint = CGPointMake(sizeOfView.width * 0.5,
                             rowHeight * 0.5 + 5);

}


//get the image context with options(recommended funct to use)
//get the size of the imageView
UIGraphicsBeginImageContextWithOptions(CGSizeMake(imageViewWidth, imageViewHeight), YES, 0.0);

//use the the image that is going to be drawn on as the receiver
[underImage drawInRect:CGRectMake(0.0, 0.0, imageViewWidth, imageViewHeight)];



CGContextRef ctx = UIGraphicsGetCurrentContext();

CGContextSetLineWidth(ctx, 0.5);

//UIGraphicsPushContext(ctx);

//uses path ref
CGMutablePathRef path = CGPathCreateMutable();
//draw the triangle
CGPathMoveToPoint(path, NULL, firstPoint.x, firstPoint.y);
CGPathAddLineToPoint(path, NULL, secondPoint.x, secondPoint.y);
CGPathAddLineToPoint(path, NULL, thirdPoint.x, thirdPoint.y);
CGPathAddLineToPoint(path, NULL, firstPoint.x, firstPoint.y);
//close the path
CGPathCloseSubpath(path);
//add the path to the context
CGContextAddPath(ctx, path);
CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGContextSetStrokeColorWithColor(ctx, [UIColor blackColor].CGColor);
CGContextFillPath(ctx);
CGContextAddPath(ctx, path);
CGContextStrokePath(ctx);
CGPathRelease(path);

//UIGraphicsPopContext();

//get the new image with the triangle
UIImage *rslt = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return rslt;

}
Chris Spittles
  • 15,023
  • 10
  • 61
  • 85
Sakiboy
  • 7,252
  • 7
  • 52
  • 69
1

Your code looks too complicated for that kind of task. Why don't you use simple UIImageView with any triangle image you ever want? Just show it when the table at the bottom and that's all.

Note, that when you're implementing delegate for UITableView you're also able to catch it's UIScrollView's delegate messages such as scrollView:didEndDecelerating: and so on.

Regarding your code you've missed an actual path draw:

CGContextAddPath(context, trianglePath);
CGContextFillPath(context);

To make it possible you should use path-related functions. Using CGContext-related functions seems to be improper since such approach may remove old path. So the better way is to create your own mutable path in the context, draw your triangle in it and then draw this path into context by functions mentioned above.

Andrei Chevozerov
  • 1,029
  • 1
  • 10
  • 24
  • Could you explain how to use 'CGContextAddPath(context,trianglePath);'?? In the few times I've had to draw using CGContext operations I never used 'CGContextAddPath()' (I only have experience drawing lines and rectangles to a pdf with CGContext..). Thank you for your response, if I can't get this to work then I will just add a simple triangle.png to my imageView. I just want some experience with CG drawing. – Sakiboy Jul 22 '13 at 20:13
  • I now see how to use CGContextAddPath() , and realize that I had forgotten to add "CGContextDrawPath(ctx, kCGPathFillStroke);" in my code also... Thank you for your answer. – Sakiboy Jul 22 '13 at 20:43