Hiding and showing UITableview with slide down and slide up animation - ios

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;
}];
}
}

Related

How to put UICollectionView and button in UIPageControl in ios?

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.

How to animate deletion of a label?

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);
}

UISegementedControl reverts back to original frame after touch

Every time I click on my UISegementedControl it snaps back to its original frame. I can see it barely through my translucent toolbar.
I have a UIViewController with a UITableView, and UIToolBar like this:
There is a UISegmentedControl hidden just below the table view, behind the toolbar:
The Filter button calls the 'onFilterButtonPressed' method
- (IBAction)onFilterButtonPressed:(id)sender
{
if(self.filterBar.hidden){
[self showFilterBar];
} else {
[self hideFilterBar];
}
}
- (void)hideFilterBar
{
CGRect filterBarFrame = CGRectMake(0, self.view.frame.size.height+(self.filterBar.frame.size.height+1), self.filterBar.frame.size.width, self.filterBar.frame.size.height);
CGRect tableViewFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y,self.tableView.frame.size.width, self.tableView.frame.size.height+(self.filterBar.frame.size.height+1));
[UIView animateWithDuration:0.3 animations:^{
[self.filterBar setFrame:filterBarFrame];
[self.tableView setFrame:tableViewFrame];
} completion:^(BOOL finished) {
self.filterBar.hidden = YES;
}];
}
- (void)showFilterBar
{
CGRect filterBarFrame = CGRectMake(0, self.view.frame.size.height-(self.filterBar.frame.size.height+1), self.filterBar.frame.size.width, self.filterBar.frame.size.height);
CGRect tableViewFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y,self.tableView.frame.size.width, self.tableView.frame.size.height-(self.filterBar.frame.size.height+1));
self.filterBar.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
[self.tableView setFrame:tableViewFrame];
[self.filterBar setFrame:filterBarFrame];
}];
}
This is because of auto layout. With that turned on (which it is by default), you should do any positioning or resizing of views by modifying constraints, not setting frames.

How to check if NSLayoutConstraint is animating

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.

Second touch animation

Trying to get to grips with Xcode and seem to be making some progress over the last few weeks.
Does anyone know a way that a custom button can do a different set of animations on a second click.
So let say I have a custom button and its of Mario, when i click it he runs from the middle of the screen and out of the right hand side of the screen and then runs back in to the middle from the left of the screen, he also makes noise.
I have achieved this using this code:
- (IBAction)marioRunning_clicked:(id)sender
{
[UIView animateWithDuration:1.50 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
marioRunning.center = CGPointMake(350.5, 456.0);
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:0.00 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
marioRunning.center = CGPointMake(-30.5, 456.0);
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:1.50 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
marioRunning.center = CGPointMake(160.0, 456.0);
} completion:^(BOOL finished) {
if(finished) // NSLog ( #"Finished !!!!!" );
marioRunning.center = CGPointMake(160.0, 456.0);
}];
}
}];
}
}];
marioRunning.imageView.animationImages = [NSArray arrayWithObjects:[UIImage imageNamed:#"mario-running2"],[UIImage imageNamed:#"mario-running3"],nil];
marioRunning.imageView.animationDuration = 0.15;
marioRunning.imageView.animationRepeatCount = 19;
[marioRunning.imageView startAnimating];
}
How could I make him do a second set of animations on the next click? For example instead of running from left to right, if i tap him the second time he will Jump up and down?
Use the selected state of the button to decide which animation to do
-(void)buttonClicked:(UIButton*)button
{
if(button.selected)
{
[self doAnimation1];
}
else
{
[self doAnimation2];
}
button.selected = !button.selected;
}
This might be overkill, but here's a cool way to do what you want:
Make a subclass of UIButton, and let's call it DDDMarioButton:
typedef void (^DDDAnimationBlock)(UIButton *button);
#interface DDDMarioButton : UIButton
- (void)addAnimationBlockToQueue:(DDDAnimationBlock)block;
#end
Then in DDDMarioButton.m:
#interface DDDMarioButton ()
#property (nonatomic, strong) NSMutableArray *animationQueue;
#end
#implementation DDDMarioButton
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void)buttonPressed:(id)button
{
DDDAnimationBlock block = self.animationQueue[0];
block(self);
[self.animationQueue removeObjectAtIndex:0];
}
- (void)addAnimationBlockToQueue:(DDDAnimationBlock)block
{
if(!self.animationQueue)
{
self.animationQueue = [NSMutableArray new];
}
[self.animationQueue addObject:block];
}
#end
and then wherever you create your buttons, you add each step one by one:
DDDMarioButton *button = [[DDDMarioButton alloc] initWithFrame:CGRectZero];
[button addAnimationBlockToQueue:^(UIButton *button) {
// perform some animation
}];
[button addAnimationBlockToQueue:^(UIButton *button) {
// perform another animation
}];
And that should do it. I haven't tested this, you'll probably need some configuration, but that's pretty much the idea.

Resources