I have used UIDynamics before, but I never used it along with the methods provided by the Core Animation framework.
I basically would like to achieve something very simple:
I would like my UI Object to travel along a path and have another UI Object attached to it.
I create the attachment behavior like so:
attachment = [[UIAttachmentBehavior alloc] initWithItem:view2 attachedToItem:view1];
So, as view1 being animated, view2 will follow.
All this is working if I trigger it using a UIPushBehavior.
My question is, is it possible to mix UIDynamics using:
CABasicAnimation, CAKeyFrameAnimation and [UIView ....] animation block?
I tried to animate view1 using an animation block.
Result: while view1 is being animated, view2 is not being attached.
If I set off the above using a push behavior, it animates and view2 is attached to view1 without problem.
Again, is it possible applying UIDynamics behaviors to UI Objects while using CABasicAnimation, CAKeyFrameAnimation and [UIView ....] animation block for animation?
Addendum:
Thought I would add the animation block I use (didn't add it because I thought it was too juvenile and simple to mention), but for completeness' sake:
[UIView animateWithDuration:5.0f animations:^
{
view1.center = (CGPoint){320.0, 480.0};
}];
For alloc and init'ing UIDynamics properties it is done in viewDidLoad:
animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
attachment = [[UIAttachmentBehavior alloc] initWithItem:view2 attachedToItem:view1];
[animator addBehavior:attachment];
Related
I need to update a view continuously depending on another view's position while it's moving across the screen. I tried using KVO on frame, but it seems to trigger only at the beginning of the animation. Is there a recommended way of doing this?
You want to have a look at the Core Animation presentation layer which should tell you the position during the animation.
I would add a repeatable timer and make something like:
[self updateView:_view
usingPosition:[_anotherView.presentationLayer position]];
(Don't you know _anotherView's animation in advance? Maybe then you can setup _view animation directly?)
Why not just set both animations for both view at the same time?
[UIImageView animateWithDuration:aDuration
delay:0
options:UIViewAnimationCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState
animations:^(void) {
view1.center = somePosition;
view2.center = someOtherPosition;
} completion:NULL];
They will move at the same time and with the option : UIViewAnimationOptionBeginFromCurrentState if you start an other animation before this one is finished the views will start at the point they were stopped.
But if it's not what you are looking for, can you update your question with precision on how view1 is moving.
I've been checking this site for many of my questions before but this is the first time I actually have to ask someting, so I hope I can make myself clear enough.
I have an App which is nearly finish. The main functionallity is in up and running. I'm only concern in making the whole App visually appealing. The App is maninly a database wich scientifical relevant data. I want the user to be able to store custom data in the DB and to do that I've created a "contact-like" view where the user can save some data. The view contains a table and inside this table, the cell have UITextFields. After entering the data, when the user presses a button, I want to animate the content of the textField to a cabinet-like icon. Very much like when you purchase something in the iTunes on a iOS device.
I've been able to do that animation in a "static" view (not a UITableView), playing around with starting point, end point and so on is a bit of a pain in the neck, but doable after all.
I'm doing the animation in a not really conventional way, I think, but actually very effecive. On the press of the button I create a UILabel, I set the text as the text of the textField and then I use viewAnimationWithDuration block to animate the label. Inside the block I also use Core Animation to animate the layer of the label over a path. Again, not conventional, but straight forward.
The problem I'm having is that I'm not able to create the label over the textField since it is in a UITableView. Mainly the problem is to know the position (or frame, or bounds, or position. I'm really confused already) of the textField and hence, the starting position of the path.
The code I'm using is as follows:
-(IBAction)saveCustom:(id)sender{
UILabel *imageViewForAnimation = [[UILabel alloc] initWithFrame:CGRectMake(l1, l2, l3, l4)];
imageViewForAnimation.text=label.text;
imageViewForAnimation.alpha = 1.0f;
imageViewForAnimation.backgroundColor=[UIColor clearColor];
imageViewForAnimation.textColor=[UIColor blackColor];
imageViewForAnimation.adjustsFontSizeToFitWidth=YES;
[self.view addSubview:imageViewForAnimation];
[UIView animateWithDuration:10.0
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
// Set up path movement Core Animation begins
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
CGPoint endPoint = CGPointMake(310, 380); // final point
CGMutablePathRef curvedPath = CGPathCreateMutable();
CGPoint rootViewPoint = [imageViewForAnimation convertPoint:imageViewForAnimation.center toView:taula];
CGPathMoveToPoint(curvedPath, NULL, rootViewPoint.x, rootViewPoint.y); // initial point
CGPathAddCurveToPoint(curvedPath, NULL, 100, 100, 100, 100, endPoint.x, endPoint.y);
pathAnimation.path = curvedPath;
CGPathRelease(curvedPath);
pathAnimation.fillMode=kCAFillModeForwards;
pathAnimation.removedOnCompletion=NO;
pathAnimation.duration=10.0f;
pathAnimation.delegate=self;
[imageViewForAnimation.layer addAnimation:pathAnimation forKey:#"savingAnimation"];
[imageViewForAnimation release];
//Core Animation ends
imageViewForAnimation.transform=CGAffineTransformMakeScale(0.60, 0.60);
// imageViewForAnimation.alpha=0.2;
}
completion:^(BOOL finished){
[imageViewForAnimation removeFromSuperview];
} ];
}
Any help on how to proceed will be much appreciated.
Thanks in advance!
UPDATE:
I went to the Apple Tech Talks in Berlin. In the labs they got, I asked an engineer about that. He wondered that the code I showed him didn't work. I emailed to him and he'll be back to me.
The key thing is to transform the coordinates from the table, to the view.
A UITableView shows a number of UITableViewCells. If you want to customize the controls displayed in a cell, you can add additional controls to the contentView of a UITableViewCell. Depending on how complicated your needs are, you would do this in the UITableViewDelegate or by subclassing UITableViewCell. Just be aware that adding subviews to contentView will likely interfere with the built-on controls (e.g. textLabel or detailTextLabel).
To position your additional controls or animation effects, you can check the bounds of the cell's contentView. Add your controls as subviews of contentView, animate them, and don't forget to remove them when you no longer need them.
Seems pretty conventional animation to me. And yes, effective.
As to a solution, you just need to save some state info when the user requests a save. And draw your animation label on top of the table. Should be no major problems there as long as you have a view available, super view of the table maybe?
Beyond that, how is your UI setup with respect to this table? How is the save custom activated (does the save all data or a specific field, do you have selected cell which you can access to pull the needed origin of your animation data)?
Also, don't forgot to release your UILabel after you add it as a subview, you are leaking it in the code above.
What is the built in method which can be used to hide and show toolsbars. specifying a rate or speed of the animation?
Look at this question, and do something like:
[UIView animateWithDuration:2.0
animations:^{
[self.navigationController setToolbarHidden:YES animated:YES];
}
completion:^(BOOL finished){
// whatever
}];
Toolbar's just a view—add an IBOutlet in your controller, then use UIView's (class methods) block animation methods, such as animateWithDuration:delay:options:animations:completion: or animateWithDuration:animations:. In the animation block, just move the view.frame.size.origin.y to a different location, or set its opacity to zero. the methods also allow you to specify the time period over which the animation will occur. Once complete (there's a delegate callback in the first method), you can then ask your main view to get taller by using the same methods to change the view.frame.size.origin.y of your main view.
I have a UIView that I want to animate to the position where the user's finger currently is.
So, when the touch begins, it has to animate to the tap location.
When the touch moves, it has to adjust its destination to the new location.
When the touch ends, it has to finish the animation to the last tap location.
I tried several things but none worked out. I tried creating a new animation with beginsFromCurrentState in touchesMoved, but that didn't work too.
It seems you're complicating this a little bit. If you are implementing touchesMoved, you are wanting a drag. If you are more interested in a tap, then touchesEnded is where you want to implement this. Either way, you just need to get the location in view and update your UIView's center based upon that location. If you wrap the change to the center value in a UIView animation block, it will animate to the position as it updates.
If you are using iOS 3.2 or later, you can use gesture recognizers which makes this pretty trivial:
// In viewDidLoad or some such
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(viewWasTapped:)];
[[self view] addGestureRecognizer:tapRecognizer];
Then declare your action selector:
- (void)viewWasTapped:(UITapGestureRecognizer*)recognizer
{
CGPoint location = [recognizer locationInView:[self view]];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0f]; // take a second to animate
[viewToMove setCenter:location];
[UIView commitAnimations];
}
This will animate the view from one location to another. This is referred to as implicit animation. Using Core Animation classes such CAKeyframeAnimation or CABasciAnimation would be explicit animation.
Need a few more details for this.. But are you sure you are using touchesBegan, touchesMoved and touchesEnded from the appropriate view (ie not the view you want to move)? Also make sure the userInteractionEnabled = YES. Try logging the touches from touchesBegan to make sure you are receiving the touches.
Or you might want to just check out Apples MoveMe sample code at https://developer.apple.com/library/ios/#samplecode/MoveMe/Introduction/Intro.html where they have solved all those problems for you.
So I am just beginning recently developing some simple apps for the iphone. I will say that I am fairly sure I don't have a strong understanding of programming for multiple views yet, but I am trying to learn as I go.
I have a program that started as a plain window based application so i could hand write everything in hopes of learning more about what i am doing. I have a single view controller that acts to load and release views as requested from each of the other view controllers. No elements persist from one view to the other.
I have that working fine currently, but I wanted to add animations to the view changing. A simple push animation was my goal. One view pushes out as the new view pushes in.
Looking into CATransitions and trying that, I have a working version (currently for pushing top/bottom)
[thisView.view removeFromSuperview];
[thisView release];
thisView = [[MenuViewController alloc] initWithNibName:#"MenuView" bundle:nil];
[self.view addSubview:thisView.view];
CATransition *animation = [CATransition animation];
[animation setDuration:6.3];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromTop];
[animation setRemovedOnCompletion:YES];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
[[self.view layer] addAnimation:animation forKey:nil];
as far as I can tell this is pretty standard code for using CATransition and it works to do what I need, one view gets pushed up as the other view comes in. However my problem is that there seems to be a fade that happens to each view as they come in or go out respectively.
As such - in this example; as the menu pushes up from the bottom, it will very slowly fade in from white, and as the previous view leaves the screen it will slowly fade to white.
Note that the duration is set to 6 so that the fading is dramatic.
Is there a way to remove the fading here so that each view remains solid on the way in and the way out? Or have I missed the mark completely in this route that I am taking?
I appreciate any help. Apologies I have been long winded.
I have never been able to find a solution to this problem, but I can offer a reasonable workaround. What's happening is it isn't fading to white, but fading to transparent, and the window background (or whatever view is behind) is white. There are a couple ways to get around this:
Change the window background color. If both views you're fading between have the same solid background color, then this will look pretty good.
Don't render a background in each view ("MenuView," for example), but rather have a shared background view that's under those views at all times.
Note that this will not work in all circumstances -- grouped UITableViews, for example, are always completely opaque.
(As I side note, I assume that you aren't build a navigation-based application, in which case all the animation should be handled automatically.)
You also might want to consider the looking into the UIView method setAnimationTransition:forView:cache: if you haven't already as another way to transition between views (although it cannot do a sliding animation, if you are set on that).
I solved this by enclosing the view to which I have applied the effect into a superview and by setting the superview property "clip subviews". now the fade is "clipped" by the superview.
I was able to get the views to transition without fading at the beginning and end by using UIView animation. NOTE: In the code below, I have a UINavigationController and a UITabBarController inside a main UIView. The main UIVIew (containerView) is what I added as a subView to the Application window. The other two are subviews of the containerView.
UITabBarController *tabBarController = [(AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate] tabBarController];
UIView *containerView = [(AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate] containerView];
UINavigationController *accountsNavigationController = [(AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate] accountsNavigationController];
CGRect accountsNavigationControllerEndFrame = containerView.frame;
CGRect tabBarControllerEndFrame = CGRectMake(containerView.frame.size.width, containerView.frame.origin.y, containerView.frame.size.width, containerView.frame.size.height);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
tabBarController.view.frame = tabBarControllerEndFrame;
accountsNavigationController.view.frame = accountsNavigationControllerEndFrame;
[UIView commitAnimations];