I'm trying to animate an instance of UITextView to expand and collapse some text but what happens is that the text view gets resized with a new height right away and its position animates. Ideally I'd want both properties to animate for smoother animation.
[UIView animateWithDuration:kCaptionAnimationDuration * 10
animations:^{
[self->_caption setFrame:self->_truncatedCaptionFrame];
}
completion:^(BOOL finished){
self->_displayingFullCaption = NO;
}];
How can I get the height to slowly animate instead?
So I have a UIViewController and I have a UIScrollView inside of it, which has some UI elements.
I want the user to be able to drag the UIScrollView up and down, but when it drags past a certain threshold, I want it to animate off the screen. There needs to be some springiness to it though. I tried using -(void)scrollViewDidScroll: but couldn't seem to get it right. Any thoughts?
In scroll view delegate method -(void)scrollViewDidScroll:(UIScrollView *)scrollView; observe scrollView.contentOffset.y and trigger animation when it reaches expected y position.
for example:
CGFloat yTranslation = -200.f; // Value you want to shift
[UIView animateWithDuration:0.35 animations:^{
scrollView.transform = CGAffineTransformMakeTranslation(0, yTranslation);
} completion:^(BOOL finished) {
// code after completion
}];
Basically I have a uiscrollview. The uiscrollview scrolls down when i push a certain button. However once the content offset has been set it will not allow me to scroll the uiscrollview back to the to.
For example...
If I set the content off set to 100 and animated:yes. The scrollview will scroll to that position and allow me to continue to scroll down the page but when trying to scroll up you pull up and see the upper par of the view but it then bounces back down.
Here is my code:
Firstly when the button is pressed I call the void function:
[self downExecute:scroller];
Secondly I run the void statement which set's my content off set...
- (void)downExecute:(id)sender {
NSLog(#"scroll down");
CGFloat currentOffset = scroller.contentOffset.y;
CGFloat newOffset;
newOffset = currentOffset + 100;
[UIScrollView animateWithDuration:0.3 animations:^(void) {
[scroller setContentOffset:CGPointMake(0.0,newOffset)];
}completion:^(BOOL finished) {
}];
}
Any Help would be greatly appreciated...
If your intent is to allow normal scrolling after you've repositioned the content, you could use scrollRectToVisible:animated: instead of changing the content offset.
try something like this to allow scrolling:
scroller.alwaysBounceVertical = YES;
and to manage duration of scrolling use this:
scroller.viewForBaselineLayout.layer.speed = 1.0f; // 1.0f is default
[scroller setContentOffset:(some CGPoint) animated:YES];
I am looking to animate the size of my UIView Container at the same time my ad appears at the bottom. I have the ad slide up from the bottom of the screen when it's ready. I want my UIView container to decrease that same amount of size as the ad slides up.
I created an outlet property for my container view within the top level UIViewController that it is embedded in.
My ad animation code:
- (void)adViewDidReceiveAd:(GADBannerView *)view
{
NSLog(#"Received Ad");
[UIView animateWithDuration:1.0 animations:^ {
view.frame = CGRectMake(0.0,
self.view.frame.size.height - view.frame.size.height,
view.frame.size.width,
view.frame.size.height);
// This is where I think I would need to animate the container view.
}];
}
How can I decrease the size of my container view to match that of the ad? I need the container to stay in the same spot and everything, but some height needs to be taken off of the bottom.
That's simple: just animate your container frame in the same block as you are animating your banner view up. It will be something like this:
[UIView animateWithDuration:1.0 animations:^ {
view.frame = CGRectMake(0.0,
self.view.frame.size.height - view.frame.size.height,
view.frame.size.width,
view.frame.size.height);
self.containerView.frame = CGRectMake( self.containerView.frame.origin.x,
self.containerView.frame.origin.y,
self.containerView.frame.size.width,
self.containerView.frame.size.height - view.frame.size.height);
}];
This piece of code will decrease your containerView as the same height of your banner and at the same time. You can change/adapt as you want.
Edit: if you are using autolayout, you should create a IBOutlet for the constraint and animate it, and not the frame itself.
I have been struggling for a long time with a problem with a UIScrollView.
I have a UIScrollVIew that contains a UITextView as a subview. When I select the text view a keyboard pops up. I want to resize the text view to fit exactly in the available space, and also scroll the scroll view so that the text view is positioned exactly in the visible space (not hidden by the keyboard).
When the keyboard appears I call a method that calculates the appropriate size for the text view and then performs the following code:
[UIView animateWithDuration:0.3
animations:^
{
self.textView.frame = frame;
}
];
[self.scrollView setContentOffset:CGPointMake(0,frame.origin.y) animated:YES];
(here frame is the appropriate frame for the text view).
Unfortunately the scroll view does not always scroll to the correct position, especially when it is already at a non zero vertical content offset when I select the text view. I know that the content offset that I'm setting it to is correct.
After a lot of testing I finally realized that what was happening was that after the animation completed, the scroll view was automatically scrolling again.
This code does work:
UIView animateWithDuration:0.3
animations:^
{
self.textView.frame = frame;
}
completion:^(BOOL finished) {
[self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
}
];
but it looks strange because the scroll view scrolls to the wrong position, then to the right one.
Does anyone know how I can prevent the scroll view from changing it's content offset when the text view frame finishes its animation?
I am testing using iOS 5.0.
Here is a solution that I found that works. I'm still don't completely understand what's happening, possible it has something to do with the way my springs and struts are set. Basically I am shrinking the scroll view content size by the same amount that the text view shrinks.
- (void)keyboardDidShow:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
// Get the height of the keyboard
CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
kbRect = [self.view convertRect:kbRect fromView:nil];
CGSize kbSize = kbRect.size;
// Adjust the height of the text view to fit in the visible view
CGRect frame = self.textView.frame;
int visibleHeight = self.view.frame.size.height;
visibleHeight -= kbSize.height;
frame.size.height = visibleHeight;
// Get the new scroll view content size
CGSize contentSize = self.scrollView.contentSize;
contentSize.height = contentSize.height - self.textView.frame.size.height + frame.size.height;
[UIView animateWithDuration:0.1
animations:^
{
self.textView.frame = frame;
// Note that the scroll view content size needs to be reset, or the scroll view
// may automatically scroll to a new position after the animation is complete.
self.scrollView.contentSize = contentSize;
[self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
}
];
// Turn off scrolling in scroll view
self.scrollView.scrollEnabled = NO;
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
// Update the view layout
[UIView animateWithDuration:0.3 animations:^
{
self.scrollView.contentOffset = CGPointZero;
[self updateViewLayout];
}
];
// Turn on scrolling in the scroll view
self.scrollView.scrollEnabled = YES;
}
([self updateViewLayout] is a method that returns the text view to the correct height, and resets the scroll view content size, as well as making sure all the other subviews are properly positioned).
Do not adjust the frame of the text view. All you need to do is scroll the scrollview. If you scroll the scrollview animated, then the textView will slide up animated. Just do the following:
[self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
If you need the scroll view to scroll at a specific rate then manually adjust the content offset in an animation block.(I haven't tested this, you may want to adjust the animation flag, or step through the content offset one pixel at a time if this doesn't work)
[UIView animateWithDuration:0.3f
animations:^{
[self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
} ];
I believe I also had something similar. I wanted my horizontal UIScrollView to go back to it's original offset (0,0), and every time I animated back to it, it would be just a couple pixels off, but as soon as someone touched the scrollview, it would continue and finish the animation (almost like lag in a video game).
Due to that, I tried putting it in GCD as the main queue and it worked perfectly fine after that. Here's the code:
- (void)setPageZero{
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:1.0f
delay:0 options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[self.scrollView setContentOffset:CGPointMake(0, self.scrollView.frame.origin.y) animated:YES];
}
completion:^(BOOL finished) {}];
});
}
What that basically does, is that it puts the animation into the main queue (kind of like a superhighway in the CPU/GPU) and it prioritizes it over other things!
Hope this helps future readers!
I'm having a similar problem. Basically I have a scroll view with three pages each containing a custom UIView class. The custom UIView class contains an image and a number of overlay views containing information about the image. The overlay views contain a number of UITextView fields.
I attach the custom views to the scroll view and then I load the image & overlays using block operations. I swipe to the right by deleting the first view, repositioning the next two views, and adding an new view to the right.
If I create the UITextField objects and disable scrolling as follows:
UITextView* view = [[UITextView alloc]
initWithFrame:CGRectMake(position.x,position.y,width,height)];
view.editable = NO;
view.scrollEnabled = NO;
Then the scroll view gets repositioned between pages when I return from the block code. Note that I don't reposition the scroll view and on exit from the block, the scroll view is in the correct position.
However, if I comment out the code to disable scrolling
UITextView* view = [[UITextView alloc]
initWithFrame:CGRectMake(position.x,position.y,width,height)];
view.editable = NO;
// view.scrollEnabled = NO;
this repositioning does not occur and the scrolling works as expected.
Complete hack: May improve the reset issue:
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[self setContentOffset:self.contentOffset animated:NO];
}