iOS animation: Drop down that keeps it position - animation

I´m trying to create a drop down menu that will display a set of controls. I got the animation working but the whole "button" moves with the animation.
My button is a UIView which is named settingsPanel, this is my code so far:
[UIView animateWithDuration:1.0f animations:^{
self.settingsPanel.bounds = CGRectMake(self.settingsPanel.bounds.origin.x, self.settingsPanel.bounds.origin.y, self.settingsPanel.bounds.size.width, self.settingsPanel.bounds.size.height + 300);
}];
I just want the height of the panel to change, and it does, but the whole view moves up a bit as well.
How can I create a animation that justs increases the height downwards?

You need to set the frame, not the bounds.
[UIView animateWithDuration:1.0f animations:^{
self.settingsPanel.frame =
CGRectMake(self.settingsPanel.frame.origin.x,
self.settingsPanel.frame.origin.y,
self.settingsPanel.frame.size.width,
self.settingsPanel.frame.size.height + 300);
}];
Frame is an external coordinate. When you change the frame, you change the actual position of the view within its superview, so you can keep the origin and width the same and just increase the height.
Bounds is an internal coordinate. When you change the bounds, the system has to decide what to do about the frame; its solution is that the change happens around a stationary center position. So the top moves upward as the height grows downward.

Related

Xcode - viewDidLayoutSubviews

i have a view inside a viewController, i wanted to start the smaller view outside the viewController in the left, and animate it to the centre when i press a button. so i made it like this:
override func viewDidLayoutSubviews() {
smallView.center = CGPointMake(smallView.center.x - 400, smallView.center.y)
}
And it works perfectly!, the problem is i have a text view inside that smaller view, and every time i start editing it it jumps outside of the main viewController right where it was, and i have to press the button again to bring it inside.
How to fix this?
PS: i tried positioning it to the centre when i start editing the text view like this:
func textViewDidBeginEditing(textView: UITextView) {
smallView.center = CGPointMake(smallView.center.x + 400, smallView.center.y)
}
But it doesn't work. and the method is connected to the textView properly(delegate)
PS2: i also have imagePickerController inside my viewController.
OK, as you're using Auto Layout.
The first rule of Auto Layout (you will see this in any Auto Layout book) is that you absolutely cannot touch the frame or center of a view directly.
// don't do these
myView.frame = CGRectMake(0, 0, 100, 100);
// ever
myView.center = CGPointMake(50, 50);
You can get the frame and center but you can never set the frame or center.
In order to move stuff around using Auto Layout you need to update the constraints.
For instance if I set up a view called myView and want it to grow and shrink in height I would do something like...
Set the top constraint to the superview at 0.
Set the left constraint to the superview at 0.
Set the right constraint to the superview at 0.
Set the height constraint to 50 (for example) and save it in a property called heightConstraint.
Now to animate the change in height I do this...
self.heightConstraint.constant = 100;
[UIView animateWithDuration:1.0
animations:^ {
[self.view layoutIfNeeded];
}];
This will then animate the height from 50 (where it was when I set it) to 100.
This is the same for ANY animation of views using Auto Layout. If (for instance) I had saved the left constraint I could change that and it would increase and decrease the gap from the left edge of the superview to myView.
There are several really good tutorials about AutoLayout on the Ray Wenderlich site. I'd suggest you take a look at them.
Whatever you do, I'd strongly suggest not just disabling Auto Layout. If you don't know how to use Auto Layout then you will very quickly fall behind with iOS 8 and the new device sizes.

Trying to mix UIKit Dynamics UICollision and core animation to scale a box's bounds

From a previous question I had.
CGAffineTransformScale does not send it's scale when using UIDynamicAnimator
Im trying to mix an animated scale effect on a box that has a smaller box on top of it.
Both boxes have UICollisionBehavior, I want to eventually make the bottom box thats getting larger scale fast enough to provide a velocity force I that will make the top box react with a bounce up.
The below is the scale code. The bounds is instantly set to its target final while the image in the view is still scaling. I want the bounds and image to be scaling at the same time so I can see the expected reactions happening.
- (IBAction)tapBoxThing:(UITapGestureRecognizer *)sender {
/* Make sure no translation is applied to this image view */
_boxView.transform = CGAffineTransformIdentity;
/* Begin the animation */
[UIView beginAnimations:nil
context:NULL];
/* Make the animation 5 seconds long */
[UIView setAnimationDuration:5.0f];
[_gravity removeItem:_boxView];
[_collision removeItem:_boxView];
// right here, the box will animate the image in the view to slowly fill in the new bounds.
// But I want the bounds to animate, its currently instantly scaling to teh final ammount.
// Core Animation states that frame is not animatable but bounds is.
CGRect frameZ = _boxView.bounds;
frameZ.size.height += 60.0f;
frameZ.size.width += 60.0f;
_boxView.bounds = frameZ;
[_gravity addItem:_boxView];
[_collision addItem:_boxView];
[UIView commitAnimations];
}

