I need to change UIView position on scroll of tableview. When i change the frame size of UIView in the animation block it goes down and than move to correct position. Please look at my code.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint scrollVelocity = [_collectionViewLeaderboard.panGestureRecognizer velocityInView:_collectionViewLeaderboard.superview];
if (scrollVelocity.y > 0.0f){
NSLog(#"going down");
[UIView animateWithDuration:0.3f
animations:^ {
_headerview.frame = CGRectMake(0, 0, _headerview.frame.size.width, _headerview.frame.size.height);
_headerviewSecond.frame = CGRectMake(0, _headerview.frame.size.height, _headerviewSecond.frame.size.width, _headerviewSecond.frame.size.height);
self.collectionViewLeaderboard.frame = CGRectMake(self.view.frame.origin.x, _headerviewSecond.frame.size.height+_headerview.frame.size.height, self.view.frame.size.width, self.view.frame.size.height);
frameconditon = _headerview.frame;
} completion:^ (BOOL completed) {
}];
}
else if (scrollVelocity.y < 0.0f){
NSLog(#"going up");
//CGAffineTransform transform = CGAffineTransformMake(1, 0, 0, 1, _headerview.frame.origin.x, _headerview.frame.origin.y);
[UIView animateWithDuration:5.0 animations:^{
NSLog(#"test");
_headerview.frame = CGRectMake(0, -(_headerview.frame.size.height), _headerview.frame.size.width, _headerview.frame.size.height);
_headerviewSecond.frame = CGRectMake(0, (_headerview.frame.size.height)-40, _headerviewSecond.frame.size.width, _headerviewSecond.frame.size.height);
} completion:^(BOOL finished) {
}];
self.collectionViewLeaderboard.frame = CGRectMake(self.view.frame.origin.x, _headerviewSecond.frame.size.height, self.view.frame.size.width, self.view.frame.size.height);
}
}
headerview should move to top of view and it work but when i run it first time, it goes down and back to correct postion. How will i change constraints at the time of scrolling.
For constraint based views try to animate through changing constraints constant property using an outlet.
Related
I want to change view frame to full screen bounds and transform to landscape.
I used UIView animation change frame and view's transform.
- (void)enterFullScreen {
CGRect frame = CGRectMake(0, 0, CGRectGetHeight(UIScreen.mainScreen.bounds), CGRectGetWidth(UIScreen.mainScreen.bounds));
self.originFrame = self.presentView.frame;
[UIView animateWithDuration:ZXYAnimationDuration animations:^{
self.presentView.transform = CGAffineTransformMakeRotation(M_PI_2);
self.presentView.frame = frame;
} completion:^(BOOL finished) {
}];
}
- (void)exitFullScreen {
[UIView animateWithDuration:ZXYAnimationDuration animations:^{
self.presentView.transform = CGAffineTransformIdentity;
self.presentView.frame = self.originFrame;
} completion:^(BOOL finished) {
}];
}
I expect the view rotate to landscape and full screen, but seems rotate error.
Finally, I tried it out, the answer is, do not exchange width and heigh, just like below:
- (void)enterFullScreen {
CGRect frame = CGRectMake(0, 0, CGRectGetWidth(UIScreen.mainScreen.bounds), CGRectGetHeight(UIScreen.mainScreen.bounds));
self.originFrame = self.presentView.frame;
[UIView animateWithDuration:ZXYAnimationDuration animations:^{
self.presentView.transform = CGAffineTransformMakeRotation(M_PI_2);
self.presentView.frame = frame;
} completion:^(BOOL finished) {
}];
}
- (void)exitFullScreen {
[UIView animateWithDuration:ZXYAnimationDuration animations:^{
self.presentView.transform = CGAffineTransformIdentity;
self.presentView.frame = self.originFrame;
} completion:^(BOOL finished) {
}];
}
I have UITableView and i want to animate when user click on Button.
For Selected State --> BOTTOM TO TOP
For UnSelected State --> TOP TO BOTTOM
For that I have tried Below Code.
My TableView frame (0,39, width, height)
- (IBAction)onInviteFriendsButtonClick:(UIButton *)sender {
sender.selected =! sender.selected;
if (sender.selected) {
CGRect napkinBottomFrame = self.tblVWInviteFriend.frame;
napkinBottomFrame.origin.y = [UIScreen mainScreen].bounds.size.height;
self.tblVWInviteFriend.frame = napkinBottomFrame;
[UIView animateWithDuration:0.5 delay:0.0 options: UIViewAnimationOptionTransitionCurlUp animations:^{
self.tblVWInviteFriend.frame = CGRectMake(0, 39, self.tblVWInviteFriend.frame.size.width, self.tblVWInviteFriend.frame.size.height);
} completion:^(BOOL finished){/*done*/}];
}
else {
CGRect napkinBottomFrame = self.tblVWInviteFriend.frame;
napkinBottomFrame.origin.y = 39;
self.tblVWInviteFriend.frame = napkinBottomFrame;
[UIView animateWithDuration:0.5 delay:0.0 options: UIViewAnimationOptionTransitionCurlDown animations:^{
self.tblVWInviteFriend.frame = CGRectMake(0, -[UIScreen mainScreen].bounds.size.height, self.tblVWInviteFriend.frame.size.width, self.tblVWInviteFriend.frame.size.height);
} completion:^(BOOL finished){/*done*/}];
}
}
When i click button it will animate from BOTTOM TO TOP properly.
but when i click button again it will again gone from BOTTOM TO TOP.
Because you have set frame.origin.y of tableview is -y or XY coordinate.
self.tblVWInviteFriend.frame = CGRectMake(0, -[UIScreen mainScreen].bounds.size.height, self.tblVWInviteFriend.frame.size.width, self.tblVWInviteFriend.frame.size.height);
replace with this
self.tblVWInviteFriend.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height, self.tblVWInviteFriend.frame.size.width, self.tblVWInviteFriend.frame.size.height);
Try this :
- (IBAction)onInviteFriendsButtonClick:(UIButton *)sender {
sender.selected =! sender.selected;
if (sender.selected) {
CGRect napkinBottomFrame = txtAOP.frame;
napkinBottomFrame.origin.y = [UIScreen mainScreen].bounds.size.height;
txtAOP.frame = napkinBottomFrame;
[UIView animateWithDuration:0.5 delay:0.0 options: UIViewAnimationOptionTransitionCurlUp animations:^{
txtAOP.frame = CGRectMake(0, 39, txtAOP.frame.size.width, txtAOP.frame.size.height);
} completion:^(BOOL finished){/*done*/}];
}
else {
CGRect napkinBottomFrame = txtAOP.frame;
napkinBottomFrame.origin.y = -[UIScreen mainScreen].bounds.size.height;
txtAOP.frame = napkinBottomFrame;
[UIView animateWithDuration:0.5 delay:0.0 options: UIViewAnimationOptionTransitionCurlDown animations:^{
txtAOP.frame = CGRectMake(0,39 , txtAOP.frame.size.width, txtAOP.frame.size.height);
} completion:^(BOOL finished){/*done*/}];
}
}
viewDidLoad :
topBarMenu = [[TopBarMenu alloc] initWithFrame:CGRectMake(0, 64, 1024, 0)];
[self.view addSubview:topBarMenu];
topBarMenu.clipsToBounds = YES;
- (void)menuButton_TouchUpInside:(TopBarIcon *)sender
{
isTopBarMenuShown = !isTopBarMenuShown;
if (isTopBarMenuShown) {
[UIView animateWithDuration:1.5 animations:^{
topBarMenu.frame = CGRectMake(0, 64, 1024, 600);
}];
}else {
[UIView animateWithDuration:1.5 animations:^{
topBarMenu.frame = CGRectMake(0, 64, 1024, 0);
}];
}
}
In my code i want to animate showing and hiding my menu. Showing is very stepped and dosen't look nice. Hiding immediately remove the screen without any animation. How to solve this problem ?
You need to set constant when you are using Autolayout and Animation. So, set constant before you begin the Animation. So, create outlet of constrain of y position.
topbaryposition.constant=0; (IBOutlet of Top position (Y postion of Topbar))
- (void)menuButton_TouchUpInside:(TopBarIcon *)sender
{
isTopBarMenuShown = !isTopBarMenuShown;
if (isTopBarMenuShown) {
[UIView animateWithDuration:1.5 animations:^{
topBarMenu.frame = CGRectMake(0, 64, 1024, 600);
}];
}else {
[UIView animateWithDuration:1.5 animations:^{
topBarMenu.frame = CGRectMake(0, 64, 1024, 0);
}];
}
}
Something like ,
Edit :-
I found your Issue .
Your issue is seeting the frame in else when you hiding the topbar.you have set only height as 0 but you also need to set y positioan as 0..
Something like ,
topBarMenu.frame = CGRectMake(0, 0, 1024, 0);
- (void)menuButton_TouchUpInside:(TopBarIcon *)sender
{
isTopBarMenuShown = !isTopBarMenuShown;
if (isTopBarMenuShown) {
[UIView animateWithDuration:1.5 animations:^{
topBarMenu.frame = CGRectMake(0, 64, 1024, 600);
}];
}else {
[UIView animateWithDuration:1.5 animations:^{
topBarMenu.frame = CGRectMake(0, 0, 1024, 0);
}];
}
}
try this
if (sideView.frame.origin.x >= 0 )
{
[UIView animateKeyframesWithDuration:0.5 delay:0 options:UIViewKeyframeAnimationOptionBeginFromCurrentState animations:^{
sideView.frame=CGRectMake(-400, 45, CGRectGetWidth(sideView.frame), CGRectGetHeight(sideView.frame));
} completion:^(BOOL finished) {
}];
}
else
{
[UIView animateKeyframesWithDuration:0.5 delay:0 options:UIViewKeyframeAnimationOptionBeginFromCurrentState animations:^{
sideView.frame=CGRectMake(0, 45, CGRectGetWidth(sideView.frame), CGRectGetHeight(sideView.frame));
} completion:^(BOOL finished)
{
}];
}
I think set frame directly is not a very good method,I suggest to change frame is more appropriate.
Such as:
- (void)menuButton_TouchUpInside:(TopBarIcon *)sender
{
isTopBarMenuShown = !isTopBarMenuShown;
if (isTopBarMenuShown) {
[UIView animateWithDuration:1.5 animations:^{
CGRect rect = topBarMenu.frame;
rect.size.height = 600.0f;
topBarMenu.frame = rect;
//topBarMenu.frame = CGRectMake(0, 64, 1024, 600);
}];
} else {
[UIView animateWithDuration:1.5 animations:^{
CGRect rect = topBarMenu.frame;
rect.size.height = 0.0f;
topBarMenu.frame = rect;
//topBarMenu.frame = CGRectMake(0, 64, 1024, 0);
}];
}
}
I am new to animation, and trying to write a custom segue to achieve slide out a side menu from left to right, overlay the home view, and occupy half of the screen.
There is a custom segue code:
#import "CustomSegue.h"
#implementation CustomSegue
- (void)perform {
UIViewController *contentVC = self.sourceViewController;
UIViewController *sideBarVC = self.destinationViewController;
CGRect sideFrame = sideBarVC.view.frame;
[sideBarVC.view setFrame: CGRectMake(0, 0, 0, contentVC.view.frame.size.height)];
CGRect animationFrame = contentVC.view.frame;
sideFrame = sideBarVC.view.frame;
animationFrame.size.width = contentVC.view.frame.size.width / 2;
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:
^{
sideBarVC.view.frame = animationFrame;
}
completion:
^(BOOL finished) {
sideBarVC.view.frame = animationFrame;
contentVC.view.alpha = 0.5f;
[[contentVC.view superview] addSubview:sideBarVC.view];
}];
}
#end
I add some variable to see if the frame is correct, and it is correct when I change the frame.
But I don't see my "expected" animation: sideBarVC.view.frame = animationFrame;
Could some one help on this? Thanks.
If you want to have a slide from left to right animation, you will firstly have to set the original X of animating view's frame to be a negative value, then in the animation block, set original x to be 0. Something like that.
sideFrame = sideBarVC.view.frame;
sideBarVC.view.frame = CGRectOffset(sideFrame, - contentVC.view.frame.size.width, 0);
[[contentVC.view superview] addSubview:sideBarVC.view];
[UIView animateWithDuration:0.3 animations:^{
sideBarVC.view.frame = sideFrame;
contentVC.view.alpha = 0.5f;
} completion:nil];
Using your code I don't see animation happens, because sideBarVC.view is added in the completion block of the animation. By then the animation has already finished, and sideBarVC.view is added as subview and its frame is set.
Tunred out I misunderstand the position. Using below code could achieve the animation,
but it still has one problem, the side bar menu is under navigation tool bar on top of the screen. Do anyone know how to solve it?
- (void)perform {
UIViewController *contentVC = self.sourceViewController;
UIViewController *sideBarVC = self.destinationViewController;
CGRect sideFrame = sideBarVC.view.frame;
[sideBarVC.view setFrame: CGRectMake(-(contentVC.view.frame.size.width), 0, contentVC.view.frame.size.width/2, contentVC.view.frame.size.height)];
CGRect animationFrame = contentVC.view.frame;
sideFrame = sideBarVC.view.frame;
animationFrame.size.width = contentVC.view.frame.size.width / 2;
sideBarVC.view.alpha = 0;
[[[contentVC.view superview] window] addSubview:sideBarVC.view]; < -- this is important, not [superview addSubView]
[UIView animateWithDuration:1
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
sideBarVC.view.frame = animationFrame;
sideBarVC.view.alpha = 1;
}
completion:^(BOOL finished) {
sideBarVC.view.alpha = 1;
sideBarVC.view.frame = animationFrame;
}];
For Swift 3
override func perform() {
let contentVC = self.sourceViewController;
let sideBarVC = self.destinationViewController;
var sideFrame = sideBarVC.view.frame
sideBarVC.view.frame = CGRect(x: -(contentVC.view.frame.size.width), y: 0, width: contentVC.view.frame.size.width/2, height: contentVC.view.frame.size.height)
sideFrame = sideFrame.offsetBy(dx: -1 * contentVC.view.frame.size.width, dy: 0)
contentVC.view.superview?.addSubview(sideBarVC.view)
UIView.animate(withDuration: 0.3) {
sideBarVC.view.frame = sideFrame
contentVC.view.alpha = 0.5
}
}
I'm trying to make a user interface that animates when I click on it.
This is my sketch:
It starts with the mapview as small as on the left sketch. The rest is filled with a tableview. Now when I click on the map view it slides to the bottom like on the right sketch so the mapview fills the most off the screen. Ans visa versa when I click on the small Tableview.
How can I achieve this?
I thought off creating a View and then add mapview and tableview as subviews, but then I don't know how to animate that. Did some real simple animations until now.
Can someone point me in the right direction?
NSNumber isMapExpanded = 0;
- (void) expandMap
{
[UIView animateWithDuration:1.0
delay:0.2
options:nil
animations:^{
if([isMapExtended integerValue] == 0)
{
mapview.frame = CGRectMake(mapview.frame.origin.x, mapview.frame.origin.y, mapview.frame.size.width, mapview.frame.size.height + heightTobeExpanded);
tableView.frame = CGrectMake(tableView.frame.origin.x, tableView.frame.origin.y - heightTobeExpanded, tableView.frame.size.width, tableView.frame.size.height + heightTobeExpanded);
}
else if([isMapExtended integerValue] == 1)
{
mapview.frame = CGRectMake(mapview.frame.origin.x, mapview.frame.origin.y, mapview.frame.size.width, mapview.frame.size.height - heightTobeExpanded);
tableView.frame = CGrectMake(tableView.frame.origin.x, tableView.frame.origin.y + heightTobeExpanded, tableView.frame.size.width, tableView.frame.size.height - heightTobeExpanded);
}
}
completion:nil];
}
something along the lines of:
[UIView animateWithDuration:1.0
delay:0
options:nil
animations:^{
map.frame = CGRectMake(0,0,newheight,320);
table.frame = CGrectMake(0,newheight,screenheight-newheight, 320);
}
completion:nil];
you can call something like that in your click method. this is just an example - you should not use hardcoded numbers in your application :)
Please try this code:-
[UIView beginAnimations:#"Expand MApview" context:nil];
[tblView setFrame:CGRectMake(0, self.view.frame.size.height-50, tblView.frame.size.width,tblView.frame.size.height)];
[mapview setFrame:CGRectMake(0,0,mapview.frame.size.width,self.view.frame.size.height-50)];
[UIView setAnimationDelay:2];
[UIView commitAnimations];
As you already stated, put both the map and the table in a superview.
On click, you may use the following :
[UIView animateWithDuration:0.5 animations:^{
map.frame = CGRectMake(x,y,width,newHeight); //Set the frame to be with the new map height
tableView.frame = CGRectMake(x,NewYCoordinate,width,height); //Move the tableView down
}];
- (void) changeFrameBetweenMapAndTable
{
[UIView animateWithDuration:1.0
delay:0.5
options:nil
animations:^{
CGRect mapRect = mapview.frame;
mapview.frame = tableView.frame;
tableView.frame = mapRect;
}
completion:nil];
}