How make a transparent & flat UIBarButtonItem? - objective-c

I wanna to make buttons for my app flat & transaparent, like the ones in the kindle app (see the shop button).
I try to set a custom background by code with not luck (the button is draw as a rectangle, with he border color fill all the background):
- (UIImage *) screenshot {
// Create a graphics context with the target size
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
CGSize imageSize = self.bounds.size;
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
+(UIImage *) buttonFlat {
UIView *bt = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 1.0f, 1.0f)];
bt.backgroundColor = [UIColor blackColor];
bt.layer.borderColor = [UIColor lightGrayColor].CGColor;
bt.layer.borderWidth = 1;
bt.layer.cornerRadius = 5.0;
bt.alpha = 0.7;
return [bt screenshot];
}
I know how do this with a normal UIButton, but prefer to make this so I can retain the standard icons of the UIBarButtonItem if possible...

A UIBarButton can hold any custom view:
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:someView];

Related

How to convert uitextview content to a image in custom size?

I create a uitextview and I can add text and images to it with NSAttributedString and NSTextAttachment
self.tvContent = [[UITextView alloc] initWithFrame:CGRectMake(0, 20,
self.view.frame.size.width, self.view.frame.size.height - 64)];
self.tvContent.font = [UIFont fontWithName:#"Arial" size:16.0f];
self.tvContent.backgroundColor = [UIColor whiteColor];
self.tvContent.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);
self.tvContent.contentInset = UIEdgeInsetsMake(0, 0, 10, 0);
self.tvContent.layoutManager.allowsNonContiguousLayout=NO;
[self.view addSubview:self.tvContent];
And I convert its content to image with following code
- (UIImage *)imageFromView:(UITextView *)view {
CGRect tmpFrame = self.view.frame;
CGRect aFrame = view.frame;
aFrame.size.height = [view sizeThatFits:[[UIScreen mainScreen] bounds].size].height;
view.frame = aFrame;
UIGraphicsBeginImageContext([view sizeThatFits:[[UIScreen mainScreen] bounds].size]);
CGContextRef resizedContext = UIGraphicsGetCurrentContext();
[view.layer renderInContext:resizedContext];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
view.frame = tmpFrame;
return image;
}
This image's max-width is 375(iPhone 6), if I wrote less content, such as 1234, the image's width is 40, so how can I convert the content to image with custom size, such as the width is 750, and the height is as long as the content height? Any ideas? many thanks.
The UITextView only renders within it's current frame, so you need to either resize the frame to the desired size before rendering, or create a temporary UITextView object to use for rendering purpose.
Here is how rendering with a temporary object can be done:
// Your call to get the image
UIImage *image = [self imageFromTextView:self.tvContent width:750.0]; // Any width you want
// Your text view properties that also can be used for rendering purpose
- (void)setupTextViewProperties:(UITextView *)textView {
textView.font = [UIFont fontWithName:#"Arial" size:16.0f];
textView.backgroundColor = [UIColor whiteColor];
textView.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);
textView.contentInset = UIEdgeInsetsMake(0, 0, 10, 0);
textView.layoutManager.allowsNonContiguousLayout=NO;
}
Set up of the temporary UITextView object used for rendering.
- (UIImage *)imageFromTextView:(UITextView *)view width:(CGFloat)desiredWidth {
// Create a new temporary UITextView to use for rendering
CGRect frame = CGRectMake(0.0, 0.0, desiredWidth, 0.0);
UITextView *temporaryTextView = [[UITextView alloc] initWithFrame:frame];
// Setup the temporary text view
// You can have different font, colors etc from the original view
[self setupTextViewProperties:temporaryTextView];
temporaryTextView.attributedText = view.attributedText;
// Calculate the height needed for content with width
CGSize size = CGSizeMake(desiredWidth, 0.0);
size = [temporaryTextView sizeThatFits:size];
// Resize the temporary view
// Note that the calculated size can contain a width smaller that desired with
temporaryTextView.frame = CGRectMake(0.0, 0.0, desiredWidth, size.height);
// Get the image
return [self imageFromView:temporaryTextView];
}
Helper that can render any view as an image.
- (UIImage *)imageFromView:(UIView *)view {
CGSize size = view.bounds.size;
UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

UILabel inside UIView produces rounded corner with "square corner"

I have an UIView which I created and set background color to white. This view contains UILabel, which is a class called BubbleView. (Sorry I cannot add a picture because you need reputation 10+ :(
PROBLEM:
1. The following code produces a gray Label with rounded corner with gray-border square corner tips. This is because the UIView produces the square corner tips. The UILabel is rounded. Please note that I already set the background of UIView to white.
2. My text string of the UILabel is hiding behind UIView, so it is not displayed.
I'd love to show you pictures, but I am new and I cannot add pictures until I get to 10+ reputations.
http://i.stack.imgur.com/CdRjy.png
http://i.stack.imgur.com/zCdCV.png
Here is my code for setting the text and the view:
BubbleView:
- (void)drawRect:(CGRect)rect
{
const CGFloat boxWidth = self.bubbleWidth;
const CGFloat boxHeight = self.bubbleHeight;
NSLog(#"text, width, height: %#, %f, %f", self.text, self.bubbleWidth, self.bubbleHeight);
CGRect boxRect = CGRectMake(
roundf(self.bounds.size.width - boxWidth) / 2.0f,
roundf(self.bounds.size.height - boxHeight) / 2.0f,
boxWidth,
boxHeight);
UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:boxRect cornerRadius:14.0f];
[[UIColor colorWithWhite:0.3f alpha:0.8f] setFill];
[roundedRect fill];
NSDictionary *attributes = #{
NSFontAttributeName : [UIFont systemFontOfSize:16.0f],
NSForegroundColorAttributeName : [UIColor whiteColor]
};
CGPoint textPoint = CGPointMake(
self.center.x+boxWidth/2,
self.center.y+boxHeight/2);
NSLog(#"text point origin: %f, %f", textPoint.x, textPoint.y);
[self.text drawAtPoint:textPoint withAttributes:attributes];
}
Main View Controller:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
[self setText];
}
-(void) viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self setText];
}
- (void) setText
{
NSString *textR = #"I need this text to show up on autolayout so that i could continue working";
UIFont* font = [UIFont fontWithName:#"HelveticaNeue" size:14.0f];
CGSize constraint = CGSizeMake(250,9999);
CGRect textRect = [textR boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:nil];
BubbleView *hostView = [[BubbleView alloc] initWithFrame:CGRectMake(20.0f, 160.0f, textRect.size.width+20, textRect.size.height+20)];
hostView.bubbleWidth = textRect.size.width+20;
hostView.bubbleHeight = textRect.size.height+20;
hostView.text = textR;
hostView.layer.cornerRadius = 10.0f;
self.view.layer.masksToBounds = TRUE;
[hostView drawRect:textRect];
hostView.backgroundColor = [UIColor whiteColor];
self.detailsView = hostView;
//self.detailsView.backgroundColor = [UIColor whiteColor];
NSLog(#"size: %f, %f", textRect.size.width, textRect.size.height);
NSLog(#"origin: %f, %f - size: %f, %f, backgroundColor: #%#", self.detailsView.frame.origin.x, self.detailsView.frame.origin.y, self.detailsView.frame.size.width, self.detailsView.frame.size.height, self.detailsView.backgroundColor);
[self.view addSubview:self.detailsView];
self.hostSays.text = textR;
self.hostSays.textColor = [UIColor blueColor];
[self.view layoutSubviews];
}
SOLUTION (ONLY 1 PART):
OK so I managed to solve half of my problems. I had to add the following code in my BubbleView class (inside - (id)initWithFrame:(CGRect)frame). This got rid of the square angles! (I think Wain was the one who suggested this but I might've misunderstood him)...
[self setOpaque:NO];
[self setBackgroundColor:[UIColor clearColor]];
So...still have the other part 2 of problem to solve and I'm hoping someone has run into this issue before!
Set the background colour of the view and add the label as a subview. Set the frame to get your required padding. Do not implement drawRect.
Now, the view will draw the background colour and the label automatically and the label will draw the text (with its background colour and border settings).
I know when I create custom buttons I need to setMasksToBounds
+ (void) addBorderToButtons:(UIButton *) btn
{
// Round button corners
CALayer *btnLayer = [btn layer];
[btnLayer setMasksToBounds:YES];
[btnLayer setCornerRadius:15.0f];
// Apply a 1 pixel, black border around Buy Button
[btnLayer setBorderWidth:1.5f];
[btnLayer setBorderColor:[[UIColor blackColor] CGColor]];
}
Setting this changes
To this
If you want to save your coding approach you strongly need to add [super drawRect:rect] in your drawRect: method
- (void)drawRect:(CGRect)rect{
[super drawRect:rect];
YOUR CODE
}
In this case you will see your text in UILabel.
Also you should not call drawRect: directly. It will be called automatically in runtime:
BubbleView *hostView =
[[BubbleView alloc] initWithFrame:CGRectMake(20.0f,
160.0f,
textRect.size.width+20,
textRect.size.height+20)];
hostView.bubbleWidth = textRect.size.width+20;
hostView.bubbleHeight = textRect.size.height+20;
hostView.text = textR;
// hostView.layer.cornerRadius = 10.0f;
// self.view.layer.masksToBounds = TRUE;
// [hostView drawRect:textRect];
// hostView.backgroundColor = [UIColor whiteColor];
self.detailsView = hostView;

Retina Support for custom UITabBarController-like highlighting of UIImage?

I'm using BCTabBarController in my app, and I'm trying to customize it so that it uses Core Graphics to highlight the images automatically, so that I don't need four copies of each image. (Retina, Retina-selected, Legacy, Legacy-selected)
User Ephraim has posted a great starting point for this, but it returns legacy sized images. I've played with some of the settings, but I'm not very familiar with Core Graphics, so I'm shooting in the dark.
Ephraim's Code:
- (UIImage *) imageWithBackgroundColor:(UIColor *)bgColor
shadeAlpha1:(CGFloat)alpha1
shadeAlpha2:(CGFloat)alpha2
shadeAlpha3:(CGFloat)alpha3
shadowColor:(UIColor *)shadowColor
shadowOffset:(CGSize)shadowOffset
shadowBlur:(CGFloat)shadowBlur {
UIImage *image = self;
CGColorRef cgColor = [bgColor CGColor];
CGColorRef cgShadowColor = [shadowColor CGColor];
CGFloat components[16] = {1,1,1,alpha1,1,1,1,alpha1,1,1,1,alpha2,1,1,1,alpha3};
CGFloat locations[4] = {0,0.5,0.6,1};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef colorGradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, (size_t)4);
CGRect contextRect;
contextRect.origin.x = 0.0f;
contextRect.origin.y = 0.0f;
contextRect.size = [image size];
//contextRect.size = CGSizeMake([image size].width+5,[image size].height+5);
// Retrieve source image and begin image context
UIImage *itemImage = 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);
CGContextDrawLinearGradient(c, colorGradient,CGPointZero,CGPointMake(contextRect.size.width*1.0/4.0,contextRect.size.height),0);
CGContextEndTransparencyLayer(c);
//CGPointMake(contextRect.size.width*3.0/4.0, 0)
// Set selected image and end context
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGColorSpaceRelease(colorSpace);
CGGradientRelease(colorGradient);
return resultImage;
}
To implement this code, I've added a category to UIImage in my project, and then made the following changes to BCTab.h:
- (id)initWithIconImageName:(NSString *)imageName {
if (self = [super init]) {
self.adjustsImageWhenHighlighted = NO;
self.background = [UIImage imageNamed:#"BCTabBarController.bundle/tab-background.png"];
self.rightBorder = [UIImage imageNamed:#"BCTabBarController.bundle/tab-right-border.png"];
self.backgroundColor = [UIColor clearColor];
// NSString *selectedName = [NSString stringWithFormat:#"%#-selected.%#",
// [imageName stringByDeletingPathExtension],
// [imageName pathExtension]];
UIImage *defImage = [UIImage imageNamed:imageName];
[self setImage:[defImage imageWithBackgroundColor:[UIColor lightGrayColor] shadeAlpha1:0.4 shadeAlpha2:0.0 shadeAlpha3:0.6 shadowColor:[UIColor blackColor] shadowOffset:CGSizeMake(0.0, -1.0f) shadowBlur:3.0] forState:UIControlStateNormal];
[self setImage:[defImage imageWithBackgroundColor:[UIColor redColor] shadeAlpha1:0.4 shadeAlpha2:0.0 shadeAlpha3:0.6 shadowColor:[UIColor blackColor] shadowOffset:CGSizeMake(0.0, -1.0f) shadowBlur:3.0] forState:UIControlStateSelected];
}
return self;
}
How can I use Ephraim's code to work correctly with Retina display?
After digging around the internet, a Google search lead me back to StackOverflow. I found this answer to this question which discusses a different method which should be used to set the scale factor of the UIImageGraphicsContext when it is initialized.
UIGraphicsBeginImageContext(contextRect.size); needs to be changed to UIGraphicsBeginImageContextWithOptions(contextRect.size, NO, scale);, where "scale" is the
value of the scale you want to use. I grabbed it from [[UIScreen mainScreen] scale].

Trying to display images using UIScrollView

I want to create an simple app that will contain one centered image at the first start screen, than upon swipe gesture(right, left) change images.
I'm very new to this so here is what I though is what I'm looking for http://idevzilla.com/2010/09/16/uiscrollview-a-really-simple-tutorial/ .
This is the code I have in my controller implementation :
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
[myDictionary setObject:#"img1.jpg" forKey:#"http://www.testweb.com"];
[myDictionary setObject:#"img2.jpg" forKey:#"http://www.test2.com"];
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
scroll.pagingEnabled = YES;
NSInteger numberOfViews = [myDictionary count];
for (NSString* key in myDictionary) {
UIImage * image = [UIImage imageNamed:[NSString stringWithFormat:[myDictionary objectForKey:key]]];
CGRect rect = CGRectMake(10.0f, 90.0f, image.size.width, image.size.height);
UIImageView * imageView = [[UIImageView alloc] initWithFrame:rect];
[imageView setImage:image];
CGPoint superCenter = CGPointMake([self.view bounds].size.width / 2.0, [self.view bounds].size.height / 2.0);
[imageView setCenter:superCenter];
self.view.backgroundColor = [UIColor whiteColor];
[scroll addSubview:imageView];
}
scroll.contentSize = CGSizeMake(self.view.frame.size.width * numberOfViews, self.view.frame.size.height);
[self.view addSubview:scroll];
}
My first issue here is that I get img2 on my initial screen instead of img1. And second issue is when I swipe right I get white screen and no image on it. Any suggestions what I missed, what I can try/read etc?
EDIT :
I'm looking to do this the "lightest" possible way, using no fancy galleries api etc. Just display couple of really small images(i.e 200x200 px) centered on the screen that I can swipe back and forth(should't be too hard). Well everything is hard when learning a new language.
There is a project on github MWPhotoBrowser that allows you to put in a set of images which are viewed one at a time. You can then scroll from one image to the next with a swipe gesture. It is also easy to add functionality and it should give you a good understanding of how this is done. There is also Apple's PhotoScroller example which gives you straight forward code in how to do this same thing and also tile your images. Since you are new to iOS you may want to first look at both of these examples or possibly just use them as your photo viewer.
Your problem is likely to be the fact that you are setting CGRect rect = CGRectMake(10.0f, 90.0f, image.size.width, image.size.height); for both of your image views. This means that both of your UIImageView objects are placed in exactly the same position (both are positioned at 10.f on the x-coordinate of the scrollview). As the second image view is added last it covers the first and means that there is white space to the right of it.
In order to fix this you could try something like...
- (void)viewDidLoad
{
//your setup code
float xPosition = 10.f;
for (NSString* key in myDictionary) {
UIImage * image = [UIImage imageNamed:[NSString stringWithFormat:[myDictionary objectForKey:key]]];
CGRect rect = CGRectMake(xPosition, 90.0f, image.size.width, image.size.height);
xPosition += image.size.width;
//rest of your code...
}
//rest of your code
}
The above would mean that the second view is positioned on the x-coordinate at 10 + the width of the first image. Note that I haven't tested my answer.
First off the images are placed on top of each other.
CGPoint superCenter = CGPointMake([self.view bounds].size.width / 2.0, [self.view bounds].size.height / 2.0);
[imageView setCenter:superCenter];
Right here you are setting both images to be placed at the center of the screen. The second thing is your using an NSDictionary and looping through the keys. NSDictionary are not orders like an array is. You would have to sort the keys to us it in a specific order. So Barjavel had it right but skipped over the fact your setting the images to center. Try this:
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *myArray = [[NSArray alloc] initWithObjects:#"img1.jpg", #:image2.jpg", nil];
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
scroll.pagingEnabled = YES;
NSInteger numberOfViews = [myArray count];
int xPosition = 0;
for (NSString* image in myArray) {
UIImage * image = [UIImage imageNamed:image];
CGRect rect = CGRectMake(xPosition, 90.0f, image.size.width, image.size.height);
UIImageView * imageView = [[UIImageView alloc] initWithFrame:rect];
[imageView setImage:image];
self.view.backgroundColor = [UIColor whiteColor];
[scroll addSubview:imageView];
xPosition += image.size.width;
}
scroll.contentSize = CGSizeMake(self.view.frame.size.width * numberOfViews, self.view.frame.size.height);
[self.view addSubview:scroll];
}

UIImage/UIImageView redraw when containing UIView is scaled

My iPad app has a navigation where I show screenshots of the different pages and because I want to show more than one screenshot at once I scale the container to around 24% of the original screenshots (1024x768).
- (void) loadView
{
// get landscape screen frame
CGRect screenFrame = [UIScreen mainScreen].bounds;
CGRect landscapeFrame = CGRectMake(0, 0, screenFrame.size.height, screenFrame.size.width);
UIView *view = [[UIView alloc] initWithFrame:landscapeFrame];
view.backgroundColor = [UIColor grayColor];
self.view = view;
// add container view for 2 images
CGRect startFrame = CGRectMake(-landscapeFrame.size.width/2, 0, landscapeFrame.size.width*2, landscapeFrame.size.height);
container = [[UIView alloc] initWithFrame:startFrame];
container.backgroundColor = [UIColor whiteColor];
// add image 1 (1024x768)
UIImage *img1 = [UIImage imageNamed:#"01.jpeg"];
UIImageView *img1View = [[UIImageView alloc] initWithImage:img1];
[container addSubview:img1View];
// add image 2 (1024x768)
UIImage *img2 = [UIImage imageNamed:#"02.jpeg"];
UIImageView *img2View = [[UIImageView alloc] initWithImage:img2];
// move img2 to the right of img1
CGRect newFrame = img2View.frame;
newFrame.origin.x = 1024.0;
img2View.frame = newFrame;
[container addSubview:img2View];
// scale to 24%
container.transform = CGAffineTransformMakeScale(0.24, 0.24);
[self.view addSubview:container];
}
but when I scale images with "small" text it looks sth like this:
I have to use the big screenshots because if a user taps the image it should scale to 100% and be crispy clear.
is there a way how I can scale the images "smoothly" (on the fly) without ruining performance?
it would be enough to have two versions: the full-px one and another for the 24% version.
The reason the scaled-down image looks crappy is it's being scaled in OpenGL, which is using fast-but-low-quality linear interpolation. As you probably know, UIView is built on top of CALayer, which is in turn a sort of wrapper for OpenGL textures. Because the contents of the layer reside in the video card, CALayer can do all of its magic on the GPU, independent of whether the CPU is busy loading a web site, blocked on disk access, or whatever. I mention this only because it's useful to pay attention to what's actually in the textures inside your layers. In your case, the UIImageView's layer has the full 1024x768 bitmap image on its texture, and that isn't affected by the container's transform: The CALayer inside the UIImageView doesn't see that it's going to be (let's see..) 246x185 on-screen and re-scale its bitmap, it just lets OpenGL do its thing and scale down the bitmap every time it updates the display.
To get better scaling, we'll need to do it in CoreGraphics instead of OpenGL. Here's one way to do it:
- (UIImage*)scaleImage:(UIImage*)image by:(float)scale
{
CGSize size = CGSizeMake(image.size.width * scale, image.size.height * scale);
UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
}
- (void)loadView
{
// get landscape screen frame
CGRect screenFrame = [UIScreen mainScreen].bounds;
CGRect landscapeFrame = CGRectMake(0, 0, screenFrame.size.height, screenFrame.size.width);
UIView *view = [[UIView alloc] initWithFrame:landscapeFrame];
view.backgroundColor = [UIColor grayColor];
self.view = view;
// add container view for 2 images
CGRect startFrame = CGRectMake(-landscapeFrame.size.width/2, 0, landscapeFrame.size.width*2, landscapeFrame.size.height);
container = [[UIView alloc] initWithFrame:startFrame];
container.backgroundColor = [UIColor whiteColor];
// add image 1 (1024x768)
UIImage *img1 = [UIImage imageNamed:#"01.png"];
img1View = [[TapImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
img1View.userInteractionEnabled = YES; // important!
img1View.image = [self scaleImage:img1 by:0.24];
[container addSubview:img1View];
// add image 2 (1024x768)
UIImage *img2 = [UIImage imageNamed:#"02.png"];
img2View = [[TapImageView alloc] initWithFrame:CGRectMake(1024, 0, 1024, 768)];
img2View.userInteractionEnabled = YES;
img2View.image = [self scaleImage:img2 by:0.24];
[container addSubview:img2View];
// scale to 24% and layout subviews
zoomed = YES;
container.transform = CGAffineTransformMakeScale(0.24, 0.24);
[self.view addSubview:container];
}
- (void)viewTapped:(id)sender
{
zoomed = !zoomed;
[UIView animateWithDuration:0.5 animations:^
{
if ( zoomed )
{
container.transform = CGAffineTransformMakeScale(0.24, 0.24);
}
else
{
img1View.image = [UIImage imageNamed:#"01.png"];
img2View.image = [UIImage imageNamed:#"02.png"];
container.transform = CGAffineTransformMakeScale(1.0, 1.0);
}
}
completion:^(BOOL finished)
{
if ( zoomed )
{
UIImage *img1 = [UIImage imageNamed:#"01.png"];
img1View.image = [self scaleImage:img1 by:0.24];
UIImage *img2 = [UIImage imageNamed:#"02.png"];
img2View.image = [self scaleImage:img2 by:0.24];
}
}];
}
And here's TapImageView, a UIImageView subclass that tells us when it's been tapped by sending an action up the responder chain:
#interface TapImageView : UIImageView
#end
#implementation TapImageView
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
[[UIApplication sharedApplication] sendAction:#selector(viewTapped:) to:nil from:self forEvent:event];
}
#end
Instead of scaling the container and all of its subviews. Create a UIImageView from the contents of the container and adjust its frame size to 24% of the original.
UIGraphicsBeginImageContext(container.bounds.size);
[container renderInContext:UIGraphicsGetCurrentContext()];
UIImage *containerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *containerImageView = [[UIImageView alloc] initWithImage:containerImage];
CGRectFrame containerFrame = startFrame;
containerFrame.size.with *= 0.24;
containerFrame.size.height *= 0.24;
containerImageView.frame = containerFrame;
[self.view addSubView:containerImageView];