iOS: UIVIew back to start position after segue and popViewController - ios

I have UIViewController, there is some animation in these UIViewController. UIView that animates on this UIViewController has different start and end position. I also have segue, that will push new UIViewController to the scene. All works okay, but if I return to my first UIViewController, position of my UIVIew changes to start position.
How can I fix this?
- (void)viewDidLoad
{
[super viewDidLoad];
[UIView animateWithDuration:0.3 animations:^{
self.myView.center = CGPointMake(self.myView.center.x,self.ahotherView.center.y);
}completion:^(BOOL complete){
}];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
self.myView.center = CGPointMake(self.myView.center.x, self.ahotherView.center.y);
}

Autolayout is causing it to return to the beginning position. You can either turn it off or write a bit of code to override the constraints.
You'll have to first add constraints in Storyboard, which is an entirely different question in itself. I recommend doing some research. Once you've added the proper constraints and created IBOutlets for them, you'll be changing the values of the constraint constants, then calling [self.myView layoutIfNeeded] inside your animation block. Instead of changing the center property. Might look something like this:
//update constraint values
self.topConstraint.constant = 70;
self.bottomConstraint.constant = 20;
//animate
[UIView animateWithDuration:0.5f animations:^{
[self.myView layoutIfNeeded];
} completion:^(BOOL finished) {
}];

Related

Slide illusion creates flicker

I'm creating a custom selected-animation for my UITableView.
What I've got is a standard UIViewController that displays a UITableView, which upon didSelectRow:AtIndexPath: instantiates another VC from storyboard, prepares it and displays it modally using UIModalPresentationOverCurrentContext.
Then the second VC updates a constraint from the top layout guide to a UIImageView, hence placing it exactly where the cell was located on screen. This coordinate is passed from the first VC.
Next, this UIImageView slides up, creating the illusion that the cell slides up. However, this produces a flicker for a split second just before sliding the image quite often (not always, like 3/4 times).
What's a better way to position the UIImageView initially, before it's animated?
Here's my code doing this:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
self.imageViewTopConstraint.constant = self.cellFrame.origin.y;
[self.view layoutIfNeeded];
self.imageView.image = self.image;
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
/* animate the opening */
[UIView animateWithDuration:0.45 delay:0 usingSpringWithDamping:1.0f initialSpringVelocity:1.2f options:UIViewAnimationOptionTransitionNone animations:^{
/* slide image */
self.imageViewTopConstraint.constant = 0.0f;
[self.view layoutIfNeeded];
}completion:^(BOOL finished) {
}];
}

Auto Layout constraint change does not animate

I was learning the auto layout with animations from the tutorial
http://weblog.invasivecode.com/post/42362079291/auto-layout-and-core-animation-auto-layout-was
and things were working perfect.
When I tried to use this concept in my application, trying to animate a settings screen(a UIView) from bottom to top,it works great when the settings screen is just an empty UIView,
But in case I add a UILabel as a subview to this settings screen, the animation just vanishes.
On removing this UILabel form the settings screen, the animation is visible.
Here are the outlets that I have connected
__weak IBOutlet UIView *settingsView;
__weak IBOutlet NSLayoutConstraint *settingsBottomConstraint;
__weak IBOutlet NSLayoutConstraint *settingsViewHeightConstraint;
View did load setup method(setupViews)
-(void)setupViews
{
settingsBottomConstraint.constant = - settingsViewHeightConstraint.constant;
[settingsView setNeedsUpdateConstraints];
[settingsView layoutIfNeeded];
isSettingsHidden = YES;
}
Hide/Unhide Method
- (IBAction)showSettingsScreen:(id)sender {
if (isSettingsHidden) {
settingsBottomConstraint.constant = 0;
[settingsView setNeedsUpdateConstraints];
[UIView animateWithDuration:.3 animations:^{
[settingsView layoutIfNeeded];
}];
}
else{
settingsBottomConstraint.constant = - settingsViewHeightConstraint.constant;
[settingsView setNeedsUpdateConstraints];
[UIView animateWithDuration:0.3 animations:^{
[settingsView layoutIfNeeded];
}];
}
isSettingsHidden = !isSettingsHidden;
}
My issue seems similar to the
Issue with UIView Auto Layout Animation
I found the answer.
Instead of,
[settingsView layoutIfNeeded];
this line made it worked like charm,
[self.view layoutIfNeeded];
I suppose we need to perform layoutIfNeeded method on the parent view not just the view we are trying to animate.
UPDATE:
As pointed out in a comment by codyko, this is required for iOS 7, iOS 10.
For iOS 8 this issue does not exists.

Storyboard to design off screen subview

I want to use Storyboards to design content for a slider, and it seems like an easy way to design offscreen content is to use a childViewController. So I've done this
myViewController = [[UIStoryboard storyboardWithName:#"ipad" bundle:NULL] instantiateViewControllerWithIdentifier:#"keyPadOffScreen"];
[self addChildViewController:myViewController];
[myViewController didMoveToParentViewController:self];
newView = myViewController.view;
[self.view addSubview:newView];
And that adds the entire view controller over top of my root view. The problem is, I only want one of the subviews to show up, not the whole view. I can handle the animation, as long as I know how to add the root view. I tried this to just add the subview (sliderView is the name of the subview I want) instead of the whole view, but that did nothing
newView = myViewController.sliderView;
[self.view addSubview:newView];
Should I be using a different strategy?
EDIT: this DOES work, but it seems silly - setting the views size to just be the size of the subview.
newView.frame = CGRectMake(newView.frame.origin.x, newView.frame.origin.y, newView.frame.size.width, **myViewController.sliderView.frame.size.height**);
It does seem a bit overkill for just a view. Once you start doing a lot of custom view/animation/transition stuff it's often easier to implement in code, or at least it is for me since I've been doing it that way for a long time.
But maybe you want to stick with Storyboards. I respect that. And if you have a few developers working on this then it's important to keep some uniformity to how you set up your UI.
Instead of keeping it in a separate view controller and adding it when you need it to animate on-screen, simply add it to your existing view controller and either set it to hidden, or set it's alpha to 0.0 in IB. Then your animation can undo that and make it visible.
you can use custom segue here, for instance:
#implementation FRPresentEnteringPopupSegue
- (void)perform
{
FirstVC *toVC = self.destinationViewController;
SecondNavigationController *fromVC = self.sourceViewController;
toVC.view.frame = CGRectMake(0.0, 0.0, 300.0, 135.0);
toVC.view.center = CGPointMake(fromVC.view.bounds.size.width/2, fromVC.view.bounds.size.height + toVC.view.bounds.size.height/2);
[fromVC.view addSubview:toVC.view];
[toVC viewWillAppear:YES];
[UIView animateWithDuration:0.5
delay:0.0
usingSpringWithDamping:0.7
initialSpringVelocity:0.5
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
toVC.view.center = CGPointMake(fromVC.view.bounds.size.width/2, fromVC.view.bounds.size.height/2);
}completion:^(BOOL finished) {
[toVC viewDidAppear:YES];
}];
}
#end
make your UIStoryboardSegue subclass
override - (void)perform method with your custom view appearance code
use segue usual way

Toggling UITableViewCell selectionStyle causes labels on cell to disappear

I have a custom subclass of UITableViewCell. On my storyboard, it basically has a containerView (UIView *), that has some labels on it, and a UISwitch. I add a gesture to slide my tableViewCell to the right to show some detail controls underneath the containerView, and then another gesture to slide the original view back. The animation code looks like this:
- (void)showCustomControls:(UISwipeGestureRecognizer *)gesture {
[UIView animateWithDuration:0.3 animations:^{
[self.containerView setFrame:CGRectMake(self.frame.size.width - kTableViewCellSwipedWidth, 0, self.frame.size.width - kTableViewCellSwipedWidth, kOverviewTableViewCellHeight)];
}completion:^(BOOL finished) {
self.isReveal = YES;
self.selectionStyle = UITableViewCellEditingStyleNone;
}];
}
- (void)hideCustomControls:(UISwipeGestureRecognizer *)gesture {
[UIView animateWithDuration:0.3 animations:^{
[self.containerView setFrame:CGRectMake(-kTableViewCellBounceWidth, 0, self.frame.size.width, kOverviewTableViewCellHeight)];
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 animations:^{
[self.containerView setFrame:CGRectMake(-kTableViewCellBounceWidth / 2, 0, self.frame.size.width, kOverviewTableViewCellHeight)];
}completion:^(BOOL finished) {
[self.containerView setFrame:CGRectMake(0, 0, self.frame.size.width, kOverviewTableViewCellHeight)];
}];
self.isReveal = NO;
self.selectionStyle = UITableViewCellSelectionStyleBlue;
}];
}
I noticed if I left the selectionStyle on, with the row open, it looked kind of funny. So I wanted to turn the selectionstyle off. So the code in there is to turn on and off the selection style when the row is open or closed. It works, however the weird thing is, when hideCustomControls gets called, and my original row slides back into place, the labels on the container view all go away. I have a little edge of the original row that shows, and when that is showing, the labels are there. But the second that the row slides all the way in place, all the labels disappear. The UISwitch which is also on the containerView never has problems though. It is always present. Is there a reason why this may be happening? When I remove the selectionStyle code in both methods, this problem goes away. Thanks in advance.
Edit:
I put in the correct code to animate using NSLayoutConstraint. Now the problem is the UIView subclasses I have on the view underneath show through to the top view when my row slides back into place. Not sure why this happens...

iOS - Trying to fade a view controller in

In fading a view controller in from black, I am doing the following within viewDidLoad:
Creating a UIView with a black background;
Giving the UIView an alpha value of 1.0f;
Adding the UIView as a subview of [self view];
Fading the black UIView out via animateWithDuration by changing its alpha value to 0.0f; and
Removing the black UIView from [[self view] subviews]
More often than not, this works as planned. Occasionally, however, I see a glimpse of the view controller I want initially hidden, just before the black UIView is drawn.
Is there a way to avoid this? Is there a better method to place this code in than viewDidLoad?
Many thanks
Yes, add the view in the loadView method and do the actual animation in viewDidLoad or viewDidAppear. Or do as the above commentor said and simply use the view alpha.
I would create the UIView that I want hidden in UIViewController's nib file, then link that to via an IBOutlet
#interface SomeViewController: UIViewController
{
IBOutlet UIView *blackView;
}
then in UIViewController's -(void) viewDidLoad; method, I would do the following
- (void)viewDidLoad
{
[super viewDidLoad];
// Fade the opacity of blackView over 1 second,
// then remove it from the view controller.
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
blackView.layer.opacity = 0;
}
completion:^(BOOL finished) {
// This line prevents the flash
blackView.layer.opacity = 0;
[blackView removeFromSuperview];
}];
}

Resources