I want to position a UILabel in the center of my Circle but I can't seem to affect the position of the label. I can only seem to affect the position of the label by changing the height of CGRect frame. changing the other values doesn't affect the position at all.
here's my Circle.m code
- (id)initWithFrame:(CGRect)frame radius:(CGFloat)aRadius color:(UIColor*) aColor {
self = [super initWithFrame:frame];
if (self) {
self.opaque = NO;
[self setRadius:aRadius];
[self setColor:aColor];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
NSString *string = #"1";
UIFont* font = [UIFont systemFontOfSize:80];
UILabel *label = [[UILabel alloc] init];
label.text = string;
label.textColor = [UIColor whiteColor];
label.font = font;
CGRect frame = label.frame;
frame = CGRectMake(10, 10, 0, 85);
label.frame = frame;
CGContextRef contextRef = UIGraphicsGetCurrentContext();
[color setFill];
circle = CGRectMake(0, 0, radius, radius);
CGContextAddEllipseInRect(contextRef, circle);
CGContextDrawPath (contextRef, kCGPathFill);
[label drawRect:circle];
}
and my viewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat radius = 70;
CGRect position = CGRectMake(0, 0, radius, radius);
Circle *myCircle = [[Circle alloc] initWithFrame:position radius:radius color:[UIColor redColor]];
[self.view addSubview:myCircle];
}
You should not be allocating new UIViews in drawRect: (and UILabel is a subclass of UIView). There are a few good ways of doing what you want, but none of them involve allocating a new UILabel in drawRect:.
One way is to make your Circle give itself a UILabel subview in its initializer, and center the label in layoutSubviews. Then in drawRect:, you just draw the circle and don't worry about drawing the label's text:
#implementation Circle {
UILabel *_label;
}
#synthesize radius = _radius;
#synthesize color = _color;
- (id)initWithFrame:(CGRect)frame radius:(CGFloat)aRadius color:(UIColor*) aColor {
self = [super initWithFrame:frame];
if (self) {
self.opaque = NO;
[self setRadius:aRadius];
[self setColor:aColor];
_label = [[UILabel alloc] init];
_label.font = [UIFont systemFontOfSize:80];
_label.textColor = [UIColor whiteColor];
_label.text = #"1";
[_label sizeToFit];
[self addSubview:_label];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGSize mySize = self.bounds.size;
_label.center = CGPointMake(mySize.width * 0.5f, mySize.height * 0.5f);
}
- (void)drawRect:(CGRect)rect {
[self.color setFill];
CGSize mySize = self.bounds.size;
CGFloat radius = self.radius;
[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(mySize.width * 0.5f, mySize.height * 0.5f, self.radius, self.radius)] fill];
}
Related
I want to change the cursor position in TextView...
// NoteView objective _c class its super class is TextView...
#import "NoteView.h"
#implementation NoteView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.backgroundColor =[UIColor whiteColor];
self.contentMode = UIViewContentModeRedraw;
self.font = [UIFont fontWithName:#"Helvetica Neue" size:14];
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
//Get the current drawing context
CGContextRef context = UIGraphicsGetCurrentContext();
//Set the line color and width
// CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.2f].CGColor);
CGContextSetStrokeColorWithColor(context,[UIColor colorWithRed:0.29804f green:0.12157f blue:0.9f alpha:0.1].CGColor);
//Start a new Path
CGContextBeginPath(context);
//Find the number of lines in our textView + add a bit more height to draw lines in the empty part of the view
NSUInteger numberOfLines = (self.contentSize.height + self.bounds.size.height) / self.font.leading;
//Set the line offset from the baseline. (I'm sure there's a concrete way to calculate this.)
CGFloat baselineOffset = 6.0f;
//iterate over numberOfLines and draw each line
for (int x = 0; x < numberOfLines; x++) {
//0.5f offset lines up line with pixel boundary
CGContextMoveToPoint(context, self.bounds.origin.x, self.font.leading*x + 0.5f + baselineOffset);
CGContextAddLineToPoint(context, self.bounds.size.width, self.font.leading*x + 0.5f + baselineOffset);
}
//Close our Path and Stroke (draw) it
CGContextClosePath(context);
CGContextStrokePath(context);
}
//its a view controller class and here i imported NotesView here
#import "NotesViewController.h"
#interface NotesViewController ()
#end
#implementation NotesViewController
// i load the textView frame whatever i created class above
- (void)loadView {
[super loadView];
CGSize result = [[UIScreen mainScreen] bounds].size;
CGFloat scale = [UIScreen mainScreen].scale;
result = CGSizeMake(result.width*scale, result.height * scale);
if (result.height==1136)
{
_TextView = [[NoteView alloc] initWithFrame:CGRectMake(29,50,266,430)];
backgroundView.frame=CGRectMake(10,32,300,450);
}
else
{
_TextView = [[NoteView alloc] initWithFrame:CGRectMake(29,50,266,340)];
backgroundView.frame=CGRectMake(10,32,300,360);
}
[self.view addSubview:_TextView];
_TextView.delegate = self;
UIView *lineView = [[UIView alloc]initWithFrame:CGRectMake(30,40,1,backgroundView.frame.size.height-5)];
lineView.backgroundColor = [UIColor brownColor];
lineView.alpha=0.3;
[self.view addSubview:lineView];
UIView *lineView1 = [[UIView alloc]initWithFrame:CGRectMake(32,40,1,backgroundView.frame.size.height-5)];
lineView1.backgroundColor = [UIColor brownColor];
lineView1.alpha=0.3;
[self.view addSubview:lineView1];
}
}
}
// in view did load i set the delegate and code for cursor position
- (void)viewDidLoad
{
[super viewDidLoad];
// setting delegate here
_TextView.delegate=self;
_TextView.editable = YES;
[_TextView setSelectedRange:NSMakeRange(10, 0)];
}
I write all the delegate methods for Textview and ScrollView of Textview I the cursor positon is starts the vertical line after.... I'm not expressed well please understand based on images... I want cursor position... I want to set my Textview with real note application in iPhone.. I add Textview to ViewController all works well but cursor stats starting position... I want to cursor position always horizontal line........ Try to give solution based on the images..
Do it like this image.
Here you have to set the position of your textview in your VC so it will come after the horizontal line.
I have seen this and this but it doesn't clear my doubt.
I have a custom imageView class, a subclass basically. where I need to add sub image views on a UIView at particular pixel values. When I draw these images using custom imageview (draw rect) my images are inverted.
Please help as to what is the change I need to do in my frame so that image is not inverted.
Below is the image.
CustomImageView.m
#implementation CustomImageView
#synthesize customImage;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
// Initialization code.
}
return self;
}
- (void)drawRect:(CGRect)rect{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, rect, customImage.CGImage);
[super drawRect:rect];
}
- (void)dealloc {
[customImage release];
[super dealloc];
}
#end
CustomImageView.h
#interface CustomImageView : UIView
{
}
#property(nonatomic,retain)UIImage *customImage;
#end
I am using this as below
-(void)drawArrowImagewithStartX:(CGFloat)X1 startY:(CGFloat)Y1 andEndX:(CGFloat)X2 endY:(CGFloat)Y2
{
CustomImageView *arrowImageView = [[CustomImageView alloc] initWithFrame:CGRectZero];
CGRect startPointFrame = CGRectZero;
CGRect endPointFrame = CGRectZero;
CGFloat arrowWidth = 0.0;
CGFloat arrowHeight = 0.0;
CGFloat y1 = -(Y1+194.0);
CGFloat y2 = -(Y1+194.0);
if (isMapZoomed) {
startPointFrame = CGRectMake(X1, Y1, 16.0, 16.0);
endPointFrame = CGRectMake(X2, Y2, 16.0, 16.0);
arrowWidth = 5.0;
arrowHeight = 25.0;
}
else {
startPointFrame = CGRectMake(X1, y1, 8.0, 8.0);
endPointFrame = CGRectMake(X2, y2, 8.0, 8.0);
arrowWidth = 10.0;
arrowHeight = 50.0;
}
CustomImageView *startImageView = [[CustomImageView alloc] initWithFrame:CGRectZero];
startImageView.frame = startPointFrame;
if (stepNo == 0)
startImageView.customImage = [UIImage imageNamed:KStartFlag];
else
startImageView.customImage = [UIImage imageNamed:KStartPoint];
CustomImageView *endImageView = [[CustomImageView alloc] initWithFrame:CGRectZero];
endImageView.frame = endPointFrame;
if (stepNo == ([self.allPOIDetailsArray count]-1))
endImageView.customImage = [UIImage imageNamed:KEndFlag];
else
endImageView.customImage = [UIImage imageNamed:KEndPoint];
if(X1 == X2){
if (y1 > y2){
arrowImageView.frame = CGRectMake(X2, (y1-(y1-y2)/2), arrowWidth, arrowHeight);
arrowImageView.customImage =[UIImage imageNamed:KArrowUp];
}
else{
arrowImageView.frame = CGRectMake(X1, (y1+(y2-y1)/2), 5.0, 25.0);
arrowImageView.customImage =[UIImage imageNamed:KArrowDown];
}
}
else {
if (X1 > X2) {
arrowImageView.frame = CGRectMake((X1-(X1-X2)/2), y2, 25.0, 5.0);
arrowImageView.customImage = [UIImage imageNamed:KArrowLeft];
}
else{
arrowImageView.frame = CGRectMake((X1+(X2-X1)/2), y1, 25.0, 5.0);
arrowImageView.customImage = [UIImage imageNamed:KArrowRight];
}
}
for(UIView *subvw in self.zoomingView.subviews)
if ([subvw isKindOfClass:[UIImageView class]]) {
for (UIView *subview in subvw.subviews)
[subview removeFromSuperview];
[subvw addSubview:startImageView];
[subvw addSubview:endImageView];
[subvw addSubview:arrowImageView];
NSLog(#"Subview frame %#",NSStringFromCGRect(subvw.frame));
NSLog(#"\n\nImage frame %# %#",NSStringFromCGRect(arrowImageView.frame),NSStringFromCGRect(startImageView.frame));
}
[arrowImageView release];
[startImageView release];
[endImageView release];
}
yes it is the normal behavior.
Uikit topleft corner coordinate (0,0)
OpenGL/CoreGraphics bottomleft coordinate (0,0)
and hence ur image appear to be inverted.
you can fix this by:
Moving origin up by the view's height.
Negate (multiply by -1)
the y axis.
Best of both worlds, use UIImage's drawAtPoint: or drawInRect: while still specifying your custom context:
UIGraphicsPushContext(context);
[image drawAtPoint:CGPointZero];
UIGraphicsPopContext();
Also you void modifying your context with CGContextTranslateCTM or CGContextScaleCTM.
I have been trying desperately to draw some images into a view. The view should be inside a scrollview. For that I subclassed UIScrollview and override the drawRect method in it. And added this as my UIView's subview.
#interface DrawAnotherViewClass : UIScrollView<UIScrollViewDelegate> {
}
#end
#implementation DrawAnotherViewClass
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
CGRect fullScreenRect=[[UIScreen mainScreen] applicationFrame];
self.frame = fullScreenRect;
self.contentSize = CGSizeMake(600, 600);
self.showsHorizontalScrollIndicator = YES;
self.showsVerticalScrollIndicator = NO;
self.pagingEnabled = YES;
}
return self;
}
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextMoveToPoint(context, 10.0f, 50.0f);
CGContextAddLineToPoint(context, 10.0f, 200.0f);
CGContextStrokePath(context);
CGContextMoveToPoint(context, 8.0f, 77.0f);
CGContextAddLineToPoint(context, 300.0f, 77.0f);
CGContextStrokePath(context);
CGContextSetRGBFillColor(context, 0, 0, 255, 0.1);
CGContextSetRGBStrokeColor(context, 0, 0, 255, 1);
CGContextStrokeEllipseInRect(context, CGRectMake(65.0, 33.5, 25, 25));
UIImage *image1 = [UIImage imageNamed:#"PinDown1.png"];
UIImage *image2 = [UIImage imageNamed:#"pinGreen_v1.png"];
CGPoint drawPoint = CGPointMake(0.0f, 10.0f);
[image2 drawAtPoint:drawPoint];
for(int i =1; i<20; i++){
CGPoint drawPointOne = CGPointMake(40.0f * i, 40.0f);
[image1 drawAtPoint:drawPointOne];
}
}
Am I missing something here. Is this the right way to go.
If the view that should perform the drawing resides in that UIScrollView, you have to put the - (void)drawRect:(CGRect)rect method into that view's class method and not into the UIScrollView subclass.
I am trying to animate my UIImageView so that it animates from height x to height y and I have the following code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.test = [self createNewBarWithValue:800 atLocation:CGPointMake(107, 43)];
}
- (UIImageView*)createNewBarWithValue:(float)percent atLocation:(CGPoint)location
{
UIImageView *newBar = [[[UIImageView alloc] initWithFrame:CGRectMake(location.x, location.y, 107, 43)] autorelease];
newBar.image = [UIImage imageNamed:#"bar.png"];
CABasicAnimation *scaleToValue = [CABasicAnimation animationWithKeyPath:#"transform.scale.y"];
scaleToValue.toValue = [NSNumber numberWithFloat:percent];
scaleToValue.fromValue = [NSNumber numberWithFloat:0];
scaleToValue.duration = 1.0f;
scaleToValue.delegate = self;
newBar.layer.anchorPoint = CGPointMake(0.5, 1);
[newBar.layer addAnimation:scaleToValue forKey:#"scaleUp"];
CGAffineTransform scaleTo = CGAffineTransformMakeScale( 1.0f, percent );
newBar.transform = scaleTo;
return newBar;
}
However, I am not seeing anything here. What am I missing?
It doesn't appear you add the UIImageView to your view controller's view.
e.x.
[self.view addSubview:test];
Edit: It seems that the origin point's components are been multiplied by 2 when drawing the PDF page. Is something I'm doing causing this?
I have a UIViewController that displays a PDF page on a UIScrollView. the PDF page itself is drawn on a CATiledLayer, however, when my view controller draws the layer there is a considerable offset between the layer's bounds and the drawn PDF. As you can see in the picture, the page should have been drawn on the yellow view:
Here is the relevant code that draws the page:
- (void)refreshPage
{
if(contentView) {
for(UIView *v in self.view.subviews) {
[v removeFromSuperview];
[v release];
}
}
CGRect pageRect = CGRectIntegral(CGPDFPageGetBoxRect(self._document.page, kCGPDFCropBox));
pageRect.origin.x = ((self.view.frame.size.width / 2) - (pageRect.size.width / 2));
CATiledLayer *tiledLayer = [CATiledLayer layer];
tiledLayer.delegate = self;
tiledLayer.tileSize = CGSizeMake(1024.0, 1024.0);
tiledLayer.levelsOfDetail = 1000;
tiledLayer.levelsOfDetailBias = 1000;
tiledLayer.frame = pageRect;
contentView = [[UIView alloc] initWithFrame:pageRect];
[contentView.layer addSublayer:tiledLayer];
CGRect viewFrame = self.view.frame;
viewFrame.origin = CGPointZero;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:viewFrame];
//[scrollView setBackgroundColor:[UIColor cyanColor]];
//[contentView setBackgroundColor:[UIColor yellowColor]];
scrollView.delegate = self;
scrollView.contentSize = pageRect.size;
scrollView.maximumZoomScale = 1000;
[scrollView addSubview:contentView];
[self.view addSubview:scrollView];
pagingViewController = [[PDFPagingViewController alloc] initWithDocument:self._document AndObserver:self];
[self.view addSubview:pagingViewController.view];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return contentView;
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
if(self._document) {
[layer setBackgroundColor:(CGColorRef)[UIColor redColor]];
CGRect drawingRect = CGContextGetClipBoundingBox(ctx);
CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(ctx, drawingRect);
CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(self._document.page, kCGPDFCropBox, layer.bounds, 0, true));
CGContextDrawPDFPage(ctx, self._document.page);
}
}
You need to change when you set the pageRect's origin (which I assume you do to center in the view). You are setting both the layer's frame and the contentView's frame to the offset pageRect when you really intend to offset only one.
-(void)refreshPage {
//...
CGRect pageRect = CGRectIntegral(CGPDFPageGetBoxRect(self._document.page, kCGPDFCropBox));
CATiledLayer *tiledLayer = [CATiledLayer layer];
//...
tiledLayer.frame = pageRect;
// set the pageRect origin now to center the contentView, not the layer
pageRect.origin.x = ((self.view.frame.size.width / 2) - (pageRect.size.width / 2));
contentView = [[UIView alloc] initWithFrame:pageRect];
[contentView.layer addSublayer:tiledLayer];
//...
}