I have a button and on click event of it i want to insert a UIView. I know how to insert a UIView however i am not able to push/move other UIView's that are below it so that i can accommodate the added UIView.
I have already looked at this link but it does not serve my purpose
Any suggestions?
In the method of the button create the new view and add it as a subview. Set the frame.origin.x to 0 minus the width of the view (if you want it to push from the left) so it is not visible and change that value to where you want it to be inside [UIView animateWithDuration:animations:].
[UIView animateWithDuration:1.0 animations:^(void){
[newView setFrame:({
CGRect frame = newView.frame;
frame.origin.x = 150; // If you want it to start at x = 150
frame;
})];
// If you want to move other views too, just add them in this block
}];
If you don't get what I'm doing to set the frame, check out the first tip in this post.
Related
I have an imageview I put onto the view controller of a circle.
I would like to start that circle from off screen and move it to the location I've put it.
What would be the best way to animate it?
Try this;
-(void)viewWillAppear {
[UIView animateWithDuration:5
delay:5
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CGRect frame = view.frame;
frame.origin.y = self.view.frame.size.height-200;
frame.origin.x = 0;
view.frame = frame;
}completion:^(BOOL finished) {}];
}
You many animation option's [UIViewAnimationOptions]
UIViewAnimationOptionCurveEaseInOut,
UIViewAnimationOptionCurveLinear,
UIViewAnimationOptionTransitionFlipFromLeft,
UIViewAnimationOptionTransitionCurlUp,
UIViewAnimationOptionTransitionCrossDissolve,
UIViewAnimationOptionTransitionFlipFromTop..
You want to create your image view off-screen. Its easiest if you set it up in Interface Builder that way. you can create it on-screen, add a constraint to place it at the target location, note the value, and then change the constraint's constant so the view is moved off-screen.
Then control-drag the constraint into your view controller and create an outlet to it.
To animate the image view on-screen, change the constraint's constant value to the "on-screen" value you noted above, and then call layoutIfNeeded() on the view from inside an a UIView animateWithDuration block.
If you want to add the image view in code then you need to add it off-screen, add it as a subview, and then trigger a UIView animation to move it back on-screen. You should probably also do the positioning with constraints as outlined above, although it gets more complicated because you have to create those constraints in code.
I'm using Objective-C. And I want to make the table view move down with animation when I add a search bar above it. This is my code(table here is my table view):
[UIView animateWithDuration:0.3 animations:^{
CGRect frame = self.table.frame;
frame.origin.y = frame.origin.y+30;
self.table.frame = frame;
}];
But it doesn't work. Someone can help me?
Add layoutIfNeeded at the end of animation block. Like that:
[UIView animateWithDuration:0.3 animations:^{
CGRect frame = self.table.frame;
frame.origin.y = frame.origin.y+30;
self.table.frame = frame;
[self.view layoutIfNeeded];
}];
Changing frames like this is not the best way to do it, and its old fashioned. The best way is to get access to one of the autolayout constraints on the view, and change it. For eg - say your tableview has a top constraint that defines the gap between the top of the tableview and the superview - eg 10px. Drag that constraint from IB, into your class. Best way to do this is to highlight the constraint on the left hand side of IB, in the list that contains all your views etc. Drag across to make it a property in your class, just like you do with a button or label. Then at runtime, you change the .constant property of that constraint. For eg. Heres my NSLayoutConstraint property when dragged across into the class :
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *topBuffer;
Then at the point in code where you want the move to happen, you change the constant property, OUTSIDE of the animation call :
self.topBuffer.constant = 50; //<-- or whatever the new value is
Then all you do is call [self.view layoutIfNeeded] in the animation block. By the way - note here Ive used the anim block with springs etc for a bouncey effect too. Also note - layoutIfNeeded is called on the superview of the object you are changing - so self.view here is my main superview that contains the tableview.
[UIView animateWithDuration:0.7f delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseIn animations:^(void) {[self.view layoutIfNeeded];} completion:nil];
I have a container view which is equally divided between two UIViews like this:
The portion in black is my UIView 1, which I am currently not using. My UIView 2 contains a UISegmented Bar and a UITableView.
The hierarchy of my views look something like this:
Now, my requirement is I want to resize my view2 to cover entire container view dynamically and view1 to go away based on some condition. Currently I am not worried about that condition, I just tried to resize my view2 using the following code inside - (void)viewDidLoad
CGRect newFrame = self.view2.frame;
newFrame.size.width = 200;
newFrame.size.height = 200;
newFrame.origin.x=0;
newFrame.origin.y=0;
[self.view2 setFrame:newFrame];
Here view2 is the outlet to my view2 in interface builder.
But, nothing is changing from the above code. I tried to find any other way but had no help. So please help me find out my mistake in my current technique or tell me how some other technique to do it.
Thanks in advance!
The code to change frame seems fine, just remove the view from superview, set the frame and add to superview again programmatically.
[self.view2 removeFromSuperview];
// set the frame
CGRect newFrame = self.view2.frame;
newFrame.size.width = 200;
newFrame.size.height = 200;
newFrame.origin.x=0;
newFrame.origin.y=0;
[self.view2 setFrame:newFrame];
//add self.view2 again wherever it was
[myView addSubView:self.view2];
When I add some animations on the subview of the scrollview that like extending or contract a textfield,it just not work. But it worked well when the subview add to a simple UIView.
How did it happen?
There should be no problem animating the frame of a UITextField within a UIScrollView.
The most common source of "my animation isn't animating" in iOS 6 and later is the attempt to animate a control by adjusting the frame when employing autolayout (because the adjustment of the frame can be thwarted by the constraints being reapplied by the most innocuous of actions). You can tell if you're using autolayout or not by selecting the File Inspector (the first tab) of the rightmost panel in Interface Builder, and seeing if "Use Autolayout" is checked:
For example, to animate the frame when not using autolayout, assuming your UITextField has an IBOutlet called textField, you might do something like:
[UIView animateWithDuration:0.5 animations:^{
CGRect frame = self.textField.frame;
frame.size.width = 280;
self.textField.frame = frame;
}];
But the equivalent when using autolayout is not achieved by adjusting the frame, but rather by changing the constraints' constant values. For example, assuming you created an IBOutlet for the width constraint called textFieldWidthConstraint on your UITextField, you would animate the changing of the width with something like:
self.textFieldWidthConstraint.constant = 280;
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutIfNeeded];
}];
If you believe you are using the appropriate animation technique that corresponds to your choice of autolayout or non-autolayout, but it's still not working, you should show us some code and describe the situation in greater detail.
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];
}