I am creating a custom NSLayoutConstraint subclass and I need to know if the layout constraint's constant property is currently animating for internal state handling. In other words, I need to distinguish between:
{ //no animation
myLayoutConstraint.constant = 100;
}
and
{ //animated
myLayoutConstraint.constant = 100;
[UIView animateWithDuration:0.2 animations:^{
[self.myViewThatHasTheConstraintAttached layoutIfNeeded];
} completion:^(BOOL finished) {
[...]
}];
}
So that I can handle corner cases for receiving a message on the middle of an animation. Is this possible?
The only way to do this would be to have a boolean wherever you want to access this and do something like...
{ //no animation
theView.animatingChange = NO;
myLayoutConstraint.constant = 100;
}
{ //animated
theView.animatingChange = YES;
myLayoutConstraint.constant = 100;
[UIView animateWithDuration:0.2 animations:^{
[self.myViewThatHasTheConstraintAttached layoutIfNeeded];
} completion:^(BOOL finished) {
[...]
theView.animatingChange = NO;
}];
}
The property on the view changes immediately to the "end" value of the animation. It doesn't get changed to all the intermediate values while it is animating. Just the drawing on the screen is animated.
Related
is it possible to put animation to UITableView?
I currently have this:
- (IBAction)mPesoAccount:(id)sender {
if (accountBalanceTableView.isHidden) {
accountBalanceTableView.hidden = NO;
} else {
accountBalanceTableView.hidden = YES;
}
}
it hides or show the uitableview whenever i click a button, i would like to add an animation when i'm hiding and showing the uitableview
it would similar like a dropdown item, where it slides up into the button and collapses down when the button clicked again.
Simply animating your UITableView frame if you are using non constraints approach, or making the bottom constraint IBOutlet and changing the constant value
- (void)viewDidLayoutSubViews
{
[super viewDidLayoutSubViews];
self.originalTableViewFrame = accountBalanceTableView.frame;
}
- (IBAction)mPesoAccount:(id)sender {
if (accountBalanceTableView.isHidden)
{
[UIView animateWithDuration:.3 animations:^{
accountBalanceTableView.frame = self.originalTableViewFrame;
}completion:^(BOOL finished) {
accountBalanceTableView.hidden = NO;
}];
}
else
{
[UIView animateWithDuration:0.3 animations:^{
accountBalanceTableView.frame = CGRectMake(originalTableViewFrame.origin.x, originalTableViewFrame.origin.y + originalTableViewFrame.size.height, originalTableViewFrame.size.width, 0);
} completion:^(BOOL finished) {
accountBalanceTableView.hidden = YES;
}];
}
}
I am using this message to animate a customer view to the lower edge of the device screen. I've connected the layout constraint and set initial constant as -60. When the value is set to 0, I expect the view to animate to top. But unfortunately the expected functionality is not working. Even the method is called, the view is hoped up when interface orientation changes. I am using Xcode 6.4 and iOS 8 as base sdks. Any help will be appreciated.
if (alertVisible)
{
self.alertViewVerticalConstraint.constant = 0;
[UIView animateWithDuration:0.25 animations: ^{
[self.view bringSubviewToFront:self.alertView];
self.alertView.alpha = 0.5;
[self.alertView layoutIfNeeded];
}];
}
else
{
self.alertViewVerticalConstraint.constant = -60;
[UIView animateWithDuration:0.25 animations: ^{
self.alertView.alpha = 0.0;
[self.alertView layoutIfNeeded];
}];
}
Whenever you want to animate the constraint changes, you have to defines the line within the animation block.
So your code will become something like this,
if (alertVisible)
{
[UIView animateWithDuration:0.25 animations: ^{
self.alertViewVerticalConstraint.constant = 0;
[self.view bringSubviewToFront:self.alertView];
self.alertView.alpha = 0.5;
[self.view layoutIfNeeded];
}];
}
else
{
[UIView animateWithDuration:0.25 animations: ^{
self.alertViewVerticalConstraint.constant = -60;
self.alertView.alpha = 0.0;
[self.view layoutIfNeeded];
}];
}
This is my collectionview when i swipe it scrolls,
i have putted UICollectionView and button in UIPageControl, when swipe UICollectionView scrolling, and button view not scrolling smoothly as works as normal UIPageControl
I'm not sure but I think it has something to do with your CATransitions
Try changing the last piece of the method so you use UIView animations instead of CATransitions:
if(pageControl.currentPage==pageControl.numberOfPages-1)
{
[UIView animateWithDuration:0.2
animations:^{
dayRadialCollection.alpha = 0.0f;
addWeek.alpha = 1.0f;
removeWeek.alpha = 1.0f;
} completion:^(BOOL finished) {
}];
}
else {
[UIView animateWithDuration:0.2
animations:^{
dayRadialCollection.alpha = 1.0f;
addWeek.alpha = 0.0f;
removeWeek.alpha = 0.0f;
} completion:^(BOOL finished) {
}];
}
There is also no need to hide the elements, as alpha 0.0f will not show them anyway.
I have a view controller that have a scroll view that bounce horizontally , and in this scroll view I have a label.
I can now hold the label and scroll it down, and if I release it will bounce up back.
What I want is that: When I scroll the view y coordinate (using myScrollView.contentOffset.y) to some value, lets say -33 and under I can release my fine and the label will animate to the bottom of the screen and disappear, and now I can set the label to be a new value, and It will animate from top to the label original position.
Here a photo of how the view controller looks like:
And this is the relevant method I already implemented (powered by #rebello95):
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.myScrollView.contentOffset.y <= -73) {
[UIView animateWithDuration:0.3 animations:^{
self.homeLabel.alpha = 0.0;
} completion:^(BOOL finished) {
[self.homeLabel removeFromSuperview];
self.homeLabel = nil;
}];
}
NSLog(#"%f", self.myScrollView.contentOffset.y);
}
Now I want it to slide to the bottom of the page and fade.
thanks!
EDIT: The animation now moves the label to the bottom of the view controller then fades it out.
You can use an animation block to move the label, then put another block inside the completion block to fade out the label, then remove it after the animation completes.
Example:
[UIView animateWithDuration:0.3 animations:^{
[self.myLabel setFrame:CGRectMake(self.myLabel.frame.origin.x, self.view.frame.size.height - self.myLabel.frame.size.height, self.myLabel.frame.size.width, self.myLabel.frame.size.height)];
self.labelRemoving = YES;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
[self.myLabel removeFromSuperview];
self.myLabel = nil;
self.labelRemoving = NO;
}];
}];
Sidenote: You should probably be using <= instead of == in your if statement to achieve your desired results. In addition, you may want to set a flag to indicate that your label is being removed (since that method will inevitably be called multiple times). Something like this:
//.h
#property (nonatomic, assign) BOOL labelRemoving;
//.m
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.myScrollView.contentOffset.y <= -33 && !self.labelRemoving) {
[UIView animateWithDuration:0.3 animations:^{
[self.myLabel setFrame:CGRectMake(self.myLabel.frame.origin.x, self.view.frame.size.height - self.myLabel.frame.size.height, self.myLabel.frame.size.width, self.myLabel.frame.size.height)];
self.labelRemoving = YES;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
[self.myLabel removeFromSuperview];
self.myLabel = nil;
self.labelRemoving = NO;
}];
}];
}
NSLog(#"%f", self.myScrollView.contentOffset.y);
}
There's an array with uiviews. Their frames are set due to current interfaceOrientation
Then we add these views to self.view programmatically using
-(void)placeView
{
if ([self.arrayWithViews count] > 0)
{
[UIView animateWithDuration:1.f animations:^{
UIView *currentView = [self.arrayWithViews lastObject];
[currentView setAlpha:0.f];
[self.view addSubview:currentView];
[currentView setAlpha:1.f];
[self.arrayWithViews removeLastObject];
} completion:^(BOOL finished) {
[self placeView];
}];
}
}
Now, if the orientation change happens the views keep adding (with coordinates corresponding to previous orientation).
The question is - how to stop the animation process or how to prevent interface orientation change while the animation takes place.
P.S. [self.view.layer removeAllAnimations] doesn't work (I didn't figure out why)
Could you please advise what to do?
removeAllAnimations will still call completion block, so you repeat to call placeView, so you need add a flag:
-(void)placeView
{
if(!self.runAni){ //Add a flag to stop repeat to call [self placeView]
return;
}
if ([self.arrayWithViews count] > 0)
{
[UIView animateWithDuration:1.f animations:^{
UIView *currentView = [self.arrayWithViews lastObject];
[currentView setAlpha:0.f];
[self.view addSubview:currentView];
[currentView setAlpha:1.f];
[self.arrayWithViews removeLastObject];
} completion:^(BOOL finished) {
[self placeView];
}];
}
}
to stop animation, you should do :
self.runAni = NO;
[self.view.layer removeAllAnimations];
begin to do:
self.runAni = YES;
[self placeView];