ObjectAnimator in Android doesn't update the View's parent

Objective:
Build a SlideUp animation in a ImageView with fixed height that is placed in a LinearLayout with wrap_content height.
Problem:
The animation runs normally, but the parent LinearLayout doesn't resize itself while or after the animation occurs. I mean, if it is set to "wrap_content" and the "content" changes it's position (y axis to -100), it's expected that the parent accompanies the animation, "animating" it's height to 0 as well, or not?
How can I force it to continue "wraping" the content while the animation runs?
PS: No, it's not about fillAfter, I'm using ObjectAnimator, which changes the real object properties, not only the View drawn. For instance, the click event is not being triggered on the place the image used to be before the animation.
My code:
ObjectAnimator oa = ObjectAnimator.ofFloat(findViewById(R.id.menu_tile_image), "y", 0, -100);
Layout structure:
LinearLayout (match_parent, wrap_content) > ImageView (fill_parent, 100)
Any clue on that? Thanks!

cocoa: how to implement a table animation?

I'm curious how to implement the following app animation:
after I click Alcides, the app will gradually show a new view on the right and the left table width will be 1/2 of the original.
if I want to implement it, how can I do?what data structure and animation should I use?
The answer with most custom animations is to think about what you want to do and do it. Trite but true.
Cut the width of the tableview in half at animation speed X
Move the RH detail table in from right at animation speed X
You will need to have your ViewController for the scene as a container for the pair of tables. But the tableviews may have their own view controllers which the container manger should keep a strong reference to.
ManagerViewController -> UIView -> PeopleTableView -> PeopleTableViewController
-> DetailTableView -> DetailTableViewController
So in code...
detailTableView.frame = Frame_with_x_aligned_to_RH_edge_of_screen;
[UIView animateWithDuration:X
animations:^{
peopleTableView.frame = Frame_with_half_its_fully_expanded_width;
detailTableView.frame = Frame_with_x_aligned_to_edge_of_peopleTable;
}
completion:^{ //stuff to do at the end of the animation
}];

Time Machine style Navigation

I've been doing some programming for iPhone lately and now I'm venturing into the iPad domain. The concept I want to realise relies on a navigation that is similar to time machine in osx. In short I have a number of views that can be panned and zoomed, as any normal view. However, the views are stacked upon each other using a third dimension (in this case depth). the user will the navigate to any view by, in this case, picking a letter, whereupon the app will fly through the views until it reaches the view of the selected letter.
My question is: can somebody give the complete final code for how to do this? Just kidding. :) What I need is a push in the right direction, since I'm unsure how to even start doing this, and whether it is at all possible using the frameworks available. Any tips are appreciated
Thanks!
Core Animation—or more specifically, the UIView animation model that's built on Core Animation—is your friend. You can make a Time Machine-like interface with your views by positioning them in a vertical line within their parent view (using their center properties), having the ones farther up that line be scaled slightly smaller than the ones below (“in front of”) them (using their transform properties, with the CGAffineTransformMakeScale function), and setting their layers’ z-index (get the layer using the view’s layer property, then set its zPosition) so that the ones farther up the line appear behind the others. Here's some sample code.
// animate an array of views into a stack at an offset position (0 has the first view in the stack at the front; higher values move "into" the stack)
// took the shortcut here of not setting the views' layers' z-indices; this will work if the backmost views are added first, but otherwise you'll need to set the zPosition values before doing this
int offset = 0;
[UIView animateWithDuration:0.3 animations:^{
CGFloat maxScale = 0.8; // frontmost visible view will be at 80% scale
CGFloat minScale = 0.2; // farthest-back view will be at 40% scale
CGFloat centerX = 160; // horizontal center
CGFloat frontCenterY = 280; // vertical center of frontmost visible view
CGFloat backCenterY = 80; // vertical center of farthest-back view
for(int i = 0; i < [viewStack count]; i++)
{
float distance = (float)(i - offset) / [viewStack count];
UIView *v = [viewStack objectAtIndex:i];
v.transform = CGAffineTransformMakeScale(maxScale + (minScale - maxScale) * distance, maxScale + (minScale - maxScale) * distance);
v.alpha = (i - offset > 0) ? (1 - distance) : 0; // views that have disappeared behind the screen get no opacity; views still visible fade as their distance increases
v.center = CGPointMake(centerX, frontCenterY + (backCenterY - frontCenterY) * distance);
}
}];
And here's what it looks like, with a couple of randomly-colored views:
do you mean something like this on the right?
If yes, it should be possible. You would have to arrange the Views like on the image and animate them going forwards and backwards. As far as I know aren't there any frameworks for this.
It's called Cover Flow and is also used in iTunes to view the artwork/albums. Apple appear to have bought the technology from a third party and also to have patented it. However if you google for ios cover flow you will get plenty of hits and code to point you in the right direction.
I have not looked but would think that it was maybe in the iOS library but i do not know for sure.

Resources