How to properly replace image in UIImageView in UIScrollView on iOS - ios

I have an interesting problem. I have one UIScrollView and inside only one UIImageView with image. I need this for zooming and panning.
Ok. On a button touch I want to replace image within UIImageView (which is within UIScrollView, like a mentioned) with the next one in line.
So far I've done this like that:
self.imageView = nil;
self.imageView = [[UIImageView alloc] initWithImage:nextImage];
The reason that I always set self.imageView to nil is that if I don't do that than the next image is scaled or zoomed like the previous one was.
But I don't think thats fine solution for memory efficiency.
Is there any other way to set new image on UIImageView with "reset" option for zooming, scale, etc... ?
UPDATE:
The code that still does not work:
[self.scrollView setZoomScale:1.0];
[self.imageView setImage:photoImage];
[self.imageView setFrame:rect];
[self.scrollView setContentSize:[self.imageView frame].size];
CGFloat minZoomScale = [self.scrollView frame].size.width / [self.imageView frame].size.width;
if (minZoomScale < [self.scrollView frame].size.height / [self.imageView frame].size.height) {
minZoomScale = [self.scrollView frame].size.height / [self.imageView frame].size.height;
}
[self.scrollView setMinimumZoomScale:minZoomScale];
[self.scrollView setZoomScale:[self.scrollView minimumZoomScale]];
UPDATE 2
Just figured out what I was doing wrong. I did not reset the minimum zoom scale.
[self.scrollView setMinimumZoomScale:1.0];
Now it works!

There is a property called zoomScale in UIScrollView
Set 1.0 to the zoomScale of your scrollview. No need to release the old UIImageView and to allocate a new UIImageView everytime. You can directly set the image to the imageview and set the zoomScale of the UIScrollView to 1.0.

Just want to make one thing clear because I ran into the same problem: reset the minimum zoom scale to 1.0 BEFORE changing the image of the imageView:
[self.scrollView setMinimumZoomScale:1.0];
[self.scrollView setZoomScale:1.0];
[self.imageView setImage:photoImage];
[self.photoView setFrame:(CGRect){.origin=CGPointMake(0.0f, 0.0f), photoImage.size=photo.size}];
[self.scrollView setContentSize:[self.imageView frame].size];
CGFloat minZoomScale = MIN([self.scrollView frame].size.width / [self.imageView frame].size.width, [self.scrollView frame].size.height / [self.imageView frame].size.height)
[self.scrollView setMinimumZoomScale:minZoomScale];
[self.scrollView setMaximumZoomScale:1.0];
[self.scrollView setZoomScale:[self.scrollView minimumZoomScale]];
[self centerScrollViewContents];
and for centring the image:
- (void)centerScrollViewContents {
CGSize boundsSize = self.scrollView.bounds.size;
CGRect contentsFrame = self.imageView.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
} else {
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
} else {
contentsFrame.origin.y = 0.0f;
}
self.imageView.frame = contentsFrame;
}

You can just use the zoomScale property of the scrollView object and set it to 1.0 everytime change the image. This'll probably go before loading the new image. This way you'll not have to alloc and init a new UIIMageVIew object each time you want to change just the image. Additionally you can put this change into an animation block to make the image change not sharp but gradual.

Whey you use this code, every time you create new object, but previous UIImageView stay on your UIScrollView. This is not efficient in memory usage.
Use next code:
[self.imageView removeFromSuperview];
[self.imageView release];
self.imageView = [[UIImageView alloc] initWithImage: nextImage];
[self addSubview: imageView];
or
[self.imageView setImage: nextImage];
[self.imageView setFrame: CGRectMake(0, 0, nextImage.size.width, nextImage.size.height)];
and then, you can set content size for you ScrollView:
topScrollView.contentSize = CGSizeMake(nextImage.size.width, nextImage.size.height);

Related

UIScrollView zoom is not working properly

Whenever I click on an image, I want the image to display as a larger image with the ability to zoom. So far when I click on the image, it displays as I want it to inside a scrollview. However, I have to get lucky to be able to zoom in properly. Most of the time when I attempt to zoom, the image just moves down and to the right and does not zoom at all. Here is my code:
-(void) pictureButtonAction
{
self.scrollImageView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
self.scrollImageView.contentSize = self.fullImageView.image.size;
self.scrollImageView.delegate = self;
self.scrollImageView.clipsToBounds = YES;
self.scrollImageView.scrollEnabled = YES;
[self.scrollImageView setMaximumZoomScale:4.0f];
[self.scrollImageView setMinimumZoomScale:1.0f];
[self.view addSubview:self.scrollImageView];
[self.scrollImageView addSubview:fullImageView];
}
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.fullImageView;
}
ImageViews frame got changed while zooming , so that it moves down. So, You have to centralize the image view each time you zoom .
your scrollviews contentsize should be greater than or equal to your image size , if your fullImageView.image.size is less than your scrollviews bounds ,then set your scrollviews contentSize atleast double the scrollviews bounds .
call the below function in scrollViewDidZoom delegate method
-(void) centerScrollViewContents
{
CGSize boundsSize = self.scrollView.bounds.size;
CGRect contentsFrame = self.imageView.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
} else {
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
} else {
contentsFrame.origin.y = 0.0f;
}
self.imageView.frame = contentsFrame;
}
Try this , hope it will help you ; happy coding ! :)
#Maria's answer works but when zooming you'll experience unwanted bounces, instead of using it under scrollViewDidZoom, use scrollViewDidEndZooming: delegate to prevent that..
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
[self centerScrollViewContents];
}
and with a little enhancement from her code:
[UIView animateWithDuration:0 animations:^{
self.previewImageView.frame = contentsFrame;
}];
a bit late for an answer but i hope this will be useful to some..

Issue while zooming uiscrollview which is used to resize and crop Image in IOS

I'm developing an App which has (image saving) in one of the views, I have three different sizes which I want my images to be saved in after the user zoom and scale the image which is captured from the scroll view when the user click on save.
Below is my Codes:
After the style is selected the width and height is set depending on type chosen and then the scrollview creating method called
-(void)viewDidAppear:(BOOL)animated{
if(!([getColor length] == 0))
{
[theColored setHidden:NO];
[imageView setImage:image];
[theStyle setHidden:NO];
[theStyled setHidden:YES];
}
if(!([getStyle length] == 0))
{
[theColored setHidden:NO];
[imageView setImage:image];
[theStyle setHidden:YES];
[theStyled setHidden:NO];
[Save setHidden:NO];
if([theType isEqual: #"Pant"]){
theW = 200;
theH = 260;
}else if ([theType isEqual:#"Shirt"])
{
theW = 220;
theH = 220;
}else if([theType isEqual:#"Shoes"])
{
theW = 200;
theH = 60;
}
// UIImage *savedImage = image;
CGFloat theScale = 1.0;
[self setTheView:image andFrameW:&theW andFrameH:&theH andTheScale:&theScale];
}}
Below is the method:
-(void)setTheView:(UIImage *)savedImage andFrameW:(CGFloat *)theFW andFrameH:(CGFloat *)theFH andTheScale:(CGFloat *)theScale{
NSLog(#"called");
CGFloat theS = *theScale;
CGFloat imgW ;
CGFloat imgH;
imgW = *theFW * theS;
imgH = *theFH * theS;
// = savedImage.size.height * theS;
[dot removeFromSuperview];
[scrollView setPagingEnabled:NO];
[scrollView setShowsHorizontalScrollIndicator:NO];
[scrollView setShowsVerticalScrollIndicator:NO];
scrollView.layer.masksToBounds=YES;
scrollView.minimumZoomScale = 0.1f;
scrollView.maximumZoomScale = 5.0f;
[scrollView setZoomScale:0.5];
scrollView.layer.borderColor = [UIColor blackColor].CGColor;
scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
[scrollView setContentSize:CGSizeMake(imgW*2,imgH*2)];
dot =[[UIImageView alloc] initWithFrame:CGRectMake(imgW/2,imgH/2,imgW,imgH)];
dot.image=savedImage;
dot.contentMode = UIViewContentModeScaleAspectFit;
[scrollView setScrollEnabled:YES];
[scrollView setTranslatesAutoresizingMaskIntoConstraints:YES];
scrollView.frame = CGRectMake(scrollView.frame.origin.x,scrollView.frame.origin.y, *theFW , *theFH);
[scrollView setHidden:NO];
[scrollView setContentOffset:CGPointMake(imgW/2,imgH/2) animated:NO];
[scrollView addSubview:dot];
}
Zooming methods:
- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView {
return dot;
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale{
NSLog(#"zoomed");
NSLog(#"%f",scale);
[self setTheView:image andFrameW:&theW andFrameH:&theH andTheScale:&scale];
}
Problem:
I have two problems here:
1- The zoom scale is not starting from last point it reached.
2- While tapping to zoom moves even before start zooming.
Update Edit
Both problems Solved
instead of calling the method again after zooming i just changed the content size
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale{
[self setTheView:image andFrameW:&theW andFrameH:&theH andTheScale:&scale];
}
replaced with
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale{
scrollView.contentSize = CGSizeMake((dot.bounds.size.width*scale)*2,(dot.bounds.size.height*scale)*2);
}
But i have new problem came up, after zooming contentOffSet is not equal up and down and also left and write
Digram explanation:
<----------------------------Content Size---------------------------->
| left offset |<---------Scrollviewframe--------->|Right offset|
i tried to set new content offset:
[scrollView setContentOffset:CGPointMake((dot.bounds.size.width*scale)/2,(dot.bounds.size.height*scale)/2) animated:NO];
but made nothing..
Problem solved i wanted to share the answer if someone wants to use scrollview to crop and zoom while allowsEditing = YES; doesn't gives the ability to set the rect size
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale{
CGFloat zoomedW = dot.bounds.size.width*scale;
CGFloat zoomedH = dot.bounds.size.height*scale;
CGFloat frameW = scrollView.frame.size.width;
CGFloat frameH = scrollView.frame.size.height;
scrollView.contentSize = CGSizeMake(frameW+zoomedW ,frameH+zoomedH);
}

UIImageView on iphone 4 image is half way out of view

I am creating an app with a simple UIImageview and scroll view for zooming.
Everything is perfect on my iPhone5/s. However, when I test the app on the iPhone 4S it does not work correctly. When I use a modal to pop the image full screen, the image is half way off the screen.
Again, this ONLY happens on the 4S and not the 5.
I tried changing the anchor points, forcing sizing but nothing works
Also, after I change my orientation from portrait to land scape and back, it goes back into "position"
I am also using constraints as my scrollview is horizontal and vertical center in my main view and the image view is horizontal vertical center in the scroll view.
Thank you in advance.
some relevant code:
image = [UIImage imageNamed:self.myImage];
[self.scrollView setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.imageView setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.myView setTranslatesAutoresizingMaskIntoConstraints:YES];
[im setBackgroundColor:[UIColor blackColor]];
im.contentMode = UIViewContentModeScaleAspectFit;
[self.scrollView setZoomScale:self.scrollView.minimumZoomScale
animated:YES];
NSLog(#"%F",img.size.height);
CGFloat imgheight = image.size.height;
CGFloat imgwidth = image.size. width;
CGSize imageSize = [self currentScreenBoundsDependOnOrientation];
self.scrollView.frame = CGRectMake(0,
0,
imageSize.width,
imageSize.height);
self.imageView.frame = CGRectMake(0,
0,
imageSize.width,
imageSize.height);
dan = true;
self.scrollView.delegate = self;
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.scrollView addGestureRecognizer:doubleTap];
self.scrollView.minimumZoomScale = 1;
self.scrollView.maximumZoomScale = 2.4;
self.scrollView.scrollEnabled = YES;
self.scrollView.zoomScale = self.scrollView.minimumZoomScale;

Graphical glitch in UIScrollView when autorotating device

I have an application which has a fullscreen UIScrollView, and within it there are seven images. The images are also meant to be full screen, and the scroll view is set to enable pagination.
I have a method which either creates or moves the image views:
-(void)rebuildImageView{
// set up images
float screenW = self.view.bounds.size.width;
float screenH = self.view.bounds.size.height;
int numImgs = self.soundNames.count;
self.mainScrollView.contentSize = CGSizeMake(screenW * numImgs, screenH);
for(int i=0; i<numImgs; i++){
UIImageView* imageView = (UIImageView*)[self.mainScrollView viewWithTag:i+100];
if(imageView == nil){
imageView = [[UIImageView alloc] init];
imageView.tag = i+100;
[self.mainScrollView addSubview:imageView];
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"image%d.jpg",i]];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
[imageView release];
}
imageView.frame = CGRectMake(i * screenW, 0, screenW, screenH);
}
// scroll to the current one
[self.mainScrollView scrollRectToVisible:CGRectMake(self.currentSound*screenW, 0, screenW, screenH) animated:YES];
}
I also have this on the view controller:
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[UIView animateWithDuration:duration animations:^{
[self rebuildImageView];
}];
}
This code works fine when I autorotate while image 0 is being shown, but when I'm on image 7, you can briefly see most of image 6 when rotating. This video shows what's happening:
http://www.youtube.com/watch?v=1O3jOcTgVP8
Is there a better method I should use to reconfigure the scroll view and images when rotating the device?
Any frame changes put in the willAnimateRotationToInterfaceOrientation:duration method should automatically animate. So you could try removing it from the block?
Personally, I've had a lot more luck with this type of thing subclassing UIScrollView and putting the equivalent layout subview frame code in an override of the layoutSubviews method (don't forget to call super or you might end up with misplaced scroll bars).

IOS Add subview on viewDidLoad

i have a problem when i'm trying to add subviews to a UIScrollView on viewDidLoad.
I'm using this code to programmatically add the UIImageViews to the scrollView:
- (void)viewDidLoad {
[super viewDidLoad];
NSInteger const_width = 100;
NSInteger numberOfViews = 4;
CGRect theFrame = [self.scrollView frame];
for (int i = 0; i < numberOfViews; i++) {
CGFloat xOrigin = i * const_width;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(xOrigin,theFrame.origin.y,const_width,110)];
UIImage *image = [UIImage imageNamed:#"cocoloco.jpg"];
[imageView setImage:image];
//[self.scrollView addSubview:imageView];
imageView.tag = i;
CGRect rect = imageView.frame;
rect.size.height = 110;
rect.size.width = 110;
imageView.frame = rect;
[self.scrollView addSubview:imageView];
}
self.scrollView.contentSize = CGSizeMake(const_width * numberOfViews, 110);}
But i get the current view:
It seems that the scroll view frame takes its position regardless the 3 yellow tabs (that are a special TabBarController) so i get a wrong frame origin from the UIScrollView and therefore the UIImageViews are wrong positioned.
Any idea?
I don't know exactly how to do it, but add the height of the frame to the "Y" position of your rectangle. Something like this:
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(xOrigin,theFrame.origin.y + (theFrame.height),const_width,110)];
To get the scrollview below the navigation bar at the top, try
self.scrollview.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
Then position the table below the scrollview by setting it's origin base on the scrollview origin and height:
CGRect frame = tableView.frame;
frame.origin.y = self.scrollview.frame.origin.y + self.scrollview.frame.size.height;
tableView.frame = frame;
You should move any resizing or layout of your UI to the -(void)layoutSubviews method and this should sort your problem correctly.

Resources