Adding CAAnimation to sublayer in UITableViewCell - ios

I've got a uitableviewcell subclass with an imageView property. Im fetching the image from the web and when i get it, i'd like to crossfade it into the image view.
I've got this CAAnimation code that i was originally using within the view controller to apply this effect. my code looked like this:
CATransition *transition = [CATransition animation];
transition.duration = 0.3f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self.photoView.layer addAnimation:transition forKey:someKey];
Now, i'd like to move that code into my UITableViewCell. I've tried applying that animation in various locations but it doesn't seem to be having an affect. I put it in awakeFromNib (the cell is from a nib file) as well as willMoveToSuperview. Any thoughts?

David is right, you're not actually changing the contents of the imageView in your code.
I just made this subclass of an UITableViewCell and added it to a basic iOS Single View application:
#import "AnimatedCell.h"
#implementation AnimatedCell {
BOOL imageWasGrabbed;
}
- (id)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.frame = CGRectMake(0,0,320,44);
self.imageView.image = [UIImage imageNamed:#"localImage"];
self.textLabel.text = #"Locally loaded image";
self.layer.borderColor = [UIColor lightGrayColor].CGColor;
self.backgroundColor = [UIColor groupTableViewBackgroundColor];
}
return self;
}
-(void)grabImage {
NSString *path = #"http://www.c4ios.com/images/temp/webImage#2x.png";
NSURL *webImageUrl = [NSURL URLWithString:path];
NSData *webImageData = [NSData dataWithContentsOfURL:webImageUrl];
UIImage *image = [UIImage imageWithData:webImageData];
CATransition *transition = [CATransition animation];
transition.duration = 1.0f;
transition.delegate = self;
NSString *n = kCAMediaTimingFunctionEaseInEaseOut;
transition.timingFunction = [CAMediaTimingFunction functionWithName:n];
transition.type = kCATransitionFade;
[self.imageView.layer addAnimation:transition forKey:#"animateContents"];
self.imageView.image = image;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if(!imageWasGrabbed) {
[self grabImage];
}
}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
self.textLabel.text = #"Web loaded image";
imageWasGrabbed = YES;
}
#end
After you add the transition to your cell's imageView layer, you need to call the following:
self.imageView.image = image;
For reference, the View Controller for my project looks like this:
#import "ViewController.h"
#import "AnimatedCell.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
AnimatedCell *cell = [[AnimatedCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"AnimatedCell"];
cell.center = self.view.center;
[self.view addSubview:cell];
}
#end

Related

How to move UIImageView while swiping in UIPageViewContoller

I would like to move red circle (as shown in following image) slowly (may be with animation) when user swipes the app intro (PageViewController). I also want to add some animations so I'm trying to use IFTTT/JazzHands framework. But it's difficult for me to understand currently. Is there any easy way to use animation in PageViewController? Or are there any tutorials that uses IFTTT/JazzHands framework? Could anybody help me, please?
Try this if its is ok vote for me
#interface homeViewController ()<UIScrollViewDelegate>
#property (weak, nonatomic) IBOutlet UIScrollView *scrollViewSlider;
#end
#implementation homeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationController.navigationBarHidden=true;
[NSTimer scheduledTimerWithTimeInterval:4 target:self
selector:#selector(scrollingTimer) userInfo:nil repeats:YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
-(void)viewDidLayoutSubviews
{
UIImage *imageOne = [UIImage imageNamed:#"download.jpeg"];
UIImage *imageTwo = [UIImage imageNamed:#"download2.jpeg"];
UIImage *imageThree = [UIImage imageNamed:#"download3.jpeg"];
UIImage *imageFour = [UIImage imageNamed:#"download4.jpeg"];
NSArray *imageArray = [NSArray arrayWithObjects:imageOne,
imageTwo, imageThree, imageFour, nil];
for (int i = 0; i <= 3; i++) {
UIImageView *imgView = [[UIImageView alloc]init];
imgView.contentMode = UIViewContentModeScaleToFill;
imgView.alpha = 0.5f;
imgView.frame = CGRectMake(i * self.scrollViewSlider.bounds.size.width,
0, self.scrollViewSlider.bounds.size.width,
self.scrollViewSlider.bounds.size.height);
[imgView setImage:imageArray[i]];
[self.scrollViewSlider addSubview:imgView];
self.scrollViewSlider.pagingEnabled = true;
[self.scrollViewSlider setContentSize:CGSizeMake(imageArray.count *
self.scrollViewSlider.bounds.size.width,
self.scrollViewSlider.bounds.size.height-20)];
}
}
-(void) scrollingTimer
{
CGPoint frame = self.scrollViewSlider.contentOffset;
[UIView animateWithDuration:3.0f animations:^(void) {
if (frame.x != 3 * self.scrollViewSlider.frame.size.width)
[self.scrollViewSlider setContentOffset:CGPointMake(frame.x +
self.scrollViewSlider.frame.size.width, 0)];
else
[self.scrollViewSlider setContentOffset:CGPointMake(0, 0)];
}];
}
Try this code without any Third party Class
just add QuartzCore framwork from library
#import <QuartzCore/QuartzCore.h>
- (CAAnimation*)movedown;
{
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = #"position.y";
animation.fromValue = #600;
animation.toValue = #50;
animation.duration = 0.25;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[subView.layer addAnimation:animation forKey:#"basic"];
subView.layer.position = CGPointMake(0,-20);
return animation;
}
pls replace your animation view in-place of subview.

Why is UITableViewCell taking long gesture?

I have a UITableView inside a UIView, lets call it view_A. There's a UIViewController, call it mainViewController. Inside it there is a UIButton. On tapping that button I add the view_A as a subview to mainViewController's view. The tableview has several menu items in it. The problem is the tableview is not responding to the touch correctly. I have to tap the cell long to make a selection. There's no gesture added on it. There's no other view covering it. It's absolutely bizzare, this behavior. Please take a look at the following code and point out what might be causing the trouble.
This is the delegate implementation/presentations in mainViewcontroller:
-(void) showDropDownMenu: (UIButton *) sender
{
UINib *nib = [UINib nibWithNibName:#"DropDownMenuView" bundle:nil];
self.myView = [[nib instantiateWithOwner:self options:nil] objectAtIndex:0];
self.myView.hidden = NO;
self.myView.tag = 101;
self.myView.delegate = self;
self.myView.btnBack.hidden = YES;
CATransition *transition = nil;
transition = [CATransition animation];
transition.duration = 0.2;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype =kCATransitionFromBottom ;
transition.delegate = self;
[self.myView.layer addAnimation:transition forKey:nil];
[self.view addSubview:self.myView];
}
-(void) hideDropDownMenu
{
CATransition *transition = nil;
transition = [CATransition animation];
transition.duration = 0.2;//kAnimationDuration
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
transition.type = kCATransitionPush;
transition.subtype =kCATransitionFromTop;
transition.delegate = self;
[self.myView.layer addAnimation:transition forKey:nil];
self.myView.tag = 102;
[UIView commitAnimations];
}
-(void) navigateBack
{
}
-(void) themeSelected: (NSIndexPath *) indexPath
{
NSLog(#"%ld",(long)indexPath.item);
themeNumber = [NSString stringWithFormat:#"%li",(indexPath.row+1)];
[self setUpTheme];
}
This is implementation of the cell.h file:
#interface ThemeTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *themeName;
#property (weak, nonatomic) IBOutlet UIImageView *themePreview;
This is implementation of cell.m file:
#import "ThemeTableViewCell.h"
#implementation ThemeTableViewCell
- (void)awakeFromNib {
// Initialization code
//ORIGINAL 82
self.clipsToBounds = YES;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
My View_A .h file can be found here.
View_A.m file can be found here.
UPDATE: I logged the gestures and turns out somehow long press gesture is set to cells.
Are you disable cell imageview userInteraction, if no try this cell.yourImageView.userInteractionEnabled = NO

Spinning an image around like a coin

I have one image. I want to spin it like a coin spin on surface. I tried rotation transform but it does not spin like that. How to achieve such an animation?
code:
- (void)viewDidLoad {
[super viewDidLoad];
[self.view setUserInteractionEnabled:YES];
lbl_facebook.font=[UIFont fontWithName:GZFont size:12.0f];
txtPassword.font=[UIFont fontWithName:GZFont size:15.0f];
txtUsername.font=[UIFont fontWithName:GZFont size:15.0f];
CATransition* transition = [CATransition animation];
transition.startProgress = 0;
transition.endProgress = 1.0;
transition.type = #"flip";
transition.subtype = #"fromRight";
transition.duration = 0.3;
transition.repeatCount = 2;
[_Image.layer addAnimation:transition forKey:#"transition"];
}
nd:
#import "LoginViewController.h"
#import "RegistrationViewController.h"
#import "ForgetPasswordViewController.h"
#import "ForgetPasswordController.h"
#import "SearchServiceProviderViewController.h"
#import <QuartzCore/QuartzCore.h>
This will make a nice, coin-like flip:
CATransition* transition = [CATransition animation];
transition.startProgress = 0;
transition.endProgress = 1.0;
transition.type = #"flip";
transition.subtype = #"fromRight";
transition.duration = 0.3;
transition.repeatCount = 2;
And add the transition animation to the layer of your view:
[_yourView.layer addAnimation:transition forKey:#"transition"];
See it in action:
One good trick to spin like this is that take different images of coin with different angle like spinning image. And then add all those images to array and start animation of images with that array..it will give you much better effect...Simple process like video framing.
Like:
NSArray *animationArray = [NSArray arrayWithObjects:
[UIImage imageNamed:#"images.jpg"],
[UIImage imageNamed:#"images1.jpg"],
[UIImage imageNamed:#"images5.jpg"],
[UIImage imageNamed:#"index3.jpg"],
nil];
UIImageView *animationView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0,320, 460)];
animationView.backgroundColor = [UIColor purpleColor];
animationView.animationImages = animationArray;
animationView.animationDuration = 1.5;
animationView.animationRepeatCount = 0;
[animationView startAnimating];

iOS Swiping functions

Good day! I have a question,I have this code for a Single Page application
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint endPosition = [touch locationInView:self.view];
if (self.imageStatus>0)
{
if (self.startPosition.x < endPosition.x)
{
// Right swipe
CATransition *transition = [CATransition animation];
transition.duration = 0.75;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
transition.type = kCATransitionPush;
transition.subtype =kCATransitionFromLeft;
transition.delegate = self;
[self.view.layer addAnimation:transition forKey:nil];
[self.view addSubview:myViewController.view];
self.imageStatus --;
if (self.imageStatus == 0)
{
self.myImage.image = [UIImage imageNamed:#"blue_back.png"];
}
else
{
self.myImage.image = [UIImage imageNamed:#"black_back.png"];
}
}
}
if (self.imageStatus<2)
{
if (self.startPosition.x > endPosition.x)
{
// Left swipe
CATransition *transition = [CATransition animation];
transition.duration = 0.75;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
transition.type = kCATransitionPush;
transition.subtype =kCATransitionFromRight;
transition.delegate = self;
[self.view.layer addAnimation:transition forKey:nil];
[self.view addSubview:myViewController.view];
self.imageStatus ++;
if (self.imageStatus == 2)
{
self.myImage.image = [UIImage imageNamed:#"red_back.png"];
}
else
{
self.myImage.image = [UIImage imageNamed:#"black_back.png"];
}
}
}
when i open the app the default background is black, when i swipe at right it shows the blue_back.png or the blue background, when i swipe back it shows the default background which is black, and when its on black again and i will swipe it left it shows the red_back.png or the red background and vise versa. now what i want is, i will add another page with yellow background next to red, so when im in the default black page, when i swipe to left two times it shows the yellow. and also the swiping function, when i swipe it it takes maybe a second to switch a page, how can i implement the "Realtime Swiping" like in the table view, but horizontal, so it changes page fast. thanks!
Updated answer:
What you want is a paging scrollview. The trick is to add the views are the correct positions in the scrollView and set the scrollviews contentSize correctly. Example with two views:
- (void)viewDidLoad
{
[super viewDidLoad];
self.edgesForExtendedLayout = UIRectEdgeBottom;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.bounds.size.height);
[self.view addSubview:scrollView];
UIView *redView = [[UIView alloc] init];
redView.frame = self.view.bounds;
redView.backgroundColor = [UIColor redColor];
[scrollView addSubview:redView];
UIView *blueView = [[UIView alloc] init];
CGRect frame = self.view.bounds;
frame.origin.x = 320;
blueView.frame = frame;
blueView.backgroundColor = [UIColor blueColor];
[scrollView addSubview:blueView];
}
Old answer:
I would be easier to make use of the build in gesture recognizers. Specifically UIPanGestureRecognizer.
Example:
In viewDidLoad:
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(myAction:)];
[self.view addGestureRecognizer:pan];
And the action:
- (void) myAction:(UIPanGestureRecognizer*)gestureRec
{
if (gestureRec.state == UIGestureRecognizerStateEnded) {
NSLog(#"ended");
NSLog(#"%#", NSStringFromCGPoint([gestureRec velocityInView:self.view]));
}
}
The state determines when its ended as you want. And you can use the velocityInView to determine right/left and up/down movement

Core Animation Strange Display after addSubview then removeFromSuperview

I have a view controller with a central container that gets flipped to show different views on each side. One of the views is a table view and the other is a custom view of mine. It is working perfectly as per screenshot 1.
My problem is that after I have added a subview over this viewcontroller (its a transparent UIView for showing help screen) and then remove this subview from the viewcontroller
, when I try re-flip the central view strange results occur. There still seems to be a flipping animation between the two views, but as you can see from the last 2 screenshot an extra central table view just sits there. I can't quite explain this exactly so I'm hoping a combination of the pictures, and some code will help:
MainPageVC.h
#interface MainPageVC : UIViewController <UITableViewDataSource, UITableViewDelegate>
#end
MainPageVC.m
#interface MainPageVC ()
#property (nonatomic, strong) NSArray *dataArr;
#property (nonatomic, weak) IBOutlet UIView *flipContainerView;
#property (nonatomic, strong) UIView *detailFlipView;
#property (nonatomic, strong) UITableView *listFlipView;
#property (nonatomic) BOOL isTransitioning;
#property (nonatomic) BOOL isFlipped;
#end
#implementation MainPageVC
#synthesize dataArr = _dataArr;
#synthesize flipContainerView = _flipContainerView;
#synthesize detailFlipView = _detailFlipView;
#synthesize listFlipView = _listFlipView;
#synthesize isTransitioning = _isTransitioning;
#synthesize isFlipped = _isFlipped;
- (void)viewDidLoad {
[super viewDidLoad];
self.dataArr = [NSArray arrayWithObjects:#"row 1", #"row 2", #"row 3", nil];;
}
- (void)viewDidLayoutSubviews {
[self setUpCustomViews];
}
- (void)setUpCustomViews {
self.isFlipped = NO;
self.isTransitioning = NO;
CGRect frame = CGRectMake(0, 0, self.flipContainerView.frame.size.width, self.flipContainerView.frame.size.height);
self.detailFlipView = [[UIView alloc] initWithFrame:frame];
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,50)];
[self.detailFlipView addSubview:customView];
self.listFlipView = [[UITableView alloc] initWithFrame:frame];
self.listFlipView.delegate = self;
self.listFlipView.dataSource = self;
UIColor *backgroundColour = [UIColor whiteColor];
CGFloat cornerRadius = 15.0f;
CGFloat borderWidth = 1.5f;
UIColor *borderColour = [UIColor colorWithRed:49.0/255.0f green:49.0/255.0f blue:49.0/255.0f alpha:1.0f];
self.detailFlipView.backgroundColor = backgroundColour;
self.listFlipView.backgroundColor = backgroundColour;
self.detailFlipView.layer.cornerRadius = cornerRadius;
self.listFlipView.layer.cornerRadius = cornerRadius;
self.detailFlipView.layer.borderWidth = borderWidth;
self.listFlipView.layer.borderWidth = borderWidth;
self.detailFlipView.layer.borderColor = [borderColour CGColor];
self.listFlipView.layer.borderColor = [borderColour CGColor];
self.detailFlipView.layer.doubleSided = NO;
self.listFlipView.layer.doubleSided = NO;
self.listFlipView.layer.masksToBounds = YES;
self.detailFlipView.layer.masksToBounds = YES;
[self.flipContainerView addSubview:self.detailFlipView];
[self.flipContainerView addSubview:self.listFlipView];
}
- (IBAction)changeViewTapped:(UIControl *)sender {
if (self.isTransitioning) return;
CALayer *top = self.listFlipView.layer;
CALayer *bottom = self.detailFlipView.layer;
if (self.isFlipped) {
top = self.detailFlipView.layer;
bottom = self.listFlipView.layer;
}
CAAnimation *topAnimation = [self flipAnimationWithDuration:0.6f forLayerBeginningOnTop:YES scaleFactor:1.2f];
CAAnimation *bottomAnimation = [self flipAnimationWithDuration:0.6f forLayerBeginningOnTop:NO scaleFactor:1.2f];
CGFloat zDistance = 1000.0f;
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1. / zDistance;
top.transform = perspective;
bottom.transform = perspective;
topAnimation.delegate = self;
[CATransaction begin];
[top addAnimation:topAnimation forKey:#"flip"];
[bottom addAnimation:bottomAnimation forKey:#"flip"];
CABasicAnimation *colorAnimation = [CABasicAnimation animationWithKeyPath:#"backgroundColor"];
colorAnimation.toValue = (id)[UIColor colorWithRed:27.0/255.0f green:47.0/255.0f blue:87.0/255.0f alpha:1.0f].CGColor;
[self.bannerButtonImageView.layer addAnimation:colorAnimation forKey:#"colorAnimation"];
[CATransaction commit];
}
-(CAAnimation *)flipAnimationWithDuration:(NSTimeInterval)aDuration forLayerBeginningOnTop:(BOOL)beginsOnTop scaleFactor:(CGFloat)scaleFactor {
self.isTransitioning = YES;
CABasicAnimation *flipAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.y"];
CGFloat startValue = beginsOnTop ? 0.0f : M_PI;
CGFloat endValue = beginsOnTop ? -M_PI : 0.0f;
flipAnimation.fromValue = [NSNumber numberWithDouble:startValue];
flipAnimation.toValue = [NSNumber numberWithDouble:endValue];
CABasicAnimation *shrinkAnimation = nil;
if (scaleFactor != 1.0f ) {
shrinkAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
shrinkAnimation.toValue = [NSNumber numberWithFloat:scaleFactor];
shrinkAnimation.duration = aDuration * 0.5;
shrinkAnimation.autoreverses = YES;
}
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:flipAnimation, shrinkAnimation, nil];
animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animationGroup.duration = aDuration;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion = NO;
return animationGroup;
}
-(void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag {
self.isFlipped = !self.isFlipped;
self.isTransitioning = NO;
}
...USUAL UITABLEVIEW METHODS
- (void)showHelpScreen {
CustomHelp *helpView = [[CustomHelp alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:helpView];
}
#end
CustomHelp.h
#interface CustomHelp : UIView
#end
CustomHelp.m
#implementation CustomHelp
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
UIView *test = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 50, 100)];
test.backgroundColor = [UIColor redColor];
[self addSubview:test];
UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[self addGestureRecognizer: singleTap];
}
return self;
}
- (void)handleSingleTap {
[UIView animateWithDuration:0.5
animations:^{ self.alpha = 0.0;}
completion:^(BOOL finished){
[self removeFromSuperview];
}];
}
#end
Adding comment as answer.
My only suggestion would be in the setUpCustomViews function to add in an if(!self.listFlipView) and if(!self.detailFlipView) to the view creation. That function may be being called multiple times and thereby adding multiple views to your window without removing the previous one.

Resources