Push a detail view in UITableViewCell class - ios

My class inherit from UITableViewCell, i have make some custom transitions to push a new detail view when an image get selected.
[UIView transitionWithView:self.masterView duration:0.5 options:UIViewAnimationOptionShowHideTransitionViews
animations:^ {
[self.masterView addSubview:self.detailImage];
}
completion:nil];
My code works fine, the detailImage subview is shown with a transition, but this transition is not what i want exactly. What i want to perform is a simple transition from bottom to up. The list of UIViewAnimation doesn't contain such animation.
Is there any way to use that transition without changing my class inheritance to UINavigationController ?

If I understand you right, the code below may be what you want.
CGRect detailImageFrameOri = self.detailImage.frame;
CGRect detailImageFrame = detailImageFrameOri;
detailImageFrame.origin.y += self.detailImage.frame.size.height;
self.detailImage.frame = detailImageFrame;
[self.masterView addSubview:self.detailImage];
[UIView animateWithDuration:0.5 animations:^{
self.detailImage.frame = detailImageFrameOri;
}];
Hope this can help you.
Edit:
from top to bottom,
CGRect detailImageFrame = self.detailImage.frame;
detailImageFrame.origin.y += self.detailImage.frame.size.height;
[self.masterView addSubview:self.detailImage];
[UIView animateWithDuration:0.5
animations:^{
self.detailImage.frame = detailImageFrame;
}
completion:^(BOOL finished) {
[self.detailImage removeFromSuperview];
}];

Related

How can I animate the height constraint of a UIPickerView?

I've learned that the way to animate constraints in Cocoa Touch is to just set them and then put [self.view layoutIfNeeded] in an animation block, like so:
self.someViewsHeightConstraint = 25.0;
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutIfNeeded];
}];
This is working fine, for example with a simple UIView. However, it does not work with a UIPickerView. It just snaps into the new position without animating.
Any ideas why this might be the case? What ways are there to work around this?
The effect I'm going for is that the Picker View should shrink to just show the chosen item, as the user goes on to input other things. One idea I had is to make a snapshotted view and animate that instead, but I couldn't quite get that working either.
I found trying to animate the height or the placement constraint of a UIPickerView to be problematic. However, doing transforms seems to work well -- even if you have Auto Layout Constraints everywhere, including in the view to be transformed.
Here's an example of what works for me. In this case, I've placed the picker view inside a blurring effects view -- but you don't even need to put your picker view inside another view to animate it.
In the code below, when I call show, it animates up vertically. When I call the hide method, it animates downwards.
- (void)showPickerViewAnimated:(BOOL)animated;
{
__weak MyViewController *weakSelf = self;
[UIView animateWithDuration:(animated ? kPickerView_AppearanceAnimationDuration : 0.0)
delay:(animated ? kPickerView_AppearanceAnimationDelay : 0.0)
options:(UIViewAnimationOptionCurveEaseInOut)
animations:^{
weakSelf.pickerViewContainerView.transform = CGAffineTransformMakeTranslation(0,0);
}
completion:^(BOOL finished) {
[weakSelf.view layoutIfNeeded];
}];
}
- (void)hidePickerViewAnimated:(BOOL)animated;
{
__weak MyViewController *weakSelf = self;
[UIView animateWithDuration:(animated ? kPickerView_DisappearanceAnimationDuration : 0.0)
delay:(animated ? kPickerView_DisappearanceAnimationDelay : 0.0)
options:(UIViewAnimationOptionCurveEaseInOut)
animations:^{
weakSelf.pickerViewContainerView.transform = CGAffineTransformMakeTranslation(0, kPickerView_Height);
}
completion:^(BOOL finished) {
[weakSelf.view layoutIfNeeded];
}];
}
picker view, If you have added constraint To TopLayout for yPosition remove it and add constraint to bottom layout instead.
That will solve the problem. here is my code and its working:
self.timePickerHeightConstraint.constant = pickerIsClosed ? 216 :
0;
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutSubviews];
} completion:^(BOOL finished){
}];

Moving origin back to original position

Today, I am trying to get a view to return to its default origin after a cancel. I am using two VCs to do this. One is a footer controller in a tableview, and the other is a modal view, which is presented after the first animation. Whenever I try to go back from the modal view, the origin is still the same one after I did the first animation. Here is the code I am using:
Footer:
-(IBAction)addPerson:(id)sender{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
NSLog(#"%f", self.view.frame.origin.y);
self.view.frame = CGRectMake(0,-368,320,400);
[UIView commitAnimations];
self.tdModal2 = [[TDSemiModalViewController2 alloc]init];
// [self.view addSubview:test.view];
[self presentSemiModalViewController2:self.tdModal2];
}
-(void)moveBack{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
NSLog(#"%f", self.view.frame.origin.y);
self.view.frame = CGRectMake(0,368,320,400);
[UIView commitAnimations];
}
And in the modal view:
-(IBAction)cancel:(id)sender{
[self dismissSemiModalViewController:self];
FooterViewController *foot = [[FooterViewController alloc]init];
self.footer = foot;
// self.footer.view.frame = CGRectMake(0,35,320,400);
[self.footer moveBack];
}
I give the following recommendations, they may be good for you.
Note 1, AffineTransform
If the translation is always to the same point and always with the same measure, I'd recommend using CGAffineTransformMakeTranslation(<#CGFloat tx#>, <#CGFloat ty#>) instead of modifying the view's frame. This method specifies how much x and y points will the view move.
In that way, returning the view to the original position is as simple as doing view.transform = CGAffineTransformIdentity.
Both of these inside their respective animation block of course.
Note 2, Using CGPoint to move the origin
If you just move the origin of the view then the recommendation is to make:
CGRect hiddenFrame = self.view.frame;
hiddenFrame.origin.y -= 736;
self.view.frame = hiddenFrame;
or
CGRect hiddenFrame = self.view.frame;
hiddenFrame.origin.y = -368;
self.view.frame = hiddenFrame;
or
CGRect hiddenFrame = self.view.frame;
hiddenFrame.origin = CGPointMake(0,-368);
self.view.frame = hiddenFrame;
The same for the move back. It's more code but it's more understandable.
Note 3, UIView animation block
You should use the new blocks:
[UIView animateWithDuration: 0.25 animations: ^(void) {
//animation block
}];
There are other blocks with more methods as delay, completion blocks, etc.
Option, Delegate or reference passing
When you create your modal controller, pass the reference of the current controller:
self.tdModal2 = [[TDSemiModalViewController2 alloc]init];
self.tdModal2.delegate = self;
You should declare that property in the TDSemiModalViewController2.h. Either by declaring the #class FooterViewController to avoid crossed imports; by making a protocol and declaring the property as id<myModalProtocol>, FooterViewController should then implement the protocol with the method moveBack; Or just declare the property as id and call [self.delegate performSelector: #selector(moveBack)].
Then in the cancel method, simply do:
[self dismissSemiModalViewController:self];
[self.delegate moveBack] //or performSelector.. in the third option case

Weird behaviour happens when using UIView animate and CGAffineTransform

I created some animations in my project. Basically, I use UIView animate and CGAffineTransform, but a very strange thing happened and I have no idea. Hope someone can help me solve this problem. Thanks in advance.
This is the strange thing:
After the user clicks on a button, the button slides off screen and another two buttons slide on the screen (I just changed the center point of these buttons to achieve this animation). And, some time later, a view on the screen start shaking (I use CGAffineTransform to achieve this).
At this moment, the strange thing happens - the button that previous slid off screen show up at its original position again and the other two buttons disappear (No animation, just shows up and disappear).
The following is the related code,
1) Button slide off and slide in animation related code
- (IBAction)start:(id)sender
{
// 1. Slide in cancel and pause button
[UIView animateWithDuration:0.5f animations:^{
[startButton setCenter:CGPointMake(startButton.center.x + 300.0f, startButton.center.y)];
[cancelButton setCenter:CGPointMake(cancelButton.center.x + 300.0f, cancelButton.center.y)];
[pauseButton setCenter:CGPointMake(pauseButton.center.x + 300.0f, pauseButton.center.y)];
} completion:^(BOOL finished) {
if (finished) {
NSLog(#"Move finished");
}
}];
}
2) The view shaking animation related code
- (void)shakeView:(UIView *)viewToShake
{
CGFloat t = 2.0;
CGAffineTransform translateRight = CGAffineTransformTranslate(CGAffineTransformIdentity, t, 0.0);
CGAffineTransform translateLeft = CGAffineTransformTranslate(CGAffineTransformIdentity, -t, 0.0);
viewToShake.transform = translateLeft;
[UIView animateWithDuration:0.07 delay:0.0 options:UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat animations:^{
[UIView setAnimationRepeatCount:2.0];
viewToShake.transform = translateRight;
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:0.05 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
viewToShake.transform = CGAffineTransformIdentity;
} completion:nil];
}
}];
}
This isn't weird, it's a common problem with
auto layout. If you move UI elements by changing frames, then as soon as something else takes place that requires laying out views, the moved views will revert to the position defined by their constraints. To fix it, you either need to turn off auto layout, or do your animations by changing constraints not frames.
I have tried your code in my test project. The problem is probably because you are using Autolayout in your xib.
Please checking your xib file and uncheck the Autolayout property.

How To dismiss SplashView in Pagecurl Style in iPhone?

I want to hide my Splash_View In Page curl Style, so that it can move to another class.
Default.png
Any Idea or suggestion from experts would be welcome.
Try this code:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.window cache:YES];
[UIView commitAnimations];
Splash_Image_View.hidden = YES;
You'll need to make the splash image part of the main view to animate it. In your main view controller, set up an IBOutlet for a UIImageView, I'll call it splashImageView. In the MainWindow.xib file, drag in a UIImageView with your splash image on it and hook it up to the outlet. Then in the viewDidAppear of your main view controller .m file, you'll need to do something like this:
[UIView transitionWithView:self.view duration:0.5 options:UIViewAnimationOptionTransitionCurlUp animations:^{
splashImageView.hidden = YES;
} completion:NULL];
This will hide the splash view with a curl animation.
The simplest solution comes to mind is to load the same picture in your first [ViewDidLoad] and then doing something like this:
[UIView transitionWithView:self.view duration:0.4
delay:0.0
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
//hide splash here
}
completion:^(BOOL finished){
}];

How to cross-fade a UIScrollView back to the beginning

I have a horizontally-scrolling paging UIScrollView in an iPad app, containing lots of pages. On the last page, I tap on a button on the screen to reset back to page 1. I would like to be able to cross-dissolve this transition, but it doesn't seem to work:
[UIView transitionWithView:self.view duration:1.0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationOptionAllowAnimatedContent animations:^{
pagingScrollView.contentOffset = CGPointZero;
} completion:^(BOOL finished) {
[self refreshPages];
}];
I read that adding UIViewAnimationOptionAllowAnimatedContent will allow all content to transition, but it doesn't work. Instead, the screen cross-dissolves to the background colour, and when the transition is complete, the first page just appears.
you cannot fade-out a UIView (the scroller) AND simultaneously fade-in the same view...
you could just using different UIViews...
what you can do is:
1) fadeOut the scroller in the current position (to the backGround)
2) while the scroller is invisible, move it to the right position (with no animation)
3) fadeIn the scroller from the backGround
something like:
// START FIRST PART OF ANIMATION
[UIView animateWithDuration:0.5 delay:0.0 options: options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationOptionAllowAnimatedContent animations:^{
pagingScrollView.alpha = 0;
} completion:^(BOOL finished) {
// FIRST PART ENDED
// MOVE SCROLLER (no animation)
pagingScrollView.contentOffset = CGPointZero;
// START SECOND PART OF ANIMATION
[UIView animateWithDuration:0.5 delay:0.0 options: options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationOptionAllowAnimatedContent animations:^{
// fadeIn - animated
pagingScrollView.alpha = 1;
} completion:^(BOOL finished) {
// ANIMATION ENDED
[self refreshPages];
}];
}];
NEW EDIT:
thanks to amadour, who taught me something with his comments,
i hope he could add an answer of his own, i would vote for him
anyway, to answer to jowie original question:
i got the right animation just moving the contentOffset setting out of the animation block,
and removing UIViewAnimationOptionAllowAnimatedContent (not really needed), and passing pagingScrollView as parameter for transitionWithView
this worked for me:
pagingScrollView.contentOffset = CGPointZero;
[UIView transitionWithView:pagingScrollView duration:3.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
// pagingScrollView.contentOffset = CGPointZero; // move up, outside of animation block
} completion:^(BOOL finished) {
NSLog(#"-->> END amimation");
[self refreshPages];
}];

Resources