Draw line in UITextView - iphone

I want to draw line in my UITextView. After some research I found this:
UITextView ruled line background but wrong line height
I tried in my code, drawRect is called but no line is drawn.. Someone could help me out here ?
#import "FacebookViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface MyViewController (){
UITextView *text;
}
#end
#implementation MyViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Do any additionnal customisation
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
text.contentMode = UIViewContentModeRedraw;
//TextView init
text = [[UITextView alloc]initWithFrame:CGRectMake(0,44,320,380)];
[self.view addSubview:text];
text.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)drawRect:(CGRect)rect {
NSLog(#"TEST");
//Get the current drawing context
CGContextRef context = UIGraphicsGetCurrentContext();
//Set the line color and width
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetLineWidth(context, 1.0f);
//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 = (text.contentSize.height + text.bounds.size.height) / text.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, text.bounds.origin.x, text.font.leading*x + 0.5f + baselineOffset);
CGContextAddLineToPoint(context, text.bounds.size.width, text.font.leading*x + 0.5f + baselineOffset);
}
CGContextClosePath(context);
CGContextStrokePath(context);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[text setNeedsDisplay];
}
#end
Probably a silly mistake but I can't find it out
Thanks

As i looked to you code everything is ok with it. Maybe there is something with color? May be it is the same as background color or something like this.
May be you forgot to set content mode:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.contentMode = UIViewContentModeRedraw;
}
return self;
}
EDIT:
I think i know:
You forgot to set [myTextView setNeedsDisplay]; after showing it. Read here
EDIT:
First you create your view:
t = [[[MyTextView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)] autorelease];
[self.view addSubview:t];
t.delegate = self;
Make your viewcontroller implement UITextViewDelegate and after that
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[t setNeedsDisplay];
}
This should work

I have same problem ..
As i think you are not subclassing from UITextView
As UIViewController does not implement this method only UITextView did
So just subclass it .. you code will work

Is it possible that you're drawing successfully but getting obscured by a matching background color? I notice that the alpha on the color you've chosen is pretty small. If only to rule this out, change:
CGContextSetStrokeColorWithColor(context, [UIColor colorWithWhite:0.5f alpha:0.15f].CGColor);
to
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);

Related

how to increase and decrease circle size in uislider with value change

I want to increase and decrease a circle size in uislider with value change..
here my code
draw.m
- (id)initWithFrame:(CGRect)frame value:(float )x
{
value=x;
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
- (void)drawRect:(CGRect)rect{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGRect rectangle = CGRectMake(6,17,value,value);
CGContextAddEllipseInRect(context, rectangle);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillPath(context);
}
and ViewController.m
#implementation ViewController
#synthesize mySlider,colorLabel;
- (void)viewDidLoad
{ [super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)sliderValue:(UISlider*)sender
{
float r=[[NSString stringWithFormat:#"%.0f",mySlider.value] floatValue];
NSLog(#"value...%f",r);
CGRect positionFrame = CGRectMake(10,100,200,100);
circle = [[draw alloc] initWithFrame:positionFrame value:r];
circle.backgroundColor=[UIColor clearColor];
[self.view addSubview:circle];
}
in this code, circle size has increase but not decrease and another problem is circle look ,
output is .
Ok, your code works, it just doesn't look like it. Add
[circle removeFromSuperview];
circle = nil;
right above
circle = [[draw alloc] initWithFrame:positionFrame value:r];
You keep drawing new circles on top of the previous ones so it takes that odd shape and also doesn't look like it's decreasing.
EDIT
To redraw your circle instead of creating a new one everytime, as #Larme pointed out, you would have to change your 'draw' object to contain a public method which reassigns your 'draw' circle objects diameter.
-(void) setDiameterWithFloat: (float)x{
value = x;
}
Then in your sliderValue IBAction, call this new method to assign the new diameter based on your slider and redraw the circle with setNeedsDisplay:
[circle setDiameterWithFloat:mySlider.value];
[circle setNeedsDisplay];
This allows you to move your initialization of the object to viewDidLoad in your ViewController, where it will be created and loaded only one time along with the rest of the view.

textview cursor position changed after horizontal line

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.

Subclassing UIView in a map to draw lines

I have an app that displays custom maps. I use a CATiledView to display the maps.
I would like to be able to draw a route over the top of the maps. To do this, I am creating a UIView then adding it to the scrollView after I add the tiling layer like this:
- (void)displayTiledImageNamed:(NSString *)imageName size:(CGSize)imageSize
{
// clear the previous imageView
[imageView removeFromSuperview];
[imageView release];
imageView = nil;
[linesView removeFromSuperview];
[linesView release];
linesView = nil;
// reset our zoomScale to 1.0 before doing any further calculations
self.zoomScale = 1.0;
// make a new TilingView for the new image
imageView = [[TilingView alloc] initWithImageName:imageName size:imageSize];
linesView = [[LinesView alloc]initWithImageName:imageName size:imageSize];
linesView.backgroundColor = [UIColor clearColor];
[self addSubview:imageView];
[self addSubview:linesView];
[self configureForImageSize:imageSize];
}
The problem, is the line that I create in linesView is not scaling correctly.
It's hard to describe, but the line that is being created is scaled as if it were drawn on the device itself, rather than drawn on the map. See the following code:
#import "LinesView.h"
#implementation LinesView
#synthesize imageName;
- (id)initWithImageName:(NSString *)name size:(CGSize)size
{
if ((self = [super initWithFrame:CGRectMake(0, 0, size.width, size.height)])) {
self.imageName = name;
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
CGContextSetLineWidth(context, 20.0);
CGContextMoveToPoint(context, 1.0f, 220.0f);
CGContextAddLineToPoint(context, 340.0f, 80);
CGContextStrokePath(context);
}
#end
I have tried putting the code to draw the line in the drawRect method of the tilingView and it works perfectly. The line width is 20px relative to the map. In the linesView the line appears to be 20px wide relative to the device and positioned relative to the scrollview.
Sorry I'm trying my best to describe the problem...
Figured this out - I added the linesView to the tilingView instead of the scrollView like this:
- (void)displayTiledImageNamed:(NSString *)imageName size:(CGSize)imageSize
{
// clear the previous imageView
[imageView removeFromSuperview];
[imageView release];
imageView = nil;
[linesView removeFromSuperview];
[linesView release];
linesView = nil;
// reset our zoomScale to 1.0 before doing any further calculations
self.zoomScale = 1.0;
// make a new TilingView for the new image
imageView = [[TilingView alloc] initWithImageName:imageName size:imageSize];
linesView = [[LinesView alloc]initWithImageName:imageName size:imageSize];
linesView.backgroundColor = [UIColor clearColor];
[self addSubview:imageView];
[imageView addSubview:linesView];
[self configureForImageSize:imageSize];
}

UITextView ruled line background but wrong line height

I have a UITextView where the user can create notes and save into a plist file.
I want to be able to show lines just like a normal notebook. The problem I have is
that the text won't align properly.
The image below explains the problem quite well.
This is the background I use to create the lines like the Notes.app
This is my code for creating the background for my UITextView:
textView.font = [UIFont fontWithName:#"MarkerFelt-Thin" size:19.0];
textView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: #"Notes.png"]];
I know that the UIFont.lineHeight property is only available in > iOS 4.x.
So I wonder if there is another solution to my problem?
You should try and draw your lines programmatically rather than using an image. Here's some sample code of how you could accomplish that. You can subclass UITextView and override it's drawRect: method.
NoteView.h
#import <UIKit/UIKit.h>
#interface NoteView : UITextView <UITextViewDelegate> {
}
#end
NoteView.m
#import "NoteView.h"
#implementation NoteView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor colorWithRed:1.0f green:1.0f blue:0.6f alpha:1.0f];
self.font = [UIFont fontWithName:#"MarkerFelt-Thin" size:19];
}
return self;
}
- (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);
CGContextSetLineWidth(context, 1.0f);
//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);
}
#end
MyViewController.h
#import <UIKit/UIKit.h>
#import "NoteView.h"
#interface MyViewController : UIViewController <UITextViewDelegate> {
NoteView *note;
}
#property (nonatomic, retain) NoteView *note;
#end
MyViewController.m
#import "MyViewController.h"
#import "NoteView.h"
#define KEYBOARD_HEIGHT 216
#implementation MyViewController
#synthesize note;
- (void)loadView {
[super loadView];
self.note = [[[NoteView alloc] initWithFrame:self.view.bounds] autorelease];
[self.view addSubview:note];
note.delegate = self;
note.text = #"This is the first line.\nThis is the second line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\n";
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[note setNeedsDisplay];
}
- (void)textViewDidBeginEditing:(UITextView *)textView {
CGRect frame = self.view.bounds;
frame.size.height -= KEYBOARD_HEIGHT;
note.frame = frame;
}
- (void)textViewDidEndEditing:(UITextView *)textView {
note.frame = self.view.bounds;
}
- (void)dealloc {
[note release];
[super dealloc];
}
Take a look at Apple's documentation for Managing the Keyboard, specifically "Moving Content That Is Located Under the Keyboard". It explains how to listen for NSNotifcations and adjust your views properly.
I think the problem is with your image, the yellow space over the line is creating the problem.
You should edit the image.
And nice work.

How to make a subview tint a portion of the screen on the iPhone?

I would like to write a UIView subclass that, among other things, colors whatever's underneath it a certain color. This is what I've come up with, but it unfortunately doesn't seem to work correctly:
#import <UIKit/UIKit.h>
#class MyOtherView;
#interface MyView : UIView
{
MyOtherView *subview;
}
#end
#implementation MyView
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
frame.origin.x += 100.0;
frame.origin.y += 100.0;
frame.size.width = frame.size.height = 200.0;
subview = [[MyOtherView alloc] initWithFrame:frame];
[self addSubview:subview];
[subview release];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
// Draw a background to test out on
UIImage *image = [UIImage imageNamed:#"somepic.png"];
[image drawAtPoint:rect.origin];
const CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blueColor] setFill];
rect.size.width = rect.size.height = 200.0;
CGContextFillRect(ctx, rect);
}
#end
#interface MyOtherView : UIView
#end
#implementation MyOtherView
- (void)drawRect:(CGRect)rect
{
// This should tint "MyView" but it doesn't.
const CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextSetBlendMode(ctx, kCGBlendModeScreen);
[[UIColor redColor] setFill];
CGContextFillRect(ctx, rect);
CGContextRestoreGState(ctx);
}
#end
I want "MyOtherView" to color "MyView" red where it overlaps, but instead it just draws an opaque red block onto it. However, this seems work fine if I copy the -drawRect: function from "MyOtherView" and append it to the one in "MyView" (this took me quite a headache to finally realize). Anyone know what I'm doing wrong? Is it even possible to do this, or should I be approaching it differently?
I think you're over-thinking this. Overlay one view over the other, and set the alpha of the top view to 0.5. You will also need to set opaque to NO.
If you set the background color of the view appropriately, you won't even need to override drawRect.
Might want to check out this SO question.