Double tap to Zoom with UIScrollView - xcode

I am using Apple's source code. I am sure there is just a snippet that I have messed up. I have a form that I have made programmatically. When I double tap the recognizer fires and goes through the motions but I it won't actually zoom. Any suggestions? Thanks for the help
imageScrollView.delegate=self;
CGRect fullScreenRect=[[UIScreen mainScreen] applicationFrame];
imageScrollView=[[UIScrollView alloc]initWithFrame:fullScreenRect];
imageScrollView.contentSize=CGSizeMake(750,1250);
imageScrollView.minimumZoomScale=1.0;
imageScrollView.maximumZoomScale=5.0;
[imageScrollView setZoomScale:imageScrollView.minimumZoomScale];
self.view=imageScrollView;
[imageScrollView release];
Added a bunch of UItextfields/labels to the scrollview.
aircraftType = [[UITextField alloc]initWithFrame:CGRectMake(170, 32, 150, 15)];
aircraftType.font=[UIFont systemFontOfSize:10];
aircraftType.borderStyle = UITextBorderStyleRoundedRect;
aircraftType.placeholder = #"Aicraft Type";
aircraftType.delegate = self;
[self.view addSubview:aircraftType];
#pragma mark UIScrollViewDelegate methods
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}
#pragma mark TapDetectingImageViewDelegate methods
- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
// double tap zooms in
float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[imageScrollView zoomToRect:zoomRect animated:YES];
}
#pragma mark Utility methods
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
CGRect zoomRect;
// the zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [imageScrollView frame].size.height / scale;
zoomRect.size.width = [imageScrollView frame].size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
}

Related

Best practice for resize window with animation using ToolBar on Cocoa

I'm wondering what's the best practice to resize a window when Toolbar changes.
I'm trying to get this effect (animated) when a Toolbar selected option changes.
Any ideas?
Thank you for your help! :)
Here's my commonly used method:
After clicking the new toolbar item, firstly get the frame size of the new subview to be added, then change window's frame with animation.
Demo (just change height, but you can add support to change width):
- (void)switchToTabView:(NSView *)settingView withAnimation:(BOOL)animation
{
NSView *windowView = self.window.contentView;
for (NSView *view in windowView.subviews) {
[view removeFromSuperview];
}
CGFloat oldHeight = windowView.frame.size.height;
[windowView addSubview:settingView];
CGFloat newHeight = settingView.frame.size.height;
CGFloat delta = newHeight - oldHeight;
NSPoint origin = settingView.frame.origin;
origin.y -= delta;
[settingView setFrameOrigin:origin];
NSRect frame = self.window.frame;
frame.size.height += delta;
frame.origin.y -= delta;
[self.window setFrame:frame display:YES animate:animation];
}
#GoKu Your answer gave me a hint how to solve it. I just added a new property for my window called "win".
Here's my solution:
- (void)updateView:(int)tag{
[[_ourViewController view] removeFromSuperview];
if (tag==0) {
self.ourViewController = [[UserView alloc] initWithNibName:#"UserView" bundle:nil];
} else if (tag==1){
self.ourViewController = [[ComputerView alloc] initWithNibName:#"ComputerView" bundle:nil];
}
NSView *newView = _ourViewController.view;
NSRect windowRect = _win.frame;
NSRect currentViewRect = newView.frame;
windowRect.origin.y = windowRect.origin.y + (windowRect.size.height - currentViewRect.size.height);
windowRect.size.height = currentViewRect.size.height;
windowRect.size.width = currentViewRect.size.width;
[self.win setContentView:newView];
[self.win setFrame:windowRect display:YES animate:YES];
}
Thanx!

CoreGraphics drawRect in a cocos2d project EXEC BAD ACCESS

I got a interesting riddle here. My cocos2d project uses a UIView to display nicer popups than the regular alert view. To be more flexible in the size of the popup, I draw the background in the drawRect method.
But first the hierarchy how I implement cocos2d and UIKit:
Every UIKit element is added to the RootViewController. Every CCNode to the EAGLView. (If someone has a better solution to mix those world, don't wait to tell me!) Unfortunately is every UIKit view in front of cocos nodes.
Everything works fine when I add the first popup to the RootViewController. But if I remove the first popup and add a new one to the RootViewController occurs a bad access.
It crashes only in combination with cocos2d.
I use the code from Ray Wenderlichs CoreGraphics 101 tutorial.
context and strokeColor are not nil.
Another important infos: I use ARC and am supporting iOS 4.2 and above.
The complete code can be found at raywenderlich.com or below
void drawLinearGradient(CGContextRef context, CGRect rect, CGColorRef startColor, CGColorRef endColor)
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[] = { 0.0, 1.0 };
NSArray *colors = [NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)endColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace,
(__bridge CFArrayRef) colors, locations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextSaveGState(context);
CGContextAddRect(context, rect);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
}
CGRect rectFor1PxStroke(CGRect rect)
{
return CGRectMake(rect.origin.x + 0.5, rect.origin.y + 0.5, rect.size.width - 1, rect.size.height -1);
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect frame = CGRectInset(self.bounds, 2, 2);
CGContextSetShadowWithColor(context, CGSizeMake(0, 0), 3.0, shadowColor);
CGRect strokeRect = CGRectInset(frame, -2.0, -2.0);
CGContextSetStrokeColorWithColor(context, strokeColor);
CGContextSetLineWidth(context, 2.0);
CGContextStrokeRect(context, rectFor1PxStroke(strokeRect));
drawLinearGradient(context, frame, gradient1, gradient2);
}
ARC releases the CGColorRef named strokeColor. One fix is to replace it with an CGFloat array and use CGContextSetStrokeColor instead CGContextSetStrokeColorWithColor
This answer solves this issue:
App crashes when using __bridge for CoreGraphics gradient on ARC
I agree with zeiteisen ,ARC releases CGColorRef and the easiest way to solve this by
replacing CGContextSetStrokeColorWithColor with
CGContextSetStrokeColor(context, components)
Change UIColor of strokeColor to 'RGB CGFloat components array' as following:
static CGFloat red, green, blue, alpha;
- (void)getRGBComponents:(CGFloat [4])components forColor:(UIColor *)color {
[color getRed:&red green:&green blue:&blue alpha:&alpha];//To fetch CGFloat RGB components
for (int component = 0; component < 4; component++) {
switch (component) {
case 0:
components[component] = red;
break;
case 1:
components[component] = green;
break;
case 2:
components[component] = blue;
break;
case 3:
components[component] = alpha;
break;
default:
break;
}
}
}
Use this method like this:
CGFloat components[4];
UIColor *strokeColor=[UIColor greyColor];//My color
[self getRGBComponents:components forColor:strokeColor];//'components' will be substituted in CGContextSetStrokeColor
NSLog(#"%f %f %f %f", components[0], components[1], components[2],components[3]);

Implementing zooming in CALayer

I'm trying to implement zoom on a CALayer in a layered-hosting NSVIew. The NSView with the layer (size of the layer: 1024x768) is inside an NSScrollView. What I did to implement the zoom is the following
- (IBAction)zoomOut:(NSButton *)sender {
CALayer *layer = self.editorView.layer;
CGRect frame = layer.frame;
frame.size.width = frame.size.width / 2;
frame.size.height = frame.size.height / 2;
layer.frame = frame;
}
- (IBAction)zoomIn:(NSButton *)sender {
CALayer *layer = self.editorView.layer;
CGRect frame = layer.frame;
frame.size.width = frame.size.width * 2;
frame.size.height = frame.size.height * 2;
layer.frame = frame;
}
After clicking on the button for zooming in or zooming out in the NSView, the problem is that whenever i scroll the NSView (remember that I put the NSView inside an NSScrollView, and that the NSView is bigger than the NSScrollView), the CALayer resizes automatically to the original size (i.e. 1024x768). I cannot figure out the reason.
Any kind of help would be much appreciated.
+ (CALayer *)layer alias backing store (I call it root layer) resizes with the view, there is no way to prevent this.

reset image in tableView imageCell is blurry

i'm trying to show an 'info' icon during a cursor 'rollover' on an NSTableView cell. i'm getting a copy of the cell's image, drawing the 'info' icon on it, and telling the cell to setImage with this copy. just drawing the icon will scale it and it won't be the same size in every one as the images in the table are different sizes. i'm not having a problem with the scaling or positioning the correct size icon.
my problem is that the replaced image is slightly blurry and it's edges are not crisp on close examination. the lack of edge makes it appear to be 'moving' slightly when the mouseEntered happens and the image is replaced.
i've tried a number of drawing techniques that doen't use lockFocus on an NSImage (drawing in CGBitmapContext, or using CIFilter compositing), and they produce the same results.
i'm using NSTableView's preparedCellAtColumn as it seems that drawing in willDisplayCell is unpredictable -- i read somewhere but can't remember where.
here is my preparedCellAtColumn method:
- (NSCell *)preparedCellAtColumn:(NSInteger)column row:(NSInteger)row
{
NSCell *cell = [super preparedCellAtColumn:column row:row];
if ((self.mouseOverRow == row) && column == 0) {
NSCell * imageCell = [super preparedCellAtColumn:0 row:row];
NSImage *sourceImage = [[imageCell image] copy];
NSRect cellRect = [self frameOfCellAtColumn:0 row:row];
NSSize cellSize = cellRect.size;
NSSize scaledSize = [sourceImage proportionalSizeForTargetSize:cellSize];
NSImage *outputImage = [[NSImage alloc] initWithSize:cellSize];
[outputImage setBackgroundColor:[NSColor clearColor]];
NSPoint drawPoint = NSZeroPoint;
drawPoint.x = (cellSize.width - scaledSize.width) * 0.5;
drawPoint.y = (cellSize.height - scaledSize.height) * 0.5;
NSRect drawRect = NSMakeRect(drawPoint.x, drawPoint.y, scaledSize.width, scaledSize.height);
NSPoint infoPoint = drawPoint;
infoPoint.x += NSWidth(drawRect) - self.infoSize.width;
[outputImage lockFocus];
[sourceImage drawInRect:drawRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[self.infoImage drawAtPoint:infoPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[outputImage unlockFocus];
[cell setImage:outputImage];
}
return cell;
}
[this is the enclosed scaling method from scott stevenson]
- (NSSize)proportionalSizeForTargetSize:(NSSize)targetSize
{
NSSize imageSize = [self size];
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
if ( NSEqualSizes( imageSize, targetSize ) == NO )
{
CGFloat widthFactor;
CGFloat heightFactor;
widthFactor = targetWidth / width;
heightFactor = targetHeight / height;
if ( widthFactor < heightFactor )
scaleFactor = widthFactor;
else
scaleFactor = heightFactor;
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
}
return NSMakeSize(scaledWidth,scaledHeight);
}
i need to support 10.6, so can't use new groovy lion methods.
thanks for your consideration...
Your code is setting the origin of the image to non-integral coordinates. That means that the edge of the image will not be pixel-aligned, producing a fuzzy result.
You just need to do this:
NSPoint drawPoint = NSZeroPoint;
drawPoint.x = round((cellSize.width - scaledSize.width) * 0.5);
drawPoint.y = round((cellSize.height - scaledSize.height) * 0.5);
That will ensure the image origin has no fractional component.

I can't draw a NSRect based on where the user clicks

I am trying to draw a rectangle and let the user create it based on where he clicks and where he drags the mouse.
The code I am using to draw the NSRect is:
CGFloat width = endPoint.x-startPoint.x; //Width of rectangle.
CGFloat height = endPoint.y-startPoint.y; //Height of rectangle.
CGFloat rectXPoint = startPoint.x; //x component of corner of rect
CGFloat rectYPoint = startPoint.x; //y component of corner of rect
if (width < 0) { //Handle negavive rect size here.
width = startPoint.x-endPoint.x;
rectXPoint = endPoint.x;
}
if (height < 0) { //and here.
height = startPoint.y-endPoint.y;
rectYPoint = endPoint.y;
}
NSRect theRect = NSMakeRect(rectXPoint, rectYPoint, width, height);
[[NSColor blackColor] set];
NSRectFill(theRect);
So I can sort of get the code to work but not exactly. Sometimes it offsets the y of the rectangle from the cursor by some seemingly arbitrary amount (even though I know it isn't arbitrary). It is hard to get a screen shot considering that would involve me moving the mouse from the point it would need to be to demonstrate the point. Just in case you need to see the code for how I am getting the location of the mouse here it is:
- (void)mouseDown:(NSEvent *)event {
NSPoint location = [self convertPointFromBase:[event locationInWindow]];
startPoint = location;
}
- (void)mouseDragged:(NSEvent *)event {
NSPoint location = [self convertPointFromBase:[event locationInWindow]];
endPoint = location;
[self setNeedsDisplay:YES];
}
And isFlipped returns YES.
If you need any more clarification ask what you need clarification.
Probably this line:
CGFloat rectYPoint = startPoint.x; //y component of corner of rect

Resources