NSWindow flip animation (easy and universal) - cocoa

How to make flip animation for OS X application windows without complex coding?

Finally, I did it. I have created object that work with NSWindowController objects instead of NSWidows.
ALWindowFlipAnimator.h
#import <Foundation/Foundation.h>
//............................................................................................................
// Shorten macroes:
#define FLIPANIMATOR [ALWindowFlipAnimator sharedWindowFlipAnimator]
//............................................................................................................
// Window flip direction:
typedef NS_ENUM(NSUInteger, ALFlipDirection)
{
ALFlipDirectionLeft,
ALFlipDirectionRight,
ALFlipDirectionUp,
ALFlipDirectionDown
};
#interface ALWindowFlipAnimator : NSObject
+(ALWindowFlipAnimator *)sharedWindowFlipAnimator;
-(void)flipToWindowNibName:(NSString *)nibName direction:(ALFlipDirection)direction;
#end
ALWindowFlipAnimator.m
#import "ALWindowFlipAnimator.h"
#import <QuartzCore/QuartzCore.h>
#implementation ALWindowFlipAnimator
{
NSWindowController *_currentWindowController; // Current window controller
NSWindowController *_nextWindowController; // Next window controller to flip to
NSWindow *_animationWindow; // Window where flip animation plays
}
//============================================================================================================
// Initialize flip window controller
//============================================================================================================
-(id)init
{
self = [super init];
if (self)
{
_currentWindowController = nil;
_nextWindowController = nil;
_animationWindow = nil;
}
return self;
}
//============================================================================================================
// Create shared flip window manager
//============================================================================================================
+(ALWindowFlipAnimator *)sharedWindowFlipAnimator
{
static ALWindowFlipAnimator *wfa = nil;
if (!wfa) wfa = [[ALWindowFlipAnimator alloc] init];
return wfa;
}
//============================================================================================================
// Flip to window with selected NIB file name from the current one
//============================================================================================================
-(void)flipToWindowNibName:(NSString *)nibName direction:(ALFlipDirection)direction
{
if (!_currentWindowController || ![[_currentWindowController window] isVisible])
{
// No current window controller or window is closed
_currentWindowController = [[NSClassFromString(nibName) alloc] initWithWindowNibName:nibName];
[_currentWindowController showWindow:self];
}
else
{
if ([[_currentWindowController className] isEqualToString:nibName])
// Bring current window to front
[[_currentWindowController window] makeKeyAndOrderFront:self];
else
{
// Flip to new window
_nextWindowController = [[NSClassFromString(nibName) alloc] initWithWindowNibName:nibName];
[self flipToNextWindowControllerDirection:direction];
}
}
}
#pragma mark - Flip animation
#define DEF_DURATION 2.0 // Animation duration
#define DEF_SCALE 1.2 // Scaling factor for animation window (_animationWindow)
//============================================================================================================
// Start window flipping animation
//============================================================================================================
-(void)flipToNextWindowControllerDirection:(ALFlipDirection)direction
{
NSWindow *currentWindow = [_currentWindowController window];
NSWindow *nextWindow = [_nextWindowController window];
NSView *currentWindowView = [currentWindow.contentView superview];
NSView *nextWindowView = [nextWindow.contentView superview];
// Create window for animation
CGFloat maxWidth = MAX(currentWindow.frame.size.width, nextWindow.frame.size.width);
CGFloat maxHeight = MAX(currentWindow.frame.size.height, nextWindow.frame.size.height);
CGFloat xscale = DEF_SCALE * 2.0;
maxWidth += maxWidth * xscale;
maxHeight += maxHeight * xscale;
CGRect animationFrame = CGRectMake(NSMidX(currentWindow.frame) - (maxWidth / 2),
NSMidY(currentWindow.frame) - (maxHeight / 2),
maxWidth, maxHeight);
_animationWindow = [[NSWindow alloc] initWithContentRect:NSRectFromCGRect(animationFrame)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[_animationWindow setOpaque:NO];
[_animationWindow setHasShadow:NO];
[_animationWindow setBackgroundColor:[NSColor clearColor]];
[_animationWindow.contentView setWantsLayer:YES];
[_animationWindow setLevel:NSScreenSaverWindowLevel];
// Move next window closer to the current one
CGRect nextFrame = CGRectMake(NSMidX(currentWindow.frame) - (NSWidth(nextWindow.frame) / 2 ),
NSMaxY(currentWindow.frame) - NSHeight(nextWindow.frame),
NSWidth(nextWindow.frame), NSHeight(nextWindow.frame));
[nextWindow setFrame:NSRectFromCGRect(nextFrame) display:NO];
// Make snapshots of current and next windows
[CATransaction begin];
CALayer *currentWindowSnapshot = [self snapshotToImageLayerFromView:currentWindowView];
CALayer *nextWindowSnapshot = [self snapshotToImageLayerFromView:nextWindowView];
[CATransaction commit];
currentWindowSnapshot.frame = [self rect:currentWindowView.frame
fromView:currentWindowView
toView:[_animationWindow contentView]];
nextWindowSnapshot.frame = [self rect:nextWindowView.frame
fromView:nextWindowView
toView:[_animationWindow contentView]];
// Create 3D transform matrix to snapshots
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -(1.0 / 1500.0);
currentWindowSnapshot.transform = transform;
nextWindowSnapshot.transform = transform;
// Add snapshots to animation window
[CATransaction begin];
[[_animationWindow.contentView layer] addSublayer:currentWindowSnapshot];
[[_animationWindow.contentView layer] addSublayer:nextWindowSnapshot];
[CATransaction commit];
[_animationWindow makeKeyAndOrderFront:nil];
// Animation for snapshots
[CATransaction begin];
CAAnimation *currentSnapshotAnimation = [self animationWithDuration:(DEF_DURATION * 0.5) flip:YES direction:direction];
CAAnimation *nextSnapshotAnimation = [self animationWithDuration:(DEF_DURATION * 0.5) flip:NO direction:direction];
[CATransaction commit];
// Start animation
nextSnapshotAnimation.delegate = self;
[currentWindow orderOut:nil];
[CATransaction begin];
[currentWindowSnapshot addAnimation:currentSnapshotAnimation forKey:#"flipAnimation"];
[nextWindowSnapshot addAnimation:nextSnapshotAnimation forKey:#"flipAnimation"];
[CATransaction commit];
}
//============================================================================================================
// Convert rectangle from one view coordinates to another
//============================================================================================================
-(CGRect)rect:(NSRect)rect fromView:(NSView *)fromView toView:(NSView *)toView
{
rect = [fromView convertRect:rect toView:nil];
rect = [fromView.window convertRectToScreen:rect];
rect = [toView.window convertRectFromScreen:rect];
rect = [toView convertRect:rect fromView:nil];
return NSRectToCGRect(rect);
}
//============================================================================================================
// Get snapshot of selected view as layer with bitmap image
//============================================================================================================
-(CALayer *)snapshotToImageLayerFromView:(NSView*)view
{
// Make view snapshot
NSBitmapImageRep *snapshot = [view bitmapImageRepForCachingDisplayInRect:view.bounds];
[view cacheDisplayInRect:view.bounds toBitmapImageRep:snapshot];
// Convert snapshot to layer
CALayer *layer = [CALayer layer];
layer.contents = (id)snapshot.CGImage;
layer.doubleSided = NO;
// Add shadow of window to snapshot
[layer setShadowOpacity:0.5];
[layer setShadowOffset:CGSizeMake(0.0, -10.0)];
[layer setShadowRadius:15.0];
return layer;
}
//============================================================================================================
// Create animation
//============================================================================================================
-(CAAnimation *)animationWithDuration:(CGFloat)time flip:(BOOL)flip direction:(ALFlipDirection)direction
{
// Set flip direction
NSString *keyPath = #"transform.rotation.y";
if (direction == ALFlipDirectionUp || direction == ALFlipDirectionDown) keyPath = #"transform.rotation.x";
CABasicAnimation *flipAnimation = [CABasicAnimation animationWithKeyPath:keyPath];
CGFloat startValue = flip ? 0.0 : -M_PI;
CGFloat endValue = flip ? M_PI : 0.0;
if (direction == ALFlipDirectionLeft || direction == ALFlipDirectionUp)
{
startValue = flip ? 0.0 : M_PI;
endValue = flip ? -M_PI : 0.0;
}
flipAnimation.fromValue = [NSNumber numberWithDouble:startValue];
flipAnimation.toValue = [NSNumber numberWithDouble:endValue];
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.toValue = [NSNumber numberWithFloat:DEF_SCALE];
scaleAnimation.duration = time * 0.5;
scaleAnimation.autoreverses = YES;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:flipAnimation, scaleAnimation, nil];
animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animationGroup.duration = time;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion = NO;
return animationGroup;
}
//============================================================================================================
// Flip animation did finish
//============================================================================================================
-(void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
{
[[_nextWindowController window] makeKeyAndOrderFront:nil];
[_animationWindow orderOut:nil];
_animationWindow = nil;
_currentWindowController = _nextWindowController;
}
#end
How to use:
Create some new NSWindowController objects with NIBs in your project
Call [FLIPANIMATOR flipToWindowNibName:#"SecondWindowController" direction:ALFlipDirectionRight]; to flip to second window, or [FLIPANIMATOR flipToWindowNibName:#"FirstWindowController" direction:ALFlipDirectionLeft]; to return back
Link QuarzCore.framework to your project
That's all!

Related

GPUImageStillCamera image preview jumps when taking a photo

I am taking a square cropped photo with GPUImageStillCamera and allowing the user to zoom the camera. When the user clicks to take a picture the camera jumps forward for a split second (as if the camera zoomed in even further past the area the user zoomed to and then immediately returns to the correct crop once the image is returned to screen). This only happens when the user has zoomed the camera. If they have not zoomed the camera the flicker/jump does not happen. (The image return has the correct crop whether or not the user has zoomed).
Thoughts?
Creating camera and adding square crop
//Add in filters
stillCamera = [[GPUImageStillCamera alloc] initWithSessionPreset:AVCaptureSessionPreset1280x720 cameraPosition:AVCaptureDevicePositionBack];
stillCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
//Creating a square crop filter
cropFilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(0.f, (720.0f/1280.0f)/2.0f, 1.f, (720.0f/1280.0f))];
Image zoom method
-(void)imagePinch:(UIPinchGestureRecognizer *)recognizer{ //Controlling the zoom scale as the user pinches the live preview
if (recognizer.state == UIGestureRecognizerStateBegan) {
zoomOutAdder = 0.0f;
if (currentScale > 2) {
zoomOutAdder = currentScale;
}
}
float addition = (recognizer.scale - lastScale);
if (addition > 0) {
addition = addition *1.7;
}
if (addition < 0) {
addition = addition *(1.7+zoomOutAdder);
}
currentScale = currentScale +addition;
lastScale = recognizer.scale;
if (currentScale < 1) {
currentScale = 1;
}
if (currentScale > 4) {
currentScale =4;
}
if (currentScale == 1) {
zoomOutAdder = 0.0f;
}
cameraImagePreview.transform = CGAffineTransformMakeScale(currentScale, currentScale);
if (recognizer.state == UIGestureRecognizerStateEnded) {
lastScale = 1.0f;
}
Take a photo method
//Adjust crop based on zoom scale of the user
CGFloat zoomReciprocal = 1.0f / currentScale;
CGPoint offset = CGPointMake(((1.0f - zoomReciprocal) / 2.0f), (((1.0f- zoomReciprocal)*(720.0f/1280.0f)) / 2.0f) + ((720.0f/1280.0f)/2)) ;
CGRect newCrop = cropFilter.cropRegion;
newCrop.origin.x = offset.x;
newCrop.origin.y = offset.y;
newCrop.size.width = cropFilter.cropRegion.size.width * zoomReciprocal;
newCrop.size.height = cropFilter.cropRegion.size.height *zoomReciprocal;
cropFilter.cropRegion = newCrop;
*/
//Place photo inside an image preview view for the user to decide if they want to keep it.
[stillCamera capturePhotoAsImageProcessedUpToFilter:cropFilter withOrientation:imageOrientation withCompletionHandler:^(UIImage *processedImage, NSError *error) {
//Pause the current camera
[stillCamera pauseCameraCapture];
//Rest of method
ADDED METHODS
- (void) flipCamera {
if (stillCamera.cameraPosition != AVCaptureDevicePositionFront) {
[UIView animateWithDuration:.65 animations:^{
flipCamera.transform = CGAffineTransformMakeScale(-1, 1);
}];
} else {
[UIView animateWithDuration:.65 animations:^{
flipCamera.transform = CGAffineTransformMakeScale(1, 1);
}];
}
[self performSelector:#selector(rotateCamera) withObject:0 afterDelay:.2];
}
- (void) rotateCamera {
[stillCamera rotateCamera];
//Adjust flash settings as needed
[stillCamera.inputCamera lockForConfiguration:nil];
if (stillCamera.cameraPosition != AVCaptureDevicePositionFront) {
[stillCamera.inputCamera setFlashMode:AVCaptureFlashModeOff];
}
NSAttributedString *attributedFlash =
[[NSAttributedString alloc]
initWithString:#"off"
attributes:
#{
NSFontAttributeName : [UIFont fontWithName:#"Roboto-Regular" size:13.0f],
NSForegroundColorAttributeName : [UIColor colorWithWhite:1 alpha:.55],
NSKernAttributeName : #(.25f)
}];
flashLabel.attributedText = attributedFlash;
[UIView animateWithDuration:.2 animations:^{
[flash setTintColor:[UIColor colorWithWhite:1 alpha:.55]];
}];
[stillCamera.inputCamera unlockForConfiguration];
}
- (void) changeFlash {
if (stillCamera.cameraPosition == AVCaptureDevicePositionFront) {//no flash available on front of camera
return;
}
[stillCamera.inputCamera lockForConfiguration:nil];
if (stillCamera.inputCamera.flashMode == AVCaptureFlashModeOff) {
[stillCamera.inputCamera setFlashMode:AVCaptureFlashModeOn];
[self animateFlashWithTintColor:[UIColor colorWithWhite:1 alpha:1] andString:#"on"];
} else if (stillCamera.inputCamera.flashMode == AVCaptureFlashModeOn) {
[stillCamera.inputCamera setFlashMode:AVCaptureFlashModeOff];
[self animateFlashWithTintColor:[UIColor colorWithWhite:1 alpha:.55] andString:#"off"];
}
[stillCamera.inputCamera unlockForConfiguration];
}
- (void) animateFlashWithTintColor:(UIColor *)color andString:(NSString *)text {
//Set new text
NSAttributedString *attributedFlash =
[[NSAttributedString alloc]
initWithString:text
attributes:
#{
NSFontAttributeName : [UIFont fontWithName:#"Roboto-Regular" size:13.0f],
NSForegroundColorAttributeName : [UIColor colorWithWhite:1 alpha:.55],
NSKernAttributeName : #(.25f)
}];
flashLabel.attributedText = attributedFlash;
float duration = .7;
[UIView animateKeyframesWithDuration:duration delay:0 options:0 animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:duration animations:^{
[flash setTintColor:color];
}];
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:.7/duration animations:^{
flash.transform = CGAffineTransformMakeRotation(M_PI);
}];
}completion:^(BOOL finished){
flash.transform = CGAffineTransformIdentity;
}];
}
-(void) usePhoto {
if ([ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusAuthorized){
NSLog(#"Do Not Have Right To Save to Photo Library");
}
//Save Image to Phone Album & save image
UIImageWriteToSavedPhotosAlbum(takenPhoto.image, nil, nil, nil);
//Save Image to Delegate
[self.delegate saveImageToDatabase:takenPhoto.image];
[self performSelector:#selector(dismissCamera) withObject:0 afterDelay:.4];
}
Some additional code showing the creation of the the various camera elements used to capture a photo.
centerPoint = CGPointMake(self.view.frame.size.width/2, (cameraHolder.frame.size.height+50+self.view.frame.size.height)/2);
cameraImagePreview = [[GPUImageView alloc] initWithFrame:CGRectMake(0, 0, cameraHolder.frame.size.width, cameraHolder.frame.size.width)];
[cameraHolder addSubview:cameraImagePreview];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTouch:)];
[cameraImagePreview addGestureRecognizer:tapGesture];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(imagePinch:)];
[cameraImagePreview addGestureRecognizer:pinchGesture];
float scaleForView = self.view.frame.size.width/720.0;
fullCameraFocusPoint = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 1280*scaleForView)];
fullCameraFocusPoint.center = CGPointMake(cameraHolder.frame.size.width/2, (cameraHolder.frame.size.width/2)+50);
[self.view insertSubview:fullCameraFocusPoint atIndex:0];
takenPhoto = [[UIImageView alloc]initWithFrame:cameraHolder.frame];
takenPhoto.alpha = 0;
[self.view addSubview:takenPhoto];
//Add in filters
stillCamera = [[GPUImageStillCamera alloc] initWithSessionPreset:AVCaptureSessionPreset1280x720 cameraPosition:AVCaptureDevicePositionBack];
stillCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
//Creating a square crop filter
cropFilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(0.f, (720.0f/1280.0f)/2.0f, 1.f, (720.0f/1280.0f))];
//Create standard vignette filter
vignetteFilter = [[GPUImageVignetteFilter alloc] init]; //1
vignetteFilter.vignetteCenter = CGPointMake(.5, .5);
vignetteFilter.vignetteStart = 0.4f;
vignetteFilter.vignetteEnd = 1.08f;
//Add filters to photo
[cropFilter addTarget:vignetteFilter];
[stillCamera addTarget:cropFilter];
[vignetteFilter addTarget:cameraImagePreview];
[stillCamera startCameraCapture];

Issue with UITabBar button, TabBar button becomes un clickable

I am creating a view with UINavigationBar and UITabBar. I have added a button on tab bar, on button click, i am hiding tab bar and show tool bar at the bottom. My code is written for current as well as previous iOS versions. I am using this code self.edgesForExtendedLayout = UIRectEdgeNone; for iOS7 this is my code :
- (void)hideTabBar {
UITabBar *tabBar = self.tabBarController.tabBar;
UIView *parent = tabBar.superview; // UILayoutContainerView
UIView *content = [parent.subviews objectAtIndex:0]; // UITransitionView
UIView *window = parent.superview;enter code here
[UIView animateWithDuration:0.5
animations:^{
CGRect tabFrame = tabBar.frame;
tabFrame.origin.y = CGRectGetMaxY(window.bounds);
tabBar.frame = tabFrame;
// CGRect contentFrame = content.frame;
// contentFrame.size.height -= tabFrame.size.height;
content.frame = window.bounds;
}];
if ([[[UIDevice currentDevice] systemVersion] intValue] < 7.0)
{
CGRect frame = tbl_AllFiles.frame;
frame.size.height -=tabBar.frame.size.height;
tbl_AllFiles.frame = frame;
}
}
- (void)showTabBar {
UITabBar *tabBar = self.tabBarController.tabBar;
UIView *parent = tabBar.superview; // UILayoutContainerView
UIView *content = [parent.subviews objectAtIndex:0]; // UITransitionView
UIView *window = parent.superview;
if ([[[UIDevice currentDevice] systemVersion] intValue] < 7.0)
{
CGRect frame = tbl_AllFiles.frame;
frame.size.height +=tabBar.frame.size.height;
tbl_AllFiles.frame = frame;
}
[UIView animateWithDuration:0.5
animations:^{
CGRect tabFrame = tabBar.frame;
tabFrame.origin.y = CGRectGetMaxY(window.bounds) - CGRectGetHeight(tabBar.frame);
tabBar.frame = tabFrame;
CGRect contentFrame = content.frame;
contentFrame.size.height -= tabFrame.size.height;
content.frame = contentFrame;
}];
}
- (void)loadToolBar {
toolbar = [UIToolbar new];
toolbar.barStyle = UIBarStyleBlackTranslucent;
moveButton = [UIButton buttonWithType:UIButtonTypeCustom];
[moveButton setFrame:CGRectMake(10, 10, 120, 25)];
[moveButton setBackgroundColor:[UIColor redColor]];
[moveButton setTitle:#"Move" forState:UIControlStateNormal];
[moveButton addTarget:self action:#selector(moveFile_Folder:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *moveItem = [[[UIBarButtonItem alloc] initWithCustomView:moveButton] autorelease];
moveItem.style = UIBarButtonItemStyleBordered;
NSArray *items = [NSArray arrayWithObjects:moveItem, nil];
toolbar.items = items;
[toolbar sizeToFit];
CGFloat toolbarHeight = [toolbar frame].size.height;
CGRect mainViewBounds = self.view.bounds;
if ([[[UIDevice currentDevice] systemVersion] intValue] < 7.0)
{
[toolbar setFrame:CGRectMake(CGRectGetMinX(mainViewBounds),
CGRectGetMinY(mainViewBounds) + CGRectGetHeight(mainViewBounds) - (toolbarHeight),
CGRectGetWidth(mainViewBounds),
toolbarHeight)];
}
else
{
[toolbar setFrame:CGRectMake(CGRectGetMinX(mainViewBounds),
CGRectGetMinY(mainViewBounds) + CGRectGetHeight(mainViewBounds),
CGRectGetWidth(mainViewBounds),
toolbarHeight)];
}
[self.view addSubview:toolbar];
[toolbar bringSubviewToFront:self.view];
}
My issue is on button clicked hideTabBar and loadToolBar methods are called. Everything is working fine, except my button is un-clickable now on toolbar.
Please help me.
i had a similar issue if your viewcontroller is not the root view controller iOS doesn't get the view frame.
Add this line to your viewcontroller in viewdidload,
self.view.frame = [UIScreen mainScreen].bounds;
hope it helps

How do I animate a UIImageView left to right with UIPageControl?

I want to animate a UIImageView left to right with UIPageControl. I have this code but it seems a bit odd...Specifically because what would I do when I reach image 3? I would have to return and that would mess up the mathematical calculations of the views in the pageControl array the way I have it set up:
-(void)createUIViews{
UIImage *image1 = [UIImage imageNamed:#"GiftCard.png"];
firstView = [[UIImageView alloc] initWithImage:image1];
firstView.backgroundColor = [UIColor grayColor];
firstView.tag = 1;
firstView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
[self.view addSubview:firstView];
CGRect newFrame = firstView.frame;
newFrame.origin.x += 40; // shift right by 50pts
newFrame.origin.y += 40;
[UIView animateWithDuration:1.0
animations:^{
firstView.frame = newFrame;
}];
UIImage *image2 = [UIImage imageNamed:#"MyCard.png"];
secondView = [[UIImageView alloc] initWithImage:image2];
secondView.backgroundColor = [UIColor grayColor];
secondView.tag = 1;
secondView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
UIImage *image3 = [UIImage imageNamed:#"GiftCard.png"];
thirdView = [[UIImageView alloc] initWithImage:image3];
thirdView.backgroundColor = [UIColor grayColor];
thirdView.tag = 1;
thirdView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self createUIViews];
// Set up the views array with 3 UIImageViews
views = [[NSArray alloc] initWithObjects:firstView, secondView, thirdView, nil];
// Set pageControl's numberOfPages to 3
self.pageControl.numberOfPages = [views count];
// Set pageControl's currentPage to 0
self.pageControl.currentPage = 0;
// Call changePage each time value of pageControl changes
[self.pageControl addTarget:self action:#selector(changePage:) forControlEvents:UIControlEventValueChanged];
}
- (IBAction) changePage:(id)sender {
NSLog(#"pageControl position %d", [self.pageControl currentPage]);
int oldPageControlPosition = [self.pageControl currentPage] - 1;
NSLog(#"old pageControl position %d", oldPageControlPosition);
//0 Get the currentview as referenced by pageControl
UIImageView *oldView = [views objectAtIndex:oldPageControlPosition];
//NSLog(#"views objectAtIndex = %#",[views objectAtIndex:[self.pageControl currentPage]]);
//1 Animate out the old view
CGRect oldViewFrame = oldView.frame;
oldViewFrame.origin.x -= 300;
[UIView animateWithDuration:2.0
delay: 0.5
options: UIViewAnimationOptionCurveEaseIn
animations:^{
oldView.frame = oldViewFrame;
}
completion:nil];
//3 Get next view from array
UIImageView *nextView = [views objectAtIndex:[self.pageControl currentPage]];
//4 Add it to mainview
[self.view addSubview:nextView];
//5 Animate in
CGRect nextViewFrame = nextView.frame;
nextViewFrame.origin.x += 40; // shift right by 50pts
nextViewFrame.origin.y += 40;
[UIView animateWithDuration:1.0
animations:^{
nextView.frame = nextViewFrame;
}];
}
When I reach the end, I try to return, the last position is 2 and oldPosition at that time is 1. Which is correct, array goes from 0 to 1 to 2 for a total of 3 positions. But when I return, the log displays position as 1 instead of 2, which is fine, because I reversed...but old position shows 0 instead of 2.
I couldnt get it to determine direction so I ended up using gesture recognizers with swipe left and swipe right instances. Here is the code:
//Help determine direction of swipe
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeNext:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.scrollView addGestureRecognizer:swipeLeft];
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipePrev:)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self.scrollView addGestureRecognizer:swipeRight];

Touch scrolling animation for list of images in iOS

My requirement is to display the list of images in horizantal way.when I touch the image it is moved to side and the next image is comes to front.In this way I need to move images side by side.Then is there any method to scroll the list of images?or Can I go for any type of animation ?
In this way images are to be placed and moved.Please suggest me how can I proceed?
I have created a working module of cover flow.....
try transformation on layers which allows 3D transformation using....
-(void) rotateView3D:(UIView *)myView:(CGFloat)angle
{
CATransform3D affinAndScaleTransform;
if (angle==30.0f||angle==-30.0f)
{
affinAndScaleTransform = CATransform3DMakeAffineTransform(CGAffineTransformMakeScale(0.9f, 0.9f));
}
else
{
affinAndScaleTransform = CATransform3DMakeAffineTransform(CGAffineTransformMakeScale(1.0f, 1.0f));
}
CALayer *layer = myView.layer;
// layer.borderColor = [[UIColor blackColor] CGColor];
// layer.borderWidth = 2.0f;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -500;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, angle * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
[layer setTransform:CATransform3DConcat(rotationAndPerspectiveTransform, affinAndScaleTransform)];
}
to scroll the views add gesture .......
for left gesture use some thig like this ........
{
UIView * view0 = [self.view viewWithTag:-1111];
UIView * view1 = [self.view viewWithTag:1111];
UIView * view2 = [self.view viewWithTag:2222];
UIView * view3 = [self.view viewWithTag:3333];
UIView * view4 = [self.view viewWithTag:4444];
[view4 setFrame:self.rect0];
int preViewNo = self.leftProduct-1;
if (preViewNo<0)preViewNo=self.productArray.count-1;
[UIView animateWithDuration:0.4 animations:^
{
[view0 setFrame:self.rect1];
[self rotateView3D:view0 : 30.0f];
[view1 setFrame:self.rect2];
[self rotateView3D:view1 : 0.0f];
[view2 setFrame:self.rect3];
[self rotateView3D:view2 : -30.0f];
[view3 setFrame:self.rect4];
[self rotateView3D:view4 : 0.0f];
}];
[self setdescriptionView:view0 :[self.productArray objectAtIndex:preViewNo]];
[view0 setTag:1111];
[view1 setTag:2222];
[view2 setTag:3333];
[view3 setTag:4444];
[view4 setTag:-1111];
self.currentProduct--;
self.rightProduct--;
self.leftProduct--;
if (self.currentProduct < 0) self.currentProduct=self.productArray.count-1;
if (self.rightProduct < 0) self.rightProduct=self.productArray.count-1;
if (self.leftProduct < 0) self.leftProduct=self.productArray.count-1;
}
on right gesture recognizer use some thing like this.......
{
UIView * view0 = [self.view viewWithTag:-1111];
UIView * view1 = [self.view viewWithTag:1111];
UIView * view2 = [self.view viewWithTag:2222];
UIView * view3 = [self.view viewWithTag:3333];
UIView * view4 = [self.view viewWithTag:4444];
[view0 setFrame:self.rect4];
int nextViewNo = self.rightProduct+1;
if (nextViewNo>=self.productArray.count)nextViewNo=0;
[UIView animateWithDuration:0.4 animations:^
{
[view4 setFrame:self.rect3];
[self rotateView3D:view4 : -30.0f];
[view3 setFrame:self.rect2];
[self rotateView3D:view3 : 0.0f];
[view2 setFrame:self.rect1];
[self rotateView3D:view2 : 30.0f];
[view1 setFrame:self.rect0];
[self rotateView3D:view1 : 0.0f];
}];
[self setdescriptionView:view4 :[self.productArray objectAtIndex:nextViewNo]];
[view0 setTag:4444];
[view1 setTag:-1111];
[view2 setTag:1111];
[view3 setTag:2222];
[view4 setTag:3333];
self.currentProduct++;
self.rightProduct++;
self.leftProduct++;
if (self.currentProduct >= self.productArray.count) self.currentProduct=0;
if (self.rightProduct >= self.productArray.count) self.rightProduct=0;
if (self.leftProduct >= self.productArray.count) self.leftProduct=0;
}
for some technical reason i have to make custom coverflow....
you can also try this .....
icarousal
I solve this problem .I found the sample example in this link.http://code4app.net/category/scrollview

Widget "flip" behavior in Core Animation/Cocoa

I'm trying to make a Card class that duplicates the behavior of Dashboard widgets in that you can put controls or images or whatever on two sides of the card and flip between them.
Layer backed views have a transform property, but altering that doesn't do what I would expect it to do (rotating the layer around the y axis folds it off to the left side).
I was pointed to some undocumented features and an .h file named cgsprivate.h, but I'm wondering if there is an official way to do this? This software would have to be shipped and I'd hate to see it fail later because the Apple guys pull it in 10.6.
Anyone have any idea how to do this? It's so weird to me that a simple widget thing would be so hard to do in Core Animation.
Thanks in advance!
EDIT: I can accomplish this behavior with images that are on layers, but I don't know how to get more advanced controls/views/whatever on the layers. The card example uses images.
Mike Lee has an implementation of the flip effect for which he has released some sample code. (Unfortunately, this is no longer available online, but Drew McCormack built off of that in his own implementation.) It appears that he grabs the layers for the "background" and "foreground" views to be swapped, uses a CATransform3D to rotate the two views in the animation, and then swaps the views once the animation has completed.
By using the layers from the views, you avoid needing to cache into a bitmap, since that's what the layers are doing anyways. In any case, his view controller looks to be a good drop-in solution for what you want.
Using Core Animation like e.James outlined...Note, this is using garbage collection and a hosted layer:
#import "AnimationWindows.h"
#interface AnimationFlipWindow (PrivateMethods)
NSRect RectToScreen(NSRect aRect, NSView *aView);
NSRect RectFromScreen(NSRect aRect, NSView *aView);
NSRect RectFromViewToView(NSRect aRect, NSView *fromView, NSView *toView);
#end
#pragma mark -
#implementation AnimationFlipWindow
#synthesize flipForward = _flipForward;
- (id) init {
if ( self = [super init] ) {
_flipForward = YES;
}
return self;
}
- (void) finalize {
// Hint to GC for cleanup
[[NSGarbageCollector defaultCollector] collectIfNeeded];
[super finalize];
}
- (void) flip:(NSWindow *)activeWindow
toBack:(NSWindow *)targetWindow {
CGFloat duration = 1.0f * (activeWindow.currentEvent.modifierFlags & NSShiftKeyMask ? 10.0 : 1.0);
CGFloat zDistance = 1500.0f;
NSView *activeView = [activeWindow.contentView superview];
NSView *targetView = [targetWindow.contentView superview];
// Create an animation window
CGFloat maxWidth = MAX(NSWidth(activeWindow.frame), NSWidth(targetWindow.frame)) + 500;
CGFloat maxHeight = MAX(NSHeight(activeWindow.frame), NSHeight(targetWindow.frame)) + 500;
CGRect animationFrame = CGRectMake(NSMidX(activeWindow.frame) - (maxWidth / 2),
NSMidY(activeWindow.frame) - (maxHeight / 2),
maxWidth,
maxHeight);
mAnimationWindow = [NSWindow initForAnimation:NSRectFromCGRect(animationFrame)];
// Add a touch of perspective
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1.0 / zDistance;
[mAnimationWindow.contentView layer].sublayerTransform = transform;
// Relocate target window near active window
CGRect targetFrame = CGRectMake(NSMidX(activeWindow.frame) - (NSWidth(targetWindow.frame) / 2 ),
NSMaxY(activeWindow.frame) - NSHeight(targetWindow.frame),
NSWidth(targetWindow.frame),
NSHeight(targetWindow.frame));
[targetWindow setFrame:NSRectFromCGRect(targetFrame) display:NO];
mTargetWindow = targetWindow;
// New Active/Target Layers
[CATransaction begin];
CALayer *activeWindowLayer = [activeView layerFromWindow];
CALayer *targetWindowLayer = [targetView layerFromWindow];
[CATransaction commit];
activeWindowLayer.frame = NSRectToCGRect(RectFromViewToView(activeView.frame, activeView, [mAnimationWindow contentView]));
targetWindowLayer.frame = NSRectToCGRect(RectFromViewToView(targetView.frame, targetView, [mAnimationWindow contentView]));
[CATransaction begin];
[[mAnimationWindow.contentView layer] addSublayer:activeWindowLayer];
[CATransaction commit];
[mAnimationWindow orderFront:nil];
[CATransaction begin];
[[mAnimationWindow.contentView layer] addSublayer:targetWindowLayer];
[CATransaction commit];
// Animate our new layers
[CATransaction begin];
CAAnimation *activeAnim = [CAAnimation animationWithDuration:(duration * 0.5) flip:YES forward:_flipForward];
CAAnimation *targetAnim = [CAAnimation animationWithDuration:(duration * 0.5) flip:NO forward:_flipForward];
[CATransaction commit];
targetAnim.delegate = self;
[activeWindow orderOut:nil];
[CATransaction begin];
[activeWindowLayer addAnimation:activeAnim forKey:#"flip"];
[targetWindowLayer addAnimation:targetAnim forKey:#"flip"];
[CATransaction commit];
}
- (void) animationDidStop:(CAAnimation *)animation finished:(BOOL)flag {
if (flag) {
[mTargetWindow makeKeyAndOrderFront:nil];
[mAnimationWindow orderOut:nil];
mTargetWindow = nil;
mAnimationWindow = nil;
}
}
#pragma mark PrivateMethods:
NSRect RectToScreen(NSRect aRect, NSView *aView) {
aRect = [aView convertRect:aRect toView:nil];
aRect.origin = [aView.window convertBaseToScreen:aRect.origin];
return aRect;
}
NSRect RectFromScreen(NSRect aRect, NSView *aView) {
aRect.origin = [aView.window convertScreenToBase:aRect.origin];
aRect = [aView convertRect:aRect fromView:nil];
return aRect;
}
NSRect RectFromViewToView(NSRect aRect, NSView *fromView, NSView *toView) {
aRect = RectToScreen(aRect, fromView);
aRect = RectFromScreen(aRect, toView);
return aRect;
}
#end
#pragma mark -
#pragma mark CategoryMethods:
#implementation CAAnimation (AnimationFlipWindow)
+ (CAAnimation *) animationWithDuration:(CGFloat)time flip:(BOOL)bFlip forward:(BOOL)forwardFlip{
CABasicAnimation *flipAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.y"];
CGFloat startValue, endValue;
if ( forwardFlip ) {
startValue = bFlip ? 0.0f : -M_PI;
endValue = bFlip ? M_PI : 0.0f;
} else {
startValue = bFlip ? 0.0f : M_PI;
endValue = bFlip ? -M_PI : 0.0f;
}
flipAnimation.fromValue = [NSNumber numberWithDouble:startValue];
flipAnimation.toValue = [NSNumber numberWithDouble:endValue];
CABasicAnimation *shrinkAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
shrinkAnimation.toValue = [NSNumber numberWithFloat:1.3f];
shrinkAnimation.duration = time * 0.5;
shrinkAnimation.autoreverses = YES;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:flipAnimation, shrinkAnimation, nil];
animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animationGroup.duration = time;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion = NO;
return animationGroup;
}
#end
#pragma mark -
#implementation NSWindow (AnimationFlipWindow)
+ (NSWindow *) initForAnimation:(NSRect)aFrame {
NSWindow *window = [[NSWindow alloc] initWithContentRect:aFrame
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[window setOpaque:NO];
[window setHasShadow:NO];
[window setBackgroundColor:[NSColor clearColor]];
[window.contentView setWantsLayer:YES];
return window;
}
#end
#pragma mark -
#implementation NSView (AnimationFlipWindow)
- (CALayer *) layerFromWindow {
NSBitmapImageRep *image = [self bitmapImageRepForCachingDisplayInRect:self.bounds];
[self cacheDisplayInRect:self.bounds toBitmapImageRep:image];
CALayer *layer = [CALayer layer];
layer.contents = (id)image.CGImage;
layer.doubleSided = NO;
// Shadow settings based upon Mac OS X 10.6
[layer setShadowOpacity:0.5f];
[layer setShadowOffset:CGSizeMake(0,-10)];
[layer setShadowRadius:15.0f];
return layer;
}
#end
The header file:
#interface AnimationFlipWindow : NSObject {
BOOL _flipForward;
NSWindow *mAnimationWindow;
NSWindow *mTargetWindow;
}
// Direction of flip animation (property)
#property (readwrite, getter=isFlipForward) BOOL flipForward;
- (void) flip:(NSWindow *)activeWindow
toBack:(NSWindow *)targetWindow;
#end
#pragma mark -
#pragma mark CategoryMethods:
#interface CAAnimation (AnimationFlipWindow)
+ (CAAnimation *) animationWithDuration:(CGFloat)time
flip:(BOOL)bFlip // Flip for each side
forward:(BOOL)forwardFlip; // Direction of flip
#end
#interface NSWindow (AnimationFlipWindow)
+ (NSWindow *) initForAnimation:(NSRect)aFrame;
#end
#interface NSView (AnimationFlipWindow)
- (CALayer *) layerFromWindow;
#end
EDIT: This will animate to flip from one window to another window. You can apply the same principals to a view.
It's overkill for your purposes (as it contains a largely-complete board and card game reference app), but check out this sample from ADC. The card games included with it do that flip effect quite nicely.
If you are able to do this with images, perhaps you can keep all of your controls in an NSView object (as usual), and then render the NSView into a bitmap image using cacheDisplayInRect:toBitmapImageRep: just prior to executing the flip effect. The steps would be:
Render the NSView to a bitmap
Display that bitmap in a layer suitable for the flip effect
Hide the NSView and expose the image layer
Perform the flip effect
I know this is late but Apple has an example project here that may be of help to anyone still stumbling upon this question.
https://developer.apple.com/library/mac/#samplecode/ImageTransition/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010277
There's a complete open source implementation of this by the guys at Mizage.
You can check it out here: https://github.com/mizage/Flip-Animation
Probably not the case in 2008 when this question was asked, but this is pretty easy these days:
[UIView animateWithDuration:0.5 animations:^{
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.iconView cache:YES];
/* changes to the view made here will be reflected on the flipped to side */
}];
Note: Apparently, this only works on iOS.

Resources