How to translate an entire UIView and retain gesture recognition? - ios

I have a UIView "MainView" that initially appears as follows:
The gradient bar is part of MainView, the whitespace beneath is part of a Container View subview.
When the search button in top-right is tapped, I animate a searchBar from offscreen to be visible in the view:
I manage to do this by the following code:
CGRect currentViewFrame = self.view.bounds;
currentViewFrame.origin.y += searchViewHeight;
[UIView animateWithDuration:0.4
delay:0.0
usingSpringWithDamping:1.0
initialSpringVelocity:4.0
options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.view.frame = currentViewFrame;
}
completion:^(BOOL finished)
{
}];
Visually, the result of this animation is perfect. The entire view shifts, and the searchBar is now on screen. However, the searchBar does not respond to interaction. Correct me if I'm wrong, but I expect this is because the MainView's frame no longer includes the screen area that the searchBar now occupies, so its effectively a gesture deadzone.
So this makes me think that instead of lazily animating the entire MainView down to accomodate the searchBar, I must instead individually translate all subviews of MainView one at a time. In this simple situation, that would not be a big problem, but I can envision a circumstance with tens of subviews making that completely unrealistic.
What is the best method to accomplish what I am trying to do? Is there a secret to animating entire views/subviews without having gesture deadzones? Thanks in advance!!

Related

Unable to hide UIView completely

I am trying to hide a UIView but nothing work so far. The UIView is at the bottom of a UITableView, not inside it as a cell. Here is what I tried so far:
self.viContainerLocation.hidden = YES;
self.viContainerLocation.alpha=0.0;
CGRect Conframe = self.viContainerLocation.frame;
Conframe.size.height = self.view.bounds.size.height;
self.viContainerLocation.frame = Conframe;
self.tableView.translatesAutoresizingMaskIntoConstraints=NO;
__block CGRect frame=self.tableView.frame;
frame.size.height= self.view.frame.size.height-frame.origin.y;
frame.size.width=self.view.frame.size.width;
self.tableView.frame=frame;
viContainerLocation is the UIView I am trying to hide. The above code hide all elements inside the UIView, but leaves a white space with the dimensions of the UIView.
For a reason I don't understand, viContainerLocation is hidden when I use this code:
[UIView transitionWithView:self.viContainerLocation
duration:0.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{ }
completion:^(BOOL finish){
__block CGRect frame=self.tableView.frame;
frame.size.height= self.view.frame.size.height-frame.origin.y;
frame.size.width=self.view.frame.size.width;
self.tableView.frame=frame;
}];
But using this code the white space gets displayed of a fraction of a second and it doesn't look good.
How can I make it go away from the beginning ?
You are misunderstanding something.
When hidding an UIView, the space occupied by this view is still visible.
If you want your tableview filling the missing space, the quickest way is to ember your tableview and your view into a UIStackView.
In a UIStackView when you set one subview to isHidden=true, the view is removed, and other views fill the left space.
More infos here : https://developer.apple.com/documentation/uikit/uistackview

How can I make a table view appear when a button is pressed/tapped?

I am trying to make a UITableView appear when a user taps on a button and disappear when the button is re-tapped.
I implemented the following code but nothing seems to appear when I tap the button.
- (IBAction)dropDown:(UIButton *)sender
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.6];
CGAffineTransform transfrom = CGAffineTransformMakeTranslation(0, 200);
self.markersTableView.transform = transfrom;
self.markersTableView.alpha = self.markersTableView.alpha * (-1) + 1;
[UIView commitAnimations];
}
What may potentially be the issue?
EDIT:
I was able to make the UITableView appear and disappear by adding self.markersTableView.hidden = YES; in viewDidLoad() and self.markersTableView.hidden = NO; in the IBAction method.
However, the table view disappears when I initially tap on the button as shown in the screenshot:
The fading of the rows is an indication it is moving down the screen, and then it disappears.
It only reappears when I re-tap on the UIButton the 2nd time.
Any clues?
Don't use a transform on your table view. That will make it LOOK like it's in a different position, but it won't respond to taps correctly.
Instead, use the newer UIView block-based animation methods and change the view's center.
The code might look like this (if you're NOT using auto-layout)
[UIView AnimateWithDuration: .2
animations: ^
{
CGPoint center = self.markersTableView.center;
center.y += 200;
self.markersTableView.center = center;
}
];
If you're using auto-layout, though, that won't work and you will need to animate the view's position using constraints.
From memory, here's an outline of how to do auto-layout based animations: You would create a vertical position constraint on your table view and connect the constraint to an IBOutlet in your view controller. In your animation code you change the constant of the constraint (the vertical position) and then in the animation block, send the view a needsLayout message.

With Objective-C, how can I animate the frame position of a bottom layer without affecting top layers?

I have two UIImageView's, one that is a background that should scroll, and one an avatar that should move positions based on user input.
I'm able to move the avatar with no problem, and I'm able to scroll my background when necessary with:
CGRect oldPos = _fieldView.frame;
CGRect newPos = CGRectMake(oldPos.origin.x, oldPos.origin.y - 400, oldPos.size.width, oldPos.size.height);
[UIView animateWithDuration:5.0
delay:0.0
options: UIViewAnimationCurveEaseOut
animations:^{
[_fieldView setFrame:newPos];
}
completion:^(BOOL finished){
NSLog(#"Done with animation");
}];
However, when this _fieldview scrolls, my avatar on top of it scrolls with it. How can I move my background image without affecting the other images?
A few other settings that may affect this:
I've disabled AutoLayout
My background image mode is set to AspectFill
I'm using a storyboard with a single UIView
Thank you for any suggestions.
EDIT
The avatar, runnerView, is added as a subview of _fieldView, with
[_fieldView addSubview:_runnerView];
You want your background scroll image to not be a superview to your avatar, but sibling view instead.
(Not the best representation, not sure how to make it look better though)
-Main View
--Scroll view
--Avatar
i.e.
[self.view addSubview:backgroundView];
[self.view addSubview:avatarView];
not
-Main View
--Scroll view
---Avatar
i.e.
[backgroundView addSubview:avatarView];
[self.view addSubview:backgroundView];
If it is required to be a subview, then you will have to move the avatar view an equal and opposite amount so it will stay in the same relative location.

Animate exit of UIView

I want to make a UIView animate when it's being closed. I tried reading the following:
http://felipe.sabino.me/ios/2012/05/10/ios-uiview-transition-effects/
iPhone UIView Animation Best Practice
iOS UIView Animation CATransform3DMakeRotation confusion
However, I'd like to make it transition from the side of the screen, as per the image in the Google Chrome app.
Is there another animation that is set for this? I was not able to find it... I'm assuming it has to do with animateWithDuration or a CATransform...can somebody point me in the right direction for this?
[EDIT]
I used the below post for an answer as well as this post:
Setting a rotation transformation to a UIView or its layer doesn't seem to work?
I was able to add multiple animations as per below:
[UIView animateWithDuration: .2
delay: 0
options: (UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
animations:^{self.view.center = CGPointMake(self.view.frame.origin.x * 3, self.view.frame.origin.y * 2), self.view.transform = CGAffineTransformMakeRotation(M_PI_4/2);}
completion:nil];
Previously I was not aware you can add multiple animations so easily. That adds rotation as well as the linear movement together.
Animate your view so it moves offscreen/shrinks/expands/fades, then do the actual removal when the animation ends.
You can do this by altering the properties of the view (position/size/offset) between a beginAnimations/commitAnimations block. UIKit will then animate these properties over the time specified.
E.g something like;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.30f];
view.transform =
CGAffineTransformMakeTranslation(
view.frame.origin.x,
480.0f + (view.frame.size.height/2) // move the whole view offscreen
);
background.alpha = 0; // also fade to transparent
[UIView commitAnimations];
In the animation end notification you can then remove the view.
I've never run Chrome on iOS, so I have to try to guess what your screenshot is showing.
Does the animation go off the screen while shrinking and turning to one side?
And do you mean you want to animate a UIViewController, or a UIView? Are you closing a view controller?
If it's a view controller, how are you managing your view controllers? Are you using a navigation controller, or are you presenting a set of modal view controllers, or some other method?

UIView animation while scrolling a table

I have a UITableView in an iPad, and its right half side is covered with a view.
What I want is: when the user scroll the UITableView, I want the covering view to slide (with an animation) to the right until its origin.x is at the end of the right side of the table, so the UITableView is clear to see (just like in the Twitter app for iPad).
The problem is: You can scroll the UITableView and animate a view at the same time. When I start scrolling, I use didStartDraging and even DidScroll to create a [UIView animate...] method, but this method stuck my scrolling.
I tired with block animation. I tried with Gestures. I tried with CABasicAnimation, and it goes quite OK, but somehow all the UISubview "Touch area" in my sliding view stay at the old place (what I mean is that the view gets its new frame, but I can scroll a UIScrollView, which is a UISubview of my view, even when my finger is out of the superviews frame S-:, even that there is no view at that point on screen.)
Any thoughts how can I make the animation without damaging the scroll of the table? (and I heard about the timer in the K and the runloop common modes. Not so helping)
Thanks.
scrollview Delegate methods will be invoked for tableView also ............
you can use following code it worked for me and hope will work for you also.......
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[UIView animateWithDuration:0.3 animations:^{
[scrollView setFrame:CGRectMake(50, scrollView.frame.origin.y, scrollView.frame.size.width, scrollView.frame.size.height)];
}];
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[UIView animateWithDuration:0.3 animations:^{
[scrollView setFrame:CGRectMake(100, scrollView.frame.origin.y, scrollView.frame.size.width, scrollView.frame.size.height)];
}];
}
set x position of scrollView(tableView) as your requirement......
Have a happy coding....

Resources