Zoom with Zoomed Buttons on a UIImageView - objective-c

I have a flat image of a map in a UIImageView and its my job to add clear buttons to some pre-defined "hot spots" that represent locations of interest on the map. However, given the size of the image on the iPhone, the hotspots they have defined are very close together and would be difficult to touch / tap.
Is there a way to zoom in on an image have those buttons scale larger so that they can be pressed more easily?

Yes add the imageview inside a scroll view,
Use this code
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageview = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"yourimage"]];
self.imageView = imageview;
[imageview release];
scrollView.contentSize = CGSizeMake(imageView.frame.size.width, imageView.frame.size.height);
scrollView.maximumZoomScale = 4.0;
scrollView.minimumZoomScale = 0.75;
scrollView.clipsToBounds = YES;
scrollView.delegate = self;
[scrollView addSubview:imageView];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return imageView;
}
In the .h file you would have
#property (nonatomic, retain) UIScrollView *scrollView;
#property (nonatomic, retain) UIImageView *imageView;
For more info please check StackOverFlow on how to add to use UIScrollView
such as Adding UIImageViews to UIScrollView

Related

UIButton - Not clickable in subview [duplicate]

In my .m file I added:
#property (strong, nonatomic) UIImageView *star1;
Then in a method I did:
UIImage *star1Image;
star1Image = [UIImage imageNamed:#"staryes"];
self.star1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
self.star1.tag = 800;
[self.star1 setImage:star1Image];
[ratingLabelBody addSubview:self.star1];
After a few lines not related to this I have:
[self.star1 setUserInteractionEnabled:YES];
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgTouchUp:)];
tapped.numberOfTapsRequired = 1;
[self.star1 addGestureRecognizer:tapped];
And finally in the .m file I have implemented:
-(void)imgTouchUp:(id)sender {
NSLog(#"imgTouchUp");
UITapGestureRecognizer *gesture = (UITapGestureRecognizer *)sender;
NSLog(#"tap detected on %li", (long)gesture.view.tag);
}
With all this, it should recognize the tap on my image but nothing is happening. Any idea?
So, since components like UILabel or UIImageView aren't design to be "touchable", to add a "touchable" feature (like a UITapRecognizer), you have to set their userInteractionEnabled to YES.
So, even if you set this property correctly for your UIImageView (star1), since you add it as a subview of ratingLabelBody, you couldn't trigger your UITapGestureRecognizer (imgTouchUp:).
You have to do the same to the parent view of your star1, which is ratingLabelBody.
Translated with code, you just had to do:
[ratingLabelBody setUserInteractionEnabled:YES];

Image sizes not working with Page Control & ScrollView?

I'm trying to implement page control and scroll view using an image array, and for some reason, my images are shifting around when swiping to the next page. It almost seems like the images are too big for the scroll view, but making them smaller doesn't seem to work. Is there a way to make it so that the ScrollView doesn't "scroll" vertically? See code below.
SSViewController.h
#import <UIKit/UIKit.h>
#interface SSViewController : UIViewController <UIScrollViewDelegate>
#property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
#property (strong, nonatomic) IBOutlet UIPageControl *pageControl;
#property (nonatomic, strong) NSArray *imageArray;
SSViewController.m
-(void)viewDidAppear:(BOOL)animated
{
imageArray = [[NSArray alloc] initWithObjects:#"first.png", #"second.png", nil];
for (int i = 0; i < [imageArray count]; i++) {
//We'll create an imageView object in every 'page' of our scrollView.
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
imageView.image = [UIImage imageNamed:[imageArray objectAtIndex:i]];
size:imageView.clipsToBounds = YES;
imageView.contentMode = UIViewContentModeScaleAspectFill;
[self.scrollView addSubview:imageView];
}
//Set the content size of our scrollview according to the total width of our imageView objects.
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [imageArray count], scrollView.frame.size.height);
}
- (void)scrollViewDidScroll:(UIScrollView *)sender
{
// Update the page when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
self.scrollView.contentOffset = CGPointMake(self.scrollView.contentOffset.x, 0);
}
I think good idea will be to shift all your allocaton code (espacially all code define frames) to viewWillAppear method, because in viewDidLoad some frame wouldn't be already set.

How should I go about recreating the iOS home screen open folder animation?

At first I thought it wouldn't be too hard, but turns out there's a bit more to it than I thought.
At the moment my code's based around this: https://github.com/jwilling/JWFolders. However, it's not very clean, the biggest problem being that it takes a screenshot every time the folder opens (renderInContext: is pretty taxing on the CPU so turns out being very low fps). Aside from that this implementation doesn't look as clean and as polished as the Apple animation does.
Apple manages to pull off a pixel perfect animation that doesn't lag. I'd like to do the same! What is the best way to go about this/how would you do this - a cleanly coded, good looking and fluid animation? At the moment, my animation's lacking in all those areas, and I'm stumped about how I could do it better (like Apple does it).
-
I'm not begging for code, just a best method/how to. But if you want to go ahead and code it then there's no way I'd say no (that would definitely be bouty worthy)!!
I would separate the Springboard into several views, where each view is one row of icons.
If a folder icon is clicked, I would animate all following views to move down and up to make place for the folder content. at the same time I would add a subview that represents the folder content and animates with the same speed its size and position if necessary.
To support a background image that spans over the whole screen I would cut that into pieces and add this pieces as background image views to each row's view.
I wrote a quick and dirty sample code with the animation starting on any tap location, also available as complete project on github.
#interface ViewController ()
#property (nonatomic, strong) UIView *upperView;
#property (nonatomic, strong) UIView *lowerView;
#property (nonatomic, strong) UIImageView *upperImageView;
#property (nonatomic, strong) UIImageView *lowerImageView;
#property (nonatomic, strong) UIView *folderContentsView;
#property (nonatomic, assign) CGRect startRect;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage *bgImg = [UIImage imageNamed:#"bg.png"];
self.upperImageView = [[UIImageView alloc] initWithImage:bgImg];
self.lowerImageView = [[UIImageView alloc] initWithImage:bgImg];
[self.upperImageView setContentMode:UIViewContentModeTop];
[self.lowerImageView setContentMode:UIViewContentModeTop];
self.upperView = [[UIView alloc] initWithFrame:self.upperImageView.frame];
self.lowerView = [[UIView alloc] initWithFrame:self.lowerImageView.frame];
[self.upperView addSubview:_upperImageView];
[self.lowerView addSubview:_lowerImageView];
[self.view addSubview:_lowerView];
[self.view addSubview:_upperView];
UITapGestureRecognizer *upperTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openOverlay:)];
UITapGestureRecognizer *lowerTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openOverlay:)];
[self.upperView setUserInteractionEnabled:YES];
[self.upperView addGestureRecognizer:upperTapRecognizer];
[self.upperView setClipsToBounds:YES];
[self.lowerView setUserInteractionEnabled:YES];
[self.lowerView addGestureRecognizer:lowerTapRecognizer];
[self.lowerView setClipsToBounds:YES];
self.folderContentsView = [[UIView alloc] initWithFrame:CGRectZero];
self.folderContentsView.backgroundColor = [UIColor redColor];
UITapGestureRecognizer *closeTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(closeOverlay:)];
[self.folderContentsView addGestureRecognizer:closeTapRecognizer];
[self.view addSubview:self.folderContentsView];
[self.folderContentsView addSubview:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bgFolder.png"]]];
[self.folderContentsView setClipsToBounds:YES];
self.startRect = [self.upperView frame];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(void)openOverlay:(UITapGestureRecognizer *) sender
{
[self.upperView setUserInteractionEnabled:NO];
[self.lowerView setUserInteractionEnabled:NO];
CGPoint location = [sender locationInView:sender.view];
self.folderContentsView.frame = CGRectMake(0, location.y,
_lowerView.frame.size.width, 0);
self.lowerView.frame = CGRectMake(0, location.y,
_lowerView.frame.size.width, _lowerView.frame.size.height);
self.upperView.frame = CGRectMake(0, 0,
_upperView.frame.size.width, location.y);
self.lowerImageView.frame = CGRectMake(_lowerImageView.frame.origin.x, -location.y,
_lowerImageView.frame.size.width, _lowerImageView.frame.size.height);
[UIView animateWithDuration:.5 animations:^{
self.folderContentsView.frame = CGRectMake(0, location.y,
_lowerView.frame.size.width, 200);
self.lowerView.frame = CGRectOffset(_lowerView.frame, 0, 200);
}];
}
-(void) closeOverlay:(UITapGestureRecognizer*) sender
{
[UIView animateWithDuration:.5 animations:^{
self.lowerView.frame = CGRectOffset(_lowerView.frame, 0, -200);
self.folderContentsView.frame = CGRectMake(0, self.folderContentsView.frame.origin.y,
self.folderContentsView.frame.size.width, 0);
} completion:^(BOOL finished) {
[self.upperView setUserInteractionEnabled:YES];
[self.lowerView setUserInteractionEnabled:YES];
self.upperView.frame = self.startRect;
}];
}
#end
two views a equipped with the same background in layers. If a tap is detected, both views are resized so that the upper view ends at the tap's y-coordinate, while the lower view starts there. the UIImageView added to the lowerView is moved in the opposite direction, so that the images stays in place.
Now the lowerView slides down while a contentView is added and resized at the same speed.
As you can see no image rendering or other tough action is required. just UIView animations.

UIImageView show image out of bounds in a UICollectionViewCell sub class

I have to create a customize UICollectionViewCell to show a image and a name for the image, And on top of the image, there is a frame image which is 2 pixels bigger in width and height than the image. However, no matter what I do, the image seems to be bigger than the frame image. I did the same thing for the table view, and it works perfect.
Here is the code:
//GridCell.h
#interface GridCell : UICollectionViewCell
#property(nonatomic, strong) UILabel *lblName;
#property(nonatomic, strong) UIImageView *image;
#end
//GridCell.m
#import "GridCell.h"
#implementation GridCell
#synthesize image, lblName;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
UIImage *bg = [UIImage imageNamed:#"borderUIimgLg.png"];
UIImageView *bgImage = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, frame.size.width, frame.size.width)];
[bgImage setImage:bg];
[bgImage setContentMode:UIViewContentModeScaleAspectFill];
NSLog(#"BG Image size %f, %f", bgImage.frame.size.width, bgImage.frame.size.height);
UIImageView *contentImage = [[UIImageView alloc] initWithFrame:CGRectMake(2.0, 2.0, frame.size.width-4.0, frame.size.width-4.0)];
[contentImage setContentMode:UIViewContentModeScaleAspectFill];
[contentImage setClipsToBounds:YES];
self.image = contentImage;
[self.contentView addSubview:self.image];
[self.contentView addSubview:bgImage];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(2.0, frame.size.width, frame.size.width - 4.0, 21.0)];
[label setFont:[UIFont fontWithName:#"HelveticaNeue-Bold" size:11.0]];
[label setTextAlignment:NSTextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
self.lblName = label;
[self.contentView addSubview:self.lblName];
}
return self;
}
The UICollectionViewCell has a size of 67 x 100, so in the code, the bgImage supposed to be always to be 67 x 67 and its origin is (0,0) and the contentImage supposed to have a frame of (0,0,63,63). By debugging, it seems correct. However, the conentimage always bigger than the bgImage. The original size of the image is 80 x 80 though. I have tried setClipToBounds,
setContentViewMode on either the cell.ContentView or the imageView, but none works.
A screenshot about the problem is attached.
Any help is appreciated.
This might have found the answer by now, try:
contentImage.clipsToBounds = YES;
you are using 2 times frame.size.width instead of frame.size.height on the other one
edit, try this:
in the cell, when using initWithFrame methods, use the self.bounds property of the cell.
if you init the imageview inside the border use CGRectInset method to initialize the imageview with smaller bounds and set the imageviews center to same as the contentview of the cell
Try changing UIViewContentModeScaleAspectFill to UIViewContentModeScaleAspectFit.

How can I use UIScrollView?

How can I use UIScrollView? please give me a simple example with one scrolling image?
This will get you an insight of the UIScrollView control:
Learning the basics of UIScrollView
Referenced from UIScrollView Tutorials
Some good samples with the basic functionalities covered
http://halmueller.wordpress.com/2008/10/08/a-very-simple-uiscrollview-demo/
http://developer.apple.com/iphone/library/samplecode/Scrolling/index.html
http://www.vimeo.com/1642150
http://jonathanwatmough.com/2008/12/implementing-tap-to-zoom-in-uiscrollview-on-an-iphone/
http://cocoawithlove.com/2009/01/multiple-virtual-pages-in-uiscrollview.html
Not to mention:
https://stackoverflow.com/search?q=UIScrollView
This can be one example. Basically we create a scrollview, set its frame, add content as a subview, and then set the content size. The image (iphone.png) below is bigger than the iphone screen so that we can scroll it.
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 20, 320, 460)];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"iphone.png"]];
[scrollView addSubview:imageView];
[imageView release];
scrollView.contentSize = CGSizeMake(imageView.image.size.width, imageView.image.size.height);
[window addSubview:scrollView];
[scrollView release];
You can use below code to add UIScrollView on yourView :-
[self.ScrollView setContentSize:(CGSizeMake(self.view.frame.size.width, self.view.frame.size.height))];
Step:1
Create a UiScrollView,
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIScrollView *MyScrollView;
#end
Step2:
In your ViewController.m,
[self.MyScrollView setContentSize:(CGSizeMake(self.view.frame.size.width, self.view.frame.size.height))];
Add UIImageView in to UIScrollView.
then,
Use
imageView.image = [UIImage imageNamed:#"image1.png"];
imageView.frame = CGRectMake(0.0, 0.0, imageView.image.size.width, imageView.image.size.height);
scrollView.contentSize = CGSizeMake(imageView.image.size.width, imageView.image.size.height);