Can anyone help me with this. I need to do custom drawing code in -drawRect so I subclassed UIImage. How would I initialize my custom UIImage with an image? Say I override the imageName method, what would I need to do in this method? After initializing can I add it to a UIImageview like so initwithImage:?
If you're going to do custom drawing, don't subclass UIImage, subclass UIView, and add your subclass view to wherever you want the custom drawing to be. Do all of your drawing directly in the -drawRect: method of UIView. An example of how to draw a diagonal blue line:
-(void) drawRect:(CGRect)rect {
CGContextRef g = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(g,self.frame.origin.x,self.frame.origin.y);
[[UIColor blueColor] setStroke];
CGContextAddLineToPoint(g,CGRectGetMaxX(self.frame),CGRectGetMaxY(self.frame));
}
Related
The UITableView I am using has a custom UItableViewCell. This custom cell has a subview (an UIView subclass) to it. I use the drawRect of the custom UIView subclass to place all the text to be displayed by the cell.
And in the drawRect (of UIView subclass) I do the following
/*
// This piece of code is called when setNeedsDisplay is called
*/
- (void)drawRect:(CGRect)rect
{
self.layer.cornerRadius = 10.0f;
self.layer.backgroundColor = [[UIColor orangeColor] CGColor];
self.layer.borderColor = [[UIColor lightGrayColor] CGColor];
self.layer.borderWidth = 3.0f;
}
However my custom cell is a black square like this
But I do see the intended behavior if I select the row. Like shown below
Whats going on ?
Your drawRect: method does not draw anything; the code that you put in there belongs in your initWithFrame: implementation.
You should manipulate the layer configuration in the initializer; in your drawRect: you should call functions of your CGContextRef based on the state of the view. For example, to draw some text you would use CGContextShowTextAtPoint, to draw some lines you would use CGContextAddLineToPoint, and so on.
See this question for information on the relationship between drawRect: and the CALayer of your UIView.
Try to set self.layer.masksToBounds = YES and (maybe) self.opaque = NO during your UIView's (the one where drawRect is overridden) initialization. (see this question)
Try to disable the selection highlight of the cell by using
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
You are doing one mistake:
Please go to the view in side the UItableViewCell and check the background color it may be black or something others, Reset it to clear color then check your result,
I have UIView that contain a pin image and a label, as we know UIView is rectangle so if I convert UIView to UIImage,UIImage is also rectangle, I want make UIImage like the a pin image because if user click a background, UIImage's event will be called too.. I want to convert UIView to UIImage without it's background, how can it be?
I use this method to change UIView to UIImage
-(UIImage *) ChangeViewToImage : (UIView *) view{
UIGraphicsBeginImageContext(view.bounds.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Hmm.. example like this, I have a rectangle as a UIView and a triangle as a shape in UIView. and then I want to make this UIView become a UIImage, but I just want the triangle without background, so the image just a triangle.. how can I do It?
A UIImage is always rectangular. What you can play with is the opacity in your views. If you make everything except your pin image transparent, it will seem as if you just have an image of the pin.
Use:
view.backgroundColor = [UIColor clearColor];
to make your view's background transparent.
Could someone please explain to me how to draw a
string using UIStringDrawing instead of using a label? here is my code but for some reason it compiles and the screen is blank...
//
// MainViewController.m
// DotH
//
#define WINDOW_FRAME [[UIScreen mainScreen] bounds]
#define SCREEN_FRAME [UIScreen mainScreen].applicationFrame
#define GRAY [UIColor grayColor]
#define BLACK [UIColor blackColor]
#implementation MainViewController
- (void)loadView {
UIView *view = [[UIView alloc] initWithFrame:SCREEN_FRAME];
[view setBackgroundColor:GRAY];
[BLACK setFill];
NSString *string = #"Hey Dude!";
[string drawAtPoint:CGPointMake(50, 50) withFont:[UIFont systemFontOfSize:14]];
self.view = view;
[view release];
}
#end
The line
[string drawAtPoint:CGPointMake(50, 50) withFont:[UIFont systemFontOfSize:14]];
needs to be in the view's drawRect: method.
This is because just before drawRect: is called, the rectangle passed as an argument to drawRect: is erased. So if you try to do custom drawing anywhere other than a view's drawRect: method, the stuff you draw will get erased whenever drawRect: is called. (Not to mention that calling drawAtPoint: is meaningless if not done by code within a UIView.)
You will need to make a custom subclass of UIView, and that subclass will need a custom drawRect: method. If you still want the view controller to be the entity responsible for deciding what string should be drawn and how, you should give your UIView subclass a method like
- (void)addString:(NSString *)string atPoint:(CGPoint)point withFont:(UIFont *)font;
That method can store that information, in, e.g., three NSMutableArrays (one of strings, one of points, and one of fonts), and increment a counter of how many strings have been added. Then, your view's drawRect: method can draw the strings described in those arrays. To add a string, your view controller just calls addString:atPoint:withFont: on your view.
I have my very own minimal view class with this:
- (void) awakeFromNib
{
NSLog(#"awakeFromNib!");
[self.layer setDelegate:self];
[self.layer setFrame:CGRectMake(30, 30, 250, 250)];
self.layer.masksToBounds = YES;
self.layer.cornerRadius = 5.0;
self.layer.backgroundColor = [[UIColor redColor] CGColor];
[self setNeedsDisplay];
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
NSLog(#"drawing!");
}
drawLayer:inContext never get called, although I can see the layer as red, rounded corner rectangle. What am I missing?
EDIT: from Apple docs
You can draw content for your layer,
or better encapsulate setting the
layer’s content image by creating a
delegate class that implements one of
the following methods: displayLayer:
or drawLayer:inContext:.
Implementing a delegate method to draw
the content does not automatically
cause the layer to draw using that
implementation. Instead, you must
explicitly tell a layer instance to
re-cache the content, either by
sending it a setNeedsDisplay or
setNeedsDisplayInRect: message, or by
setting its needsDisplayOnBoundsChange
property to YES.
Also
drawLayer:inContext:
If defined, called by the default implementation
of drawInContext:.
You should never change the delegate of layer of a UIView. From documentation of UIView layer property:
Warning: Since the view is the layer’s
delegate, you should never set the
view as a delegate of another CALayer
object. Additionally, you should never
change the delegate of this layer.
If you want to do custom drawing in a view simply override the drawRect: method.
If you do want to use layers you need to create your own:
UIView *myView = ...
CALayer *myLayer = [CALayer layer];
myLayer.delegate = self;
[myView.layer addSublayer:myLayer];
In both cases you need to call setNeedsDisplay on the view in the first case and on your custom layer in the second. You never call drawRect: or drawLayer:inContext: directly, they are called automatically when you call setNeedsDisplay.
Use
[self.layer setNeedsDisplay];
instead of
[self setNeedsDisplay];
It is the view.layer, not the view
Must I also do all this crazy coordinate system conversion stuff here, or is an UILabel different from an UIImageView drawing in -drawRect: ?
There's a method called - (void)drawTextInRect:(CGRect)rect for that.
BUT the documentation says: "You should not call this method directly. This method should only be overridden by subclasses that want to modify the default drawing behavior for the label’s text."
So? How to draw it then in -drawRect:?
UILabel is different in that you don't need to manually draw text to alter the way it is presented. Subclassing UILabel and overriding -drawTextInRect: is the quickest way to alter the way a UILabel is rendered. For example,
- (void)drawTextInRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetShadowWithColor( context, shadowOffset, shadowRadius, [shadowColor CGColor] );
[super drawTextInRect:rect];
}
will add a shadow with a specific offset, radius, and color (as a UIColor instance) to any text that you draw in that UILabel. For an example of this in action, see a project I put together for a recent class.
However, if what you are looking to do is just draw text within another view, Vladimir's answer is the way to go.
If you perform custom drawing in your view you must not draw UILabel or another UI element but rather draw text itself. NSString has several methods for drawing in current context (look at NSString's UIKit extension docs for more methods):
- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font
- (CGSize)drawAtPoint:(CGPoint)point withFont:(UIFont *)font
Actually you can do it.
Try this:
UILabel *lblRef = [[UILabel alloc] initWithFrame:CGRectMake(x, y, width, height)];
lblRef.text = [refs objectAtIndex:barCount];
lblRef.adjustsFontSizeToFitWidth = TRUE;
lblRef.adjustsLetterSpacingToFitWidth = TRUE;
lblRef.textColor = self.color;
[lblRef setTextAlignment:NSTextAlignmentCenter];
lblRef.backgroundColor = [UIColor clearColor];
[self addSubview:lblRef];