Subclassing UIView in a map to draw lines - iphone

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];
}

Related

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.

custom uiscrollview doesn't scroll (using coretext)

I am using CoreText to draw text in multiple columns (depending on the orientation of the iPad).
To test, I've created an NSMutableString composed of the numbers 100 - 999. This text spans 5 columns, 1 or 2 of which are onscreen (depending on the orientation).
To my main ViewController I've added a custom UIScrollView to hold this text, and I want it to be scrollable.
I've noticed that the scrollview doesn't scroll until I set:
[myScrollView setContentMode:UIViewContentModeRedraw];
I do want the scrollView to call drawRect when the iPad is rotated (to adjust the number of columns)!
My issue with this though is that it seems to call drawRect over and over and over ... while scrolling (and thus allocates more and more memory, also causing some lag).
I add the UIScrollView to my main viewController like so:
myScrollView = [[CoreTextTestUIView alloc] init];
myScrollView.parentView = self;
if(FACING == #"PU" || FACING == #"PD")
{
myScrollView.frame = CGRectMake(0,50,768,974);
}
else
{
myScrollView.frame = CGRectMake(0,50,1024,718);
}
[myScrollView setContentMode:UIViewContentModeRedraw];
[container addSubview:myScrollView];
Again, I want drawRect to be called when the iPad is rotated, so the number of columns can change ... BUT I do not want it to call drawRect when I simply try to scroll the UIScrollView.
Can someone help me please?
...
below is the .m for my UIScrollView:
#import "CoreTextTestUIView.h"
#import <CoreText/CoreText.h>
#implementation CoreTextTestUIView
#synthesize parentView;
NSMutableString *testText;
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
// Initialization code
//set BG color
self.backgroundColor = [[UIColor alloc] initWithRed:134 green:166 blue:228 alpha:1.0];
//UIScrollView Stuff
//self.delegate = self;
self.scrollEnabled = YES;
self.pagingEnabled = YES;
self.userInteractionEnabled = YES;
[self becomeFirstResponder];
self.showsVerticalScrollIndicator = NO;
self.showsHorizontalScrollIndicator = NO;
self.bounces = NO;
self.alwaysBounceHorizontal = YES;
self.alwaysBounceVertical = NO;
//generate long text
testText = [[NSMutableString alloc] initWithString:#""];
for(int i = 100; i < 1000; i++)
{
[testText appendString:[NSString stringWithFormat:#"%i ",i]];
}
self.alpha = 0.0;
[self fadeIn];
}
return self;
}
-(void)fadeIn
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelegate:self];
//[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
self.alpha = 1.0;
[UIView commitAnimations];
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
-(void)drawRect:(CGRect)rect
{
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"%#",testText]];
//set font
CTFontRef helvetica = CTFontCreateWithName(CFSTR("Helvetica"), 40.0, NULL);
[string addAttribute:(id)kCTFontAttributeName
value:(id)helvetica
range:NSMakeRange(0, [string length])];
//layout master
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);
//flip the coordinate system
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
int textPos = 0;
int columnIndex = 0;
//how many columns? (orientation dependent)
float howManyColumns;
if(parentView.FACING == #"PU" || parentView.FACING == #"PD")
{
howManyColumns = 1.0;
}
else
{
howManyColumns = 2.0;
}
//create columns in loop
while(textPos < [string length])
{
NSLog(#"column started");
//column form
CGMutablePathRef columnPath = CGPathCreateMutable();
CGPathAddRect(columnPath, NULL,
CGRectMake((self.bounds.size.width/howManyColumns*columnIndex), 0,
(self.bounds.size.width/howManyColumns),
self.bounds.size.height));
//column frame
CTFrameRef columnFrame = CTFramesetterCreateFrame(framesetter,
CFRangeMake(textPos, 0),
columnPath,
NULL);
//use the column path
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(textPos, 0), columnPath, NULL);
CFRange frameRange = CTFrameGetVisibleStringRange(frame);
//draw
CTFrameDraw(columnFrame, context);
//cleanup
CFRelease(columnFrame);
CGPathRelease(columnPath);
textPos += frameRange.length;
columnIndex++;
}
//set scrollView content size
int totalPages = (columnIndex+1)/howManyColumns;
self.contentSize = CGSizeMake(totalPages*self.bounds.size.width, self.frame.size.height);
//release
CFRelease(framesetter);
[string release];
}
-(void)dealloc
{
[super dealloc];
[parentView release];
[testText release];
}
#end
Looking at this, I can't see where you are setting the contentSize of your scrollView. If you do not set the contentSize of your scrollView, scrolling will not be enabled, and you will only see what fits within the current area of the scrollView. Also, if your text is static in a configuration, consider optimizing out some of the redrawing that is occurring and add it to a subview of the scrollView.
That is how drawRect works. It is called every single time that the view moves or changes or has something overlapping it. If you are managing memory correctly this shouldn't be a problem.

Tab Bar Controller Customization and "More" Problem

Here's the problem:
I have a tab bar controller customized so the tab item highlights are yellow instead of the default blue. What's wrong is that the "More" item comes up because I have too many tab items (removing them is not really an option), and this "more" is still blue.
I used classes I got from the internet to implement the customization. Here is the code:
// UITabBar+ColorExtensions.m
#implementation UITabBar (ColorExtensions)
- (void)recolorItemsWithColor:(UIColor *)color shadowColor:(UIColor *)shadowColor shadowOffset:(CGSize)shadowOffset shadowBlur:(CGFloat)shadowBlur
{
CGColorRef cgColor = [color CGColor];
CGColorRef cgShadowColor = [shadowColor CGColor];
for (UITabBarItem *item in [self items])
if ([item respondsToSelector:#selector(selectedImage)] &&
[item respondsToSelector:#selector(setSelectedImage:)] &&
[item respondsToSelector:#selector(_updateView)])
{
CGRect contextRect;
contextRect.origin.x = 0.0f;
contextRect.origin.y = 0.0f;
contextRect.size = [[item selectedImage] size];
// Retrieve source image and begin image context
UIImage *itemImage = [item image];
CGSize itemImageSize = [itemImage size];
CGPoint itemImagePosition;
itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2);
itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) / 2);
UIGraphicsBeginImageContext(contextRect.size);
CGContextRef c = UIGraphicsGetCurrentContext();
// Setup shadow
CGContextSetShadowWithColor(c, shadowOffset, shadowBlur, cgShadowColor);
// Setup transparency layer and clip to mask
CGContextBeginTransparencyLayer(c, NULL);
CGContextScaleCTM(c, 1.0, -1.0);
CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [itemImage CGImage]);
// Fill and end the transparency layer
CGContextSetFillColorWithColor(c, cgColor);
contextRect.size.height = -contextRect.size.height;
CGContextFillRect(c, contextRect);
CGContextEndTransparencyLayer(c);
// Set selected image and end context
[item setSelectedImage:UIGraphicsGetImageFromCurrentImageContext()];
UIGraphicsEndImageContext();
// Update the view
[item _updateView];
}
}
#end
and the controller:
#implementation AATabBarController
- (void)viewDidLoad {
[super viewDidLoad];
// Put in a background
CGRect frame = CGRectMake(0.0, 0, self.view.bounds.size.width, 48);
backgroundView = [[UIView alloc] initWithFrame:frame];
[backgroundView setBackgroundColor:[UIColor colorWithRed:0.0
green:0.0
blue:0.0
alpha:0.1]];
[self.tabBar insertSubview:backgroundView atIndex:0];
}
-(void)dealloc {
[backgroundView release];
[super dealloc];
}
-(void)updateTabColor:(UIColor *)color {
// Recolor the tab bar
[self.tabBar recolorItemsWithColor:color shadowColor:[UIColor blackColor] shadowOffset:CGSizeMake(0.0f, -1.0f) shadowBlur:3.0f];
}
-(void)updateBackgroundColor:(UIColor *)color {
// Update the background color
[backgroundView setBackgroundColor:color];
}
#end
Does anyone know what I should do so the "more" tab item is the customized color?
That code looks very similar to the code in this question. I know you're asking a different question here (the linked Q asks "will my app be rejected" to which the answer is "yes"). Nevertheless, you're using the same private UITabBarItem methods, so it's unlikely that anyone can give you a reliable answer.

UITextView inside UIAlertView subclass

I'm trying to put a UITextView inside a custom subclass of UIAlertView that I create using a background image of mine. The UITextView is only for displaying large quantities of text (so the scrolling).
Here is the code of my subclass
- (id)initNarrationViewWithImage:(UIImage *)image text:(NSString *)text{
if (self = [super init]) {
self.backgroundImage = image;
UITextView * textView = [[UITextView alloc] initWithFrame:CGRectZero];
self.textualNarrationView = textView;
[textView release];
self.textualNarrationView.text = text;
self.textualNarrationView.backgroundColor = [UIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0];
self.textualNarrationView.opaque = YES;
[self addSubview:textualNarrationView];
}
return self;
}
- (void)drawRect:(CGRect)rect {
NSLog(#"DRAU");
CGSize imageSize = self.backgroundImage.size;
[self.backgroundImage drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
}
- (void)layoutSubviews {
CGSize imageSize = self.backgroundImage.size;
self.textualNarrationView.bounds = CGRectMake(0, 0, imageSize.width - 20, imageSize.height - 20);
self.textualNarrationView.center = CGPointMake(320/2, 480/2);
}
- (void)show{
[super show];
NSLog(#"SCIO");
CGSize imageSize = self.backgroundImage.size;
self.bounds = CGRectMake(0, 0, imageSize.width, imageSize.height);
self.center = CGPointMake(320/2, 480/2);
}
This is my first time subclassing a UIView, I'm surely missing something since the background image appears correctly, the UITextview also but after a fraction of a second it jumps all up (seems like a coordinate problem).
I've finally created my own customized version of UIAlertView and provided a UITextView inside of it. Here is what brought me to do so.
By doing it I experienced a weird behaviour when I was trying to attach the UITextView to a background UIImageView as a subview, it wasn't responsive to touches anymore, the way to make it work as expected was to attach it to the base view and implement the following method
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
by making it return YES when encessary.

How would I add a dissolve transition to my code? (comic book)

How would I add a dissolve transition to my code?
I tried looking at Apple's code but to no avail. Any ideas?
#import "ApotheosisViewController.h"
#implementation ApotheosisViewController
#synthesize scrollView1;
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
const CGFloat kScrollObjHeight = 320.0;
const CGFloat kScrollObjWidth = 480.0;
const NSUInteger kNumImages = 40;
- (void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [scrollView1 subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (kScrollObjWidth);
}
}
// set the content size so it can be scrollable
[scrollView1 setContentSize:CGSizeMake((kNumImages * kScrollObjWidth), [scrollView1 bounds].size.height)];
}
- (void)viewDidLoad
{
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
// 1. setup the scrollview for multiple images and add it to the view controller
//
// note: the following can be done in Interface Builder, but we show this in code for clarity
[scrollView1 setBackgroundColor:[UIColor blackColor]];
[scrollView1 setCanCancelContentTouches:NO];
scrollView1.indicatorStyle = UIScrollViewIndicatorStyleBlack;
scrollView1.clipsToBounds = NO; // default is NO, we want to restrict drawing within our scrollview
scrollView1.scrollEnabled = YES;
// pagingEnabled property default is NO, if set the scroller will stop or snap at each photo
// if you want free-flowing scroll, don't set this property.
scrollView1.pagingEnabled = YES;
// load all the images from our bundle and add them to the scroll view
NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", i];
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[scrollView1 addSubview:imageView];
[imageView release];
}
[self layoutScrollImages]; // now place the photos in serial layout within the scrollview
}
- (void)dealloc
{
[scrollView1 release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// invoke super's implementation to do the Right Thing, but also release the input controller since we can do that
// In practice this is unlikely to be used in this application, and it would be of little benefit,
// but the principle is the important thing.
//
[super didReceiveMemoryWarning];
}
#end
I can't immediately tell what the code you posted has to do with a dissolve transition.
If you are trying to go from one view to another, then you could put this in your code:
In
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
for one viewController:
self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
and when switching from one view to the other:
[self presentModalViewController:otherViewController animated:YES];