I use this code in objective c to make a fade in fadeout animation when the user scrolls up or down the uitableview. Is there any way to make a nice animation like shrinking the navigationbar slowly while the user scrolls to top slowly? The more he scrolls to the top the more the navigationbar should shrink.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat scrollPos = self.tableView.contentOffset.y ;
if(scrollPos >= _currentOffset ){
//hide navbar and fadeout
[UIView animateWithDuration:0.50 animations:^{
[self.navigationController setNavigationBarHidden:YES animated:YES];
self.navigationController.navigationBar.alpha = 0.0f;
}];
} else {
//Slide it up incrementally and fadein, etc.
[UIView animateWithDuration:0.50 animations:^{
[self.navigationController setNavigationBarHidden:NO animated:YES];
self.navigationController.navigationBar.alpha = 1.0f;
}];
}
}
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
scrollView = self.tableView;
_currentOffset = self.tableView.contentOffset.y;
}
You cannot customize the size of UINavigationBar on your own. You can only hide/appear it. Apple does not allow you to do that.
You can use UIView instead! Just hide your UINavigationBar and put the same frame of UIView. Since UIView is highly customizable, you can do whatever you want.
Related
I have UITextView (textView) in some other view (extView) in my Objective C project with some text in it. The text in textView is quite long so it could by maximised and minimised. Of course, I'd like to do it with some animation.
I change the height of extView with code:
- (void)setExtViewHeight:(CGFloat)newHeight withAnimation:(CGFloat)duration
{
[self setNeedsUpdateConstraints];
[UIView animateWithDuration:duration
animations:^
{
self.extViewHeight.constant = newHeight;
[self layoutIfNeeded];
[self.textView layoutIfNeeded];
}
completion:^(BOOL finished)
{
[self layoutSubviews];
}
];
}
My problem is that animation are actually works only for extView. So when I try to minimise my view the textView jumps to new height and after that extView height is changing with animation. This jump of textView is really annoying and doesn't look good.
What did I do wrong? Why height of textView doesn't follow the animation?
Update your autolayout constant outside of the animation block.
Something like this should work.
Edit: As Duncan C. suggested if you don't want to update the textView height constant as well, you will at least need your textView to have top and bottom relational constraints to your extView
- (void)setExtViewHeight:(CGFloat)newHeight withAnimation:(CGFloat)duration
{
self.extViewHeight.constant = newHeight;
[UIView animateWithDuration:duration animations:^{
[self layoutIfNeeded];
} completion:nil];
}
I have a scroll view with a label in it, and I wants after someones scroll the label X px's to the right and release his finger to delete this label with animation.
So I created a delegate connection and added the scroll view delegate method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(#"scroll view did scroll");
}
In this method I want to say something like:
if myScrollView.someProperty moved X px's to the right and the user pulled his finger
delete this label sliding with animation to the right
Can someone please help out here :/
tnx ahead!!
Check UIScrollView's contentOffset property:
contentOffset - The point at which the origin of the content view is offset
from the origin of the scroll view.
you can use UISwipeGestureRecognizer to do this and define how many pixel you want to drag the label to the right. You can try the following code
- (void)viewDidLoad {
[super viewDidLoad];
mylabel.userInteractionEnabled=YES;
[mylabel sizeToFit];
[mylabel addGestureRecognizer:[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(didSwipeLabel:)]];
}
- (void)didSwipeLabel:(UISwipeGestureRecognizer*)swipe
{
NSLog(#"swipe");
swipe.direction = UISwipeGestureRecognizerDirectionRight;
if (swipe.direction == UISwipeGestureRecognizerDirectionRight) {
[UIView animateWithDuration:0.5 animations:^{
// swipe the label 50px right
mylabel.transform = CGAffineTransformMakeTranslation(50.0, 0.0);
} completion:^(BOOL finished) {
// when animation
[UIView animateWithDuration:0.5 animations:^{
NSLog(#"label should be removed");
[mylabel removeFromSuperview];
}];
}];
}
}
I've think about how to make the tabBar 's hidden animation more elegant and smoothly:
Here is how I implement:
So I just want to improve the animation, while the tabBar is suddenly, you know, disappear and hidden.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self.tabBarController.tabBar setHidden:YES];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self.tabBarController.tabBar setHidden:NO];
}
Any suggestion?
Try adding this method:
- (void)setTabBarHidden:(BOOL)tabBarHidden animated:(BOOL)animated
{
if (tabBarHidden == _isTabBarHidden)
return;
CGFloat offset = tabBarHidden ? self.tabBarController.tabBar.frame.size.height : -self.tabBarController.tabBar.frame.size.height;
[UIView animateWithDuration:animated ? 0.6 : 0.0
delay:0
usingSpringWithDamping:0.7
initialSpringVelocity:0.5
options:UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionLayoutSubviews
animations:^{
self.tabBarController.tabBar.center = CGPointMake(self.tabBarController.tabBar.center.x,
self.tabBarController.tabBar.center.y + offset);
}
completion:nil];
_isTabBarHidden = tabBarHidden;
}
Then you can call it like [self setTabBarHidden:YES animated:YES] and [self setTabBarHidden:NO animated:YES] to hide and show your bar, this will move it in and out of the screen instead of just make it instantly dissapear.
Don't forget to add a new bool property isTabBarHidden and also you can play with the values of the animation.
I have a vertical navigation bar that lays out the items within it using AutoLayout. When I animate the navigation bar's position on and off screen, the layout of the items within the navigation bar is incorrect. Items are resized as if the bar is shrinking in width, when that is, in fact, not occurring. What am I doing wrong?
Video of issue (note that I colored the background of each button red so you can see it more easily):
"Link".
Code animating the navigation bar (in the view controller):
self.verticalNavBarLeadingSpace.constant = hidden ? -self.verticalNavBarWidth.constant : 0;
[UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseOut
animations:^{
[self.view layoutIfNeeded];
}
completion:nil];
The -updateConstraints method in my view (using FLK+AutoLayout to create constraints):
- (void) updateConstraints
{
// Wipe out existing constraints
[self removeConstraints:self.addedConstraints];
[self.addedConstraints removeAllObjects];
UIButton *lastItem;
NSString *height = [NSString stringWithFormat:#"%f", self.itemHeight];
for (UIButton *btn in _items) {
[self.addedConstraints addObjectsFromArray:[btn constrainHeight:height]];
[self.addedConstraints addObjectsFromArray:[btn alignLeading:#"0" trailing:#"0" toView:self]];
if (!lastItem) {
[self.addedConstraints addObjectsFromArray:[btn alignTopEdgeWithView:self predicate:#"0"]];
} else {
[self.addedConstraints addObjectsFromArray:[btn constrainTopSpaceToView:lastItem predicate:#"0"]];
}
lastItem = btn;
}
[super updateConstraints];
}
I have a view controller with multiple child view controllers in it (set up using Storyboards), and I move the one on top to the right (with the status bar as well) to display the underlying sidebar view controller.
This works perfectly with frames, as shown below:
- (void)displaySidebar {
self.fullScreenSnapshotOverlay = [self takeFullScreenSnapshot];
[self.postsView addSubview:self.fullScreenSnapshotOverlay];
[self hideStatusBar];
[UIView animateWithDuration:0.4 animations:^{
CGRect newFrame = self.postsView.frame;
newFrame.origin.x += 200.0;
self.postsView.frame = newFrame;
}];
}
(hideStatusBar simply called the UIApplication method and layoutIfNeeded.)
Giving me this (perfect) result:
However, if in the Storyboard I go to the container view controller and make a constraint from its leading space to the left of the view controller it's embedded in, and then adjust that constant, it really messes up the navigation bar, I assume due to hiding the status bar and taking a screenshot. I'm using this code:
- (void)displaySidebar {
self.fullScreenSnapshotOverlay = [self takeFullScreenSnapshot];
[self.postsViewController.view addSubview:self.fullScreenSnapshotOverlay];
[self hideStatusBar];
[UIView animateWithDuration:0.4 animations:^{
self.postsViewControllerDistanceFromLeftSideConstraint.constant = 270.0;
[self.view layoutIfNeeded];
}];
}
Giving me this messed up result:
Now I know the simple thing to do would be to just continue with frames, but I'd like to learn how do it properly with Auto Layout. What am I doing wrong here?
I'm not sure how what I did is any different from what you're doing. I modified the code I posted to your other question (Why does hiding my status bar completely break my simple animation?) to what's below, and it worked fine.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self performSelector:#selector(displaySidebar) withObject:nil afterDelay:1];
}
-(void)displaySidebar {
self.snapshotView = [self takeSnapshot];
[self.PostsView addSubview:self.snapshotView];
[self hideStatusBar];
self.leftCon.constant = 270;
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
}];
}
-(void)moveOutMenu { // called from a button in the menu controller
self.leftCon.constant = 0;
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
[[UIApplication sharedApplication] setStatusBarHidden:NO];
[self.snapshotView performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:0.01];
}];
}
-(UIView *)takeSnapshot {
UIView *v = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
return v;
}
-(void)hideStatusBar {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self.view layoutIfNeeded];
}
What are all the constraints you have on the container view that you're moving? Maybe there's something different there (I have top, leading, bottom and width constraints on mine -- leftCon is the outlet to the leading constraint).