Animate addtosubview for multiple subviews - iphone

I am having an array of UIViews and I want to arrange them in a main view in a grid form, and I also wanted it to animate ( ie the grids should appear one by one slowly). Tried animating with in a for loop but didnt work but came up with a work around to achieve something closer to what I want, but just wanted to know if there is a better way to do this. I know there is some property with CAAnimationGroup (begintime) but sure how to connect it to addtosubview. Here is my code, let me know if there is a better way to do it.
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat x = 0;
CGFloat delay = .3;
for(int i=0;i<30;i++)
{
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(x, 0, 50, 50)];
myView.backgroundColor = [UIColor greenColor];
myView.alpha = 0.0;
x = x + 50+ 2;
[UIView animateWithDuration:0.25 delay:delay options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.view addSubview:myView];
myView.transform = CGAffineTransformMakeScale(0.5, 0.5);
// myView.transform = CGAffineTransformMakeRotation(90);
} completion:^(BOOL finished) {
[UIView animateWithDuration:.5 animations:^{
myView.transform = CGAffineTransformMakeScale(1.0, 1.0);
myView.alpha = 1.0;
}];
}];
delay = delay + .3;
}
// Do any additional setup after loading the view, typically from a nib.
}
-anoop

Hi,I have also used animation within for loop but it didn't work
properly then I call a method that animate the view , multiple times
and it worked properly.I think this is better way to simply apply
animation. by calling a method.I m putting some code here may it will
help u.
- (void)viewDidLoad
{
radius=82.097;
rotationMultiplier=1;
toAngle = fromAngle = 0;
toStart = NO;
center=CGPointMake(161, 233);
NSString *path = [[NSBundle mainBundle] pathForResource:#"click" ofType:#"mp3"];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];
[self.player prepareToPlay];
SingleTouchGesture *wheelRecogniser=[[SingleTouchGesture alloc] initWithTarget:self action:#selector(rotateWheel:)];
[self.view addGestureRecognizer:wheelRecogniser];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(void) rotate:(int) time
{
CABasicAnimation *topAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
topAnimation.duration=time;
topAnimation.fromValue= [NSNumber numberWithFloat:fromAngle];
topAnimation.toValue=[NSNumber numberWithFloat:toAngle];
topAnimation.delegate = self;
topAnimation.fillMode = kCAFillModeForwards;
topAnimation.removedOnCompletion = NO;
[wheelImage.layer addAnimation:topAnimation forKey:#"transform"];
fromAngle = toAngle;
}
-(void) rotateWheel:(SingleTouchGesture*) recogniser
{
toAngle += recogniser.rotation;
if (toStart)
{
if (recogniser.state == UIGestureRecognizerStateEnded)
{
NSLog(#"Speed === %f",recogniser.speed);
rotationMultiplier=[self getMultiplier:recogniser.speed];
NSLog(#"Rotation Multiplier..%f",rotationMultiplier);
toStart = NO;
NSLog(#"State Ended");
self.player.currentTime=0;
[self.player play];
if (recogniser.rotation>=0)
{
toAngle =fromAngle+(rotationMultiplier*3.14);
}
else
{
toAngle =fromAngle-(rotationMultiplier*3.14);
}
}
[self rotate:1];
}
else
{
if (recogniser.state==UIGestureRecognizerStateChanged) {
NSLog(#"continue...");
CGPoint pt=[recogniser locationInView:self.view];
float dis=[recogniser distanceBetweenPoints:center with:pt];
if (dis<radius)
{
if (recogniser.rotation>=0)
{
NSLog(#"Rotation value: +ve: %f",recogniser.rotation);
toStart = YES;
toAngle =fromAngle+(rotationMultiplier*3.14);
recogniser.rotation = 0;
}
else
{
NSLog(#"Rotation value: -ve: %f",recogniser.rotation);
toStart = YES;
toAngle=fromAngle-(rotationMultiplier*3.14);
recogniser.rotation = 0;
}
}
}
}
}
Here rotate method is calling multiple times.

Related

Pinch Zoom in and Zoom Out in Objective c

How to integrate the pinch zoom and zoom out in our apps, i am using imageview on scrollView
and my code is:
- (IBAction)handlePinchGesture:(UIGestureRecognizer *) recognizer {
if(zoomEnable == TRUE)
{
CGFloat factor = [(UIPinchGestureRecognizer *) recognizer scale];
CGFloat lastScaleFactor = 1;
//if the current factor is greater 1 --> zoom in
if (factor > 1) {
scrollView.transform = CGAffineTransformMakeScale(lastScaleFactor + (factor-1),lastScaleFactor + (factor-1));
scrollView.scrollEnabled = YES;
} else {
[UIView beginAnimations:#"animation" context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:scrollView cache:NO];
scrollView.transform = CGAffineTransformMakeScale(1,1);
[UIView commitAnimations];
}
isScrollable = TRUE;
}
}
Its start zooming every time from start i want if i zoom some then again it start when i stop zoom. Any help is highly Appreciated
Thanks;
You don't need to use UIGestureRecognizers, if you're using UIScrollView already. UIScrollView supports pinch to zoom.
For zooming and panning to work, the delegate must implement both viewForZoomingInScrollView: and scrollViewDidEndZooming:withView:atScale:; in addition, the maximum (maximumZoomScale) and minimum (minimumZoomScale) zoom scale must be different.
-(void)zoomingImages{
self.FullSizeScrollView.pagingEnabled =YES;
NSMutableArray *_scrollArray =[[NSMutableArray alloc]init];
// add images to scroll array
[_scrollArray addObject:self.image1];
[_scrollArray addObject:self.image2];
//now call init with frame function given below to set frame for each image in scroll view
for(int i =0 ;i<[_scrollArray count];i++){
ZoomingImageView *_imageScrollView = [[ZoomingImageView alloc]initWithFrame:CGRectMake(i*320, 0, 320, 460)];
_imageScrollView.captureView=self;
[self.checkFullSizeScrollView addSubview:_imageScrollView];
[_imageScrollView release];
self.checkFullSizeScrollView.contentSize = CGSizeMake((i*320)+320, 460);
}
[_scrollArray release];
}
#implementation ZoomingImageView
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
self.maximumZoomScale = 4;
self.minimumZoomScale = 1;
self.userInteractionEnabled = YES;
self.multipleTouchEnabled = YES;
self.delegate = self;
self.bouncesZoom = NO;
self.currentImageView.clipsToBounds=NO;
self.contentMode =UIViewContentModeScaleAspectFit;
UIImageView *zoomImageView_ =[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
self.currentImageView = zoomImageView_;
[zoomImageView_ release];
self.currentImageView.contentMode =UIViewContentModeScaleAspectFit;
self.currentImageView.userInteractionEnabled = YES;
self.currentImageView.multipleTouchEnabled = YES;
[self addSubview:self.currentImageView];}
return self;}

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.

animation with infinite scrollView

I have 5 pictures inside an infinite scrollView.
So in order to make that scrollView infinite/circular I positioned my images like this:
5 1 2 3 4 5 1
meaning: last picture first picture second picture.....last picture first picture
And in order for it to become infinite I have the following code:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
if(self.scrollView.contentOffset.x == 0){
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width*pathImages.count, 0, self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
else if (self.scrollView.contentOffset.x == self.view.frame.size.width*(pathImages.count+1)) {
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
}
which means that when I'm at the last picture the contentOffset of the scrollView is set to go to the first picture-in this way I get an infinite scrollView.
What I wanted next was for my scrollView to slide automatically-for this I set a timer which calls one method-onTimer:
- (void) onTimer{
NSLog(#"flip pages");
if(h < pathImages.count*self.view.frame.size.width)
{
h+= self.view.frame.size.width;
}
else
{
h=self.view.frame.size.width;
}
if(self.scrollView.contentOffset.x == 0){
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width*pathImages.count, 0, self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
if (self.scrollView.contentOffset.x == self.view.frame.size.width*pathImages.count)
{
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
else
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{ self.scrollView.contentOffset = CGPointMake(h, 0); }
completion:NULL];
}
This magic line:
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{ self.scrollView.contentOffset = CGPointMake(h, 0); }
completion:NULL];
does the scoll automatically with animation.
Everything is great except this:
after I view the last picture I should set the offset of scroll view in order to get back to the first picture with animation.
Well if I do that:
if (self.scrollView.contentOffset.x == self.view.frame.size.width*pathImages.count)
{
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{ [self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO]; }
completion:NULL];
}
after the last picture is viewed in order to get to the first picture...it loops through all the other pictures.
What I want is this:after I view the last picture to get me back to the first picture which should be loaded on screen using animation, but without viewing all the other pictures between them.Thanks
If I see this correctly, the problem is, that you again use the animation to scroll the view back to zero position. I believe you need to modify the last bit of code you posted to something like this:
if (self.scrollView.contentOffset.x == self.view.frame.size.width*pathImages.count)
{
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO];//no animation on returning
[self onTimer];//even if this code is already inside method "onTimer"
}
Rather then what you are doing try using a scrollview that displays only 3 to 5 images at the time (if they are fullscreen). If you will have many images in your application, it will crash because of high memory consumption. Try playing with this test example that does nearly what you want:
HEADER:
#import <Foundation/Foundation.h>
#interface IScrollView : UIScrollView <UIScrollViewDelegate> {
NSMutableArray *imagePaths;
UIImageView *imageViews[3];
NSInteger currentImage;
NSTimer *animationTimer;//weak link
}
#end
SOURCE:
#import "IScrollView.h"
#implementation IScrollView
- (UIImage *)imageFromResourcesWithName:(NSString *)name {
UIImage *ret = [[UIImage alloc] initWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:name]];
return [ret autorelease];
}
- (id)initWithFrame:(CGRect)frame {
if((self = [super initWithFrame:frame])) {
imagePaths = [[NSMutableArray alloc] init];
[imagePaths addObject:#"imag1.png"];
[imagePaths addObject:#"imag2.png"];
[imagePaths addObject:#"imag3.png"];
[imagePaths addObject:#"imag4.png"];
[imagePaths addObject:#"imag5.png"];
imageViews[0] = [[UIImageView alloc] initWithFrame:CGRectMake(320.0f*0, .0f, 320.0f, 480.0f)];
imageViews[1] = [[UIImageView alloc] initWithFrame:CGRectMake(320.0f*1, .0f, 320.0f, 480.0f)];
imageViews[2] = [[UIImageView alloc] initWithFrame:CGRectMake(320.0f*2, .0f, 320.0f, 480.0f)];
[self addSubview:imageViews[0]];
[self addSubview:imageViews[1]];
[self addSubview:imageViews[2]];
imageViews[0].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:0]];
imageViews[1].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:1]];
imageViews[2].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:2]];
currentImage = 1;
self.contentOffset = CGPointMake(320.0f*currentImage, .0f);
self.contentSize = CGSizeMake(3.0f*320.0f, 480.0f);
self.delegate = self;
animationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:#selector(scrollFragment) userInfo:nil repeats:YES];
}
return self;
}
- (void)repositionIfNeeded {
CGFloat offsetX = self.contentOffset.x;
NSInteger iCount = [imagePaths count];
if(offsetX > 320.0f*1.75f) {
self.contentOffset = CGPointMake(offsetX-320.0f, .0f);
imageViews[0].image = imageViews[1].image;
imageViews[1].image = imageViews[2].image;
NSInteger imageToLoad = currentImage+2;
if(imageToLoad>iCount-1)
imageToLoad -= iCount;
imageViews[2].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:imageToLoad]];
currentImage++;
if(currentImage>iCount-1)
currentImage -= iCount;
}
else if(offsetX < 320.0f*.25f) {
self.contentOffset = CGPointMake(offsetX+320.0f, .0f);
imageViews[2].image = imageViews[1].image;
imageViews[1].image = imageViews[0].image;
NSInteger imageToLoad = currentImage-2;
if(imageToLoad<0)
imageToLoad += iCount;
imageViews[0].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:imageToLoad]];
currentImage--;
if(currentImage<0)
currentImage += iCount;
}
}
- (void)scrollFragment {
self.contentOffset = CGPointMake(self.contentOffset.x+1.0, .0f);
[self repositionIfNeeded];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self repositionIfNeeded];
}
- (void)dealloc {
[imageViews[0] release];
[imageViews[1] release];
[imageViews[2] release];
[imagePaths release];
}
#end

Xcode: UIScrollView image gallery, having memory problems

I'm Trying to develop an UIScrollView Based Image gallery.
So let me explain what i'm trying to achieve here:
I want to a sliding presentation, that can show upto 140 image. ( You can swipe back and forth )
I've found information on the web, and i've been told the best way to do this is with a UIScrollview which has 3 UIImageViews which you create and remove from superview.
So i managed to create such a "sliding image gallery" with some help from a few tutorials :).
I've managed to upload the application to the ipad, start up the application and run it.
after i viewed about 50-70 slides the app crashes ( out of memory). My knowledge of Obj. C isn't that great .
You'll find the code below: it Prob. has something to do with releasing the images.
Improvements to the code would be really helpful
#import "ParatelPresentationViewController.h"
//Define the UIView ( we need 3 Image Views left, mid right);
#interface SlideShowView : UIView
{
NSArray * mImages;
UIImageView * mLeftImageView;
UIImageView * mCurrentImageView;
UIImageView * mRightImageView;
NSUInteger mCurrentImage;
BOOL mSwiping;
CGFloat mSwipeStart;
}
- (id)initWithImages:(NSArray *)inImages;
#end // SlideShowView
#pragma mark -
#implementation SlideShowView
- (UIImageView *)createImageView:(NSUInteger)inImageIndex
{
if (inImageIndex >= [mImages count])
{
return nil;
}
UIImageView * result = [[UIImageView alloc] initWithImage:[mImages objectAtIndex:inImageIndex]];
result.opaque = YES;
result.userInteractionEnabled = NO;
result.backgroundColor = [UIColor blackColor];
result.contentMode = UIViewContentModeScaleAspectFit;
result.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight ;
return result;
}
- (id)initWithImages:(NSArray *)inImages
{
if (self = [super initWithFrame:CGRectZero])
{
mImages = [inImages retain];
NSUInteger imageCount = [inImages count];
NSLog(#"hoeveel foto's: %i");
if (imageCount > 0)
{
mCurrentImageView = [self createImageView:0];
[self addSubview:mCurrentImageView];
if (imageCount > 1)
{
mRightImageView = [self createImageView:1];
[self addSubview:mRightImageView];
}
}
self.opaque = YES;
self.backgroundColor = [UIColor blueColor];
self.contentMode = UIViewContentModeScaleAspectFit;
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
return self;
}
- (void)dealloc
{
[mImages release];
[super dealloc];
}
- (void)layoutSubviews
{
if (mSwiping)
return;
//CGSize contentSize = self.frame.size; // Enable when you use content.width/height
//self.backgroundColor = [UIColor redColor];
mLeftImageView.frame = CGRectMake(-1024, 0.0f, 1024, 748);// (-1024, 0.0f, 1024, 748) can be replaced by (-contentSize.width, 0.0f, contentSize.width, contentSize.height);
mCurrentImageView.frame = CGRectMake(0.0f, 0.0f, 1024, 748);
mRightImageView.frame = CGRectMake(1024, 0.0f, 1024, 748);
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] != 1)
return;
mSwipeStart = [[touches anyObject] locationInView:self].x;
mSwiping = YES;
mLeftImageView.hidden = NO;
mCurrentImageView.hidden = NO;
mRightImageView.hidden = NO;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (! mSwiping || [touches count] != 1)
return;
CGFloat swipeDistance = [[touches anyObject] locationInView:self].x - mSwipeStart;
//CGSize contentSize = self.frame.size;
mLeftImageView.frame = CGRectMake(swipeDistance - 1024, 0.0f, 1024, 748);
mCurrentImageView.frame = CGRectMake(swipeDistance, 0.0f, 1024, 748);
mRightImageView.frame = CGRectMake(swipeDistance + 1024, 0.0f, 1024, 748);
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (! mSwiping)
return;
//CGSize contentSize = self.frame.size;
NSUInteger count = [mImages count];
CGFloat swipeDistance = [[touches anyObject] locationInView:self].x - mSwipeStart;
if (mCurrentImage > 0 && swipeDistance > 50.0f)
{
mRightImageView.image = nil;
//[mRightImageView.image release];
[mRightImageView removeFromSuperview];
[mRightImageView release];
//mRightImageView = nil;
//NSLog(#"Count of mRight : %i",[mRightImageView retainCount]);
mRightImageView = mCurrentImageView;
mCurrentImageView = mLeftImageView;
mCurrentImage--;
if (mCurrentImage > 0)
{
mLeftImageView = [self createImageView:mCurrentImage - 1];
mLeftImageView.hidden = YES;
[self addSubview:mLeftImageView];
}
else
{
mLeftImageView = nil;
}
}
else if (mCurrentImage < count - 1 && swipeDistance < -50.0f)
{
mLeftImageView.image = nil;
//[mLeftImageView.image release];
[mLeftImageView removeFromSuperview];
[mLeftImageView release];
//mLeftImageView = nil;
mLeftImageView = mCurrentImageView;
mCurrentImageView = mRightImageView;
mCurrentImage++;
if (mCurrentImage < count - 1)
{
mRightImageView = [self createImageView:mCurrentImage + 1];
mRightImageView.hidden = YES;
[self addSubview:mRightImageView];
NSLog(#"Count of mRight : %i",[mRightImageView.image retainCount]);
}
else
{
mRightImageView = nil;
}
}
[UIView beginAnimations:#"swipe" context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.3f];
mLeftImageView.frame = CGRectMake(-1024, 0.0f, 1024, 748);
mCurrentImageView.frame = CGRectMake(0.0f, 0.0f, 1024, 748);
mRightImageView.frame = CGRectMake(1024, 0.0f, 1024, 748);
[UIView commitAnimations];
mSwiping = NO;
}
#end // SlideShowView
#pragma mark -
#implementation ParatelPresentationViewController
- (id)init
{
if (self = [super initWithNibName:nil bundle:nil])
{
NSMutableArray *Displayimages = [[NSMutableArray alloc]init];
int i;
for(i=0 ; i<139 ; i++) {
NSString *tempString = [NSString stringWithFormat:#"Dia%d", i+1];
NSLog(#"Dia%d.jpg", i+1);
NSString *imageFile = [[NSBundle mainBundle] pathForResource:tempString ofType:#"JPG"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:imageFile];
if (fileExists){
[Displayimages addObject:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:tempString ofType:#"JPG"]]];
NSLog(#"img");
}else {
break;
}
}
//NSArray * images = [NSArray arrayWithObjects:[UIImage imageNamed:#"1.jpg"], [UIImage imageNamed:#"2.jpg"], [UIImage imageNamed:#"3.jpg"], [UIImage imageNamed:#"4.jpg"], [UIImage imageNamed:#"5.jpg"], nil];
//NSLog(#"Objects Img = %#", images);
NSLog(#"Images %#",Displayimages);
self.view = [[[SlideShowView alloc] initWithImages:Displayimages] autorelease];
[Displayimages release];
}
return self;
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
//return YES;
return UIInterfaceOrientationIsLandscape (interfaceOrientation);
}
#end
If you would find a solution or tips, all are welcome !
Thanks in advance
kind regards Bart !
You definitely have a memory leak in createImageView:. You will have to change
return result;
to
return [result autorelease];
There might be more leaks, but that's an obvious one.
Johannes

Fitting an Image to Screen on Rotation iPhone / iPad?

I have been playing around with one of the iPhone examples from Apple' web site (ScrollViewSuite) . I am trying to tweak it a bit so that when I rotate the the iPad the image will fit into the screen in landscape mode vertical. I have been successful in getting the image to rotate, but the image is larger than the height of the landscape screen, so the bottom is below the screen. I would like to image to scale to the height of the landscape screen.
I have been playing around with various autoSizingMask attributes without success.
The imageView is called "zoomView" this is the actual image which loads into a scrollView called imageScrollView.
I am trying to achieve the screen to rotate and look like this.... sorry only 1 link allowed new user :(
olsonvox.com/photos/correct.png
However, this is what My screen is looking like.
http://www.olsonvox.com/photos/incorrect.png
I would really appreciate some advice or guidance. Below is the RootViewController.m for the project.
Blade
#
import "RootViewController.h"
#define ZOOM_VIEW_TAG 100
#define ZOOM_STEP 1.5
#define THUMB_HEIGHT 150
#define THUMB_V_PADDING 25
#define THUMB_H_PADDING 25
#define CREDIT_LABEL_HEIGHT 25
#define AUTOSCROLL_THRESHOLD 30
#interface RootViewController (ViewHandlingMethods)
- (void)toggleThumbView;
- (void)pickImageNamed:(NSString *)name;
- (NSArray *)imageNames;
- (void)createThumbScrollViewIfNecessary;
- (void)createSlideUpViewIfNecessary;
#end
#interface RootViewController (AutoscrollingMethods)
- (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb;
- (void)autoscrollTimerFired:(NSTimer *)timer;
- (void)legalizeAutoscrollDistance;
- (float)autoscrollDistanceForProximityToEdge:(float)proximity;
#end
#interface RootViewController (UtilityMethods)
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
#end
#implementation RootViewController
- (void)loadView {
[super loadView];
imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view]bounds]];
// this code makes the image resize to the width and height properly.
imageScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin| UIViewAutoresizingFlexibleBottomMargin| UIViewAutoresizingFlexibleBottomMargin;
// TRY SETTNG CENTER HERE SOMEHOW>....
[imageScrollView setBackgroundColor:[UIColor blackColor]];
[imageScrollView setDelegate:self];
[imageScrollView setBouncesZoom:YES];
[[self view] addSubview:imageScrollView];
[self toggleThumbView];
// intitializes with the first image.
[self pickImageNamed:#"lookbook1"];
}
- (void)dealloc {
[imageScrollView release];
[slideUpView release];
[thumbScrollView release];
[super dealloc];
}
#pragma mark UIScrollViewDelegate methods
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
UIView *view = nil;
if (scrollView == imageScrollView) {
view = [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}
return view;
}
/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
}
#pragma mark TapDetectingImageViewDelegate methods
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotSingleTapAtPoint:(CGPoint)tapPoint {
// Single tap shows or hides drawer of thumbnails.
[self toggleThumbView];
}
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotDoubleTapAtPoint:(CGPoint)tapPoint {
// double tap zooms in
float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[imageScrollView zoomToRect:zoomRect animated:YES];
}
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotTwoFingerTapAtPoint:(CGPoint)tapPoint {
// two-finger tap zooms out
float newScale = [imageScrollView zoomScale] / ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[imageScrollView zoomToRect:zoomRect animated:YES];
}
#pragma mark ThumbImageViewDelegate methods
- (void)thumbImageViewWasTapped:(ThumbImageView *)tiv {
[self pickImageNamed:[tiv imageName]];
[self toggleThumbView];
}
- (void)thumbImageViewStartedTracking:(ThumbImageView *)tiv {
[thumbScrollView bringSubviewToFront:tiv];
}
// CONTROLS DRAGGING AND DROPPING THUMBNAILS...
- (void)thumbImageViewMoved:(ThumbImageView *)draggingThumb {
// check if we've moved close enough to an edge to autoscroll, or far enough away to stop autoscrolling
[self maybeAutoscrollForThumb:draggingThumb];
/* The rest of this method handles the reordering of thumbnails in the thumbScrollView. See */
/* ThumbImageView.h and ThumbImageView.m for more information about how this works. */
// we'll reorder only if the thumb is overlapping the scroll view
if (CGRectIntersectsRect([draggingThumb frame], [thumbScrollView bounds])) {
BOOL draggingRight = [draggingThumb frame].origin.x > [draggingThumb home].origin.x ? YES : NO;
/* we're going to shift over all the thumbs who live between the home of the moving thumb */
/* and the current touch location. A thumb counts as living in this area if the midpoint */
/* of its home is contained in the area. */
NSMutableArray *thumbsToShift = [[NSMutableArray alloc] init];
// get the touch location in the coordinate system of the scroll view
CGPoint touchLocation = [draggingThumb convertPoint:[draggingThumb touchLocation] toView:thumbScrollView];
// calculate minimum and maximum boundaries of the affected area
float minX = draggingRight ? CGRectGetMaxX([draggingThumb home]) : touchLocation.x;
float maxX = draggingRight ? touchLocation.x : CGRectGetMinX([draggingThumb home]);
// iterate through thumbnails and see which ones need to move over
for (ThumbImageView *thumb in [thumbScrollView subviews]) {
// skip the thumb being dragged
if (thumb == draggingThumb) continue;
// skip non-thumb subviews of the scroll view (such as the scroll indicators)
if (! [thumb isMemberOfClass:[ThumbImageView class]]) continue;
float thumbMidpoint = CGRectGetMidX([thumb home]);
if (thumbMidpoint >= minX && thumbMidpoint <= maxX) {
[thumbsToShift addObject:thumb];
}
}
// shift over the other thumbs to make room for the dragging thumb. (if we're dragging right, they shift to the left)
float otherThumbShift = ([draggingThumb home].size.width + THUMB_H_PADDING) * (draggingRight ? -1 : 1);
// as we shift over the other thumbs, we'll calculate how much the dragging thumb's home is going to move
float draggingThumbShift = 0.0;
// send each of the shifting thumbs to its new home
for (ThumbImageView *otherThumb in thumbsToShift) {
CGRect home = [otherThumb home];
home.origin.x += otherThumbShift;
[otherThumb setHome:home];
[otherThumb goHome];
draggingThumbShift += ([otherThumb frame].size.width + THUMB_H_PADDING) * (draggingRight ? 1 : -1);
}
// change the home of the dragging thumb, but don't send it there because it's still being dragged
CGRect home = [draggingThumb home];
home.origin.x += draggingThumbShift;
[draggingThumb setHome:home];
}
}
- (void)thumbImageViewStoppedTracking:(ThumbImageView *)tiv {
// if the user lets go of the thumb image view, stop autoscrolling
[autoscrollTimer invalidate];
autoscrollTimer = nil;
}
#pragma mark Autoscrolling methods
- (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb {
autoscrollDistance = 0;
// only autoscroll if the thumb is overlapping the thumbScrollView
if (CGRectIntersectsRect([thumb frame], [thumbScrollView bounds])) {
CGPoint touchLocation = [thumb convertPoint:[thumb touchLocation] toView:thumbScrollView];
float distanceFromLeftEdge = touchLocation.x - CGRectGetMinX([thumbScrollView bounds]);
float distanceFromRightEdge = CGRectGetMaxX([thumbScrollView bounds]) - touchLocation.x;
if (distanceFromLeftEdge < AUTOSCROLL_THRESHOLD) {
autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromLeftEdge] * -1; // if scrolling left, distance is negative
} else if (distanceFromRightEdge < AUTOSCROLL_THRESHOLD) {
autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromRightEdge];
}
}
// if no autoscrolling, stop and clear timer
if (autoscrollDistance == 0) {
[autoscrollTimer invalidate];
autoscrollTimer = nil;
}
// otherwise create and start timer (if we don't already have a timer going)
else if (autoscrollTimer == nil) {
autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:thumb
repeats:YES];
}
}
- (float)autoscrollDistanceForProximityToEdge:(float)proximity {
// the scroll distance grows as the proximity to the edge decreases, so that moving the thumb
// further over results in faster scrolling.
return ceilf((AUTOSCROLL_THRESHOLD - proximity) / 5.0);
}
- (void)legalizeAutoscrollDistance {
// makes sure the autoscroll distance won't result in scrolling past the content of the scroll view
float minimumLegalDistance = [thumbScrollView contentOffset].x * -1;
float maximumLegalDistance = [thumbScrollView contentSize].width - ([thumbScrollView frame].size.width + [thumbScrollView contentOffset].x);
autoscrollDistance = MAX(autoscrollDistance, minimumLegalDistance);
autoscrollDistance = MIN(autoscrollDistance, maximumLegalDistance);
}
- (void)autoscrollTimerFired:(NSTimer*)timer {
[self legalizeAutoscrollDistance];
// autoscroll by changing content offset
CGPoint contentOffset = [thumbScrollView contentOffset];
contentOffset.x += autoscrollDistance;
[thumbScrollView setContentOffset:contentOffset];
// adjust thumb position so it appears to stay still
ThumbImageView *thumb = (ThumbImageView *)[timer userInfo];
[thumb moveByOffset:CGPointMake(autoscrollDistance, 0)];
}
#pragma mark View handling methods
- (void)toggleThumbView {
[self createSlideUpViewIfNecessary]; // no-op if slideUpView has already been created
CGRect frame = [slideUpView frame];
if (thumbViewShowing) {
frame.origin.y = 0;
} else {
frame.origin.y = -225;
}
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[slideUpView setFrame:frame];
[UIView commitAnimations];
thumbViewShowing = !thumbViewShowing;
}
- (void)pickImageNamed:(NSString *)name {
// first remove previous image view, if any
[[imageScrollView viewWithTag:ZOOM_VIEW_TAG] removeFromSuperview];
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", name]];
TapDetectingImageView *zoomView = [[TapDetectingImageView alloc] initWithImage:image];
zoomView.autoresizingMask = UIViewAutoresizingFlexibleWidth ;
[zoomView setDelegate:self];
[zoomView setTag:ZOOM_VIEW_TAG];
[imageScrollView addSubview:zoomView];
[imageScrollView setContentSize:[zoomView frame].size];
[zoomView release];
// choose minimum scale so image width fits screen
float minScale = [imageScrollView frame].size.width / [zoomView frame].size.width;
[imageScrollView setMinimumZoomScale:minScale];
[imageScrollView setZoomScale:minScale];
[imageScrollView setContentOffset:CGPointZero];
}
- (NSArray *)imageNames {
// the filenames are stored in a plist in the app bundle, so create array by reading this plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"Images" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:path];
NSString *error; NSPropertyListFormat format;
NSArray *imageNames = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
if (!imageNames) {
NSLog(#"Failed to read image names. Error: %#", error);
[error release];
}
return imageNames;
}
- (void)createSlideUpViewIfNecessary {
if (!slideUpView) {
[self createThumbScrollViewIfNecessary];
CGRect bounds = [[self view] bounds];
float thumbHeight = [thumbScrollView frame].size.height;
float labelHeight = CREDIT_LABEL_HEIGHT;
// create label giving credit for images
UILabel *creditLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, thumbHeight, bounds.size.width, labelHeight)];
[creditLabel setBackgroundColor:[UIColor clearColor]];
[creditLabel setTextColor:[UIColor whiteColor]];
// [creditLabel setFont:[UIFont fontWithName:#"Helvetica" size:16]];
// [creditLabel setText:#"SAMPLE TEXT"];
[creditLabel setTextAlignment:UITextAlignmentCenter];
// create container view that will hold scroll view and label
CGRect frame = CGRectMake(0.0, -225.00, bounds.size.width+256, thumbHeight + labelHeight);
slideUpView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
slideUpView = [[UIView alloc] initWithFrame:frame];
[slideUpView setBackgroundColor:[UIColor blackColor]];
[slideUpView setOpaque:NO];
[slideUpView setAlpha:.75];
[[self view] addSubview:slideUpView];
// add subviews to container view
[slideUpView addSubview:thumbScrollView];
[slideUpView addSubview:creditLabel];
[creditLabel release];
}
}
- (void)createThumbScrollViewIfNecessary {
if (!thumbScrollView) {
float scrollViewHeight = THUMB_HEIGHT + THUMB_V_PADDING;
float scrollViewWidth = [[self view] bounds].size.width;
thumbScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, scrollViewWidth, scrollViewHeight)];
[thumbScrollView setCanCancelContentTouches:NO];
[thumbScrollView setClipsToBounds:NO];
// now place all the thumb views as subviews of the scroll view
// and in the course of doing so calculate the content width
float xPosition = THUMB_H_PADDING;
for (NSString *name in [self imageNames]) {
UIImage *thumbImage = [UIImage imageNamed:[NSString stringWithFormat:#"%#_thumb.jpg", name]];
if (thumbImage) {
ThumbImageView *thumbView = [[ThumbImageView alloc] initWithImage:thumbImage];
[thumbView setDelegate:self];
[thumbView setImageName:name];
CGRect frame = [thumbView frame];
frame.origin.y = THUMB_V_PADDING;
frame.origin.x = xPosition;
[thumbView setFrame:frame];
[thumbView setHome:frame];
[thumbScrollView addSubview:thumbView];
[thumbView release];
xPosition += (frame.size.width + THUMB_H_PADDING);
}
}
[thumbScrollView setContentSize:CGSizeMake(xPosition, scrollViewHeight)];
}
}
#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;
}
#pragma mark -
#pragma mark Rotation support
// Ensure that the view controller supports rotation and that the split view can therefore show in both portrait and landscape.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
#end
If you've set up your UIScrollView in a Nib file, make sure it is resizing properly when rotated (Use the Autosizing controls in the Size Inspector in Interface Builder: Both sets of arrows inside the box should be red)
Then use this to rescale when the iPad changes orientation:
- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration{
//if your UIImageView is called zoomView use this
CGRect zoomRect=CGRectMake(0,0,zoomView.frame.size.width, zoomView.frame.size.height);
[scrollView zoomToRect:zoomRect animated:YES];}
(Sorry about the bad placement of the {} but it wasn't pasting properly as code for some reason)
Hope this helps!