i am animating an UIImageView with an image of a circle that grows and fades which repeats:
-(void)animateOuterCircle
{
NSLog(#"animating circles");
[UIView animateWithDuration:1.5
delay:.5
options:(UIViewAnimationOptionAllowUserInteraction)
animations:^{
self.outerCircle.transform=CGAffineTransformMakeScale(.25, .25);
}
completion:nil];
[UIView animateWithDuration:1.5
delay:.5
options:(UIViewAnimationOptionRepeat | UIViewAnimationOptionAllowUserInteraction)
animations:^{
self.outerCircle.transform=CGAffineTransformMakeScale(1.5, 1.5);
self.outerCircle.alpha = 0;
}
completion:nil];
[self.view bringSubviewToFront:self.outerCircle];
}
i call this method in viewDidAppear:
- (void)viewDidAppear:(BOOL)animated
{
[self performSelectorOnMainThread:#selector(animateOuterCircle) withObject:nil waitUntilDone:NO];
//other code
}
It will animate fine when i load mainView. the issue is i load view2 and dismiss view2, when i come back to mainView, it is not animating anymore.
any ideas why this is happening?
EDIT: the methods are being called:
2012-03-15 14:11:13.946[1529:17903] view2 canceled //dismissing view2
2012-03-15 14:11:13.947[1529:17903] mapView viewWillAppear fired
2012-03-15 14:11:13.948[1529:17903] mapView viewWillAppear end
2012-03-15 14:11:14.352[1529:17903] mapView viewDidAppear fired
2012-03-15 14:11:14.353[1529:17903] animating circles
2012-03-15 14:11:14.354[1529:17903] mapView viewDidAppear end
EDIT 2:
-(IBAction) fourthBtn:(id)sender
{
view2 *view2 = [self.storyboard instantiateViewControllerWithIdentifier:#"view2"];
[self presentModalViewController:view2 animated:YES];
}
dismissing view 2:
-(IBAction) cancel:(id) sender
{
NSLog(#"heir canceled");
[self dismissModalViewControllerAnimated:YES];
}
also, i don't stop the animation myself at any point in my code.
My guess is that viewDidAppear is not being called, because from the perspective of that view, it never disappears.
Depending on how you are creating and displaying the view2, would this work within view2 when you close it?
[parentViewController viewDidAppear:YES];
i re-did some code;
-(void)viewWillDisappear:(BOOL)animated
{
[self.outerCircle removeFromSuperview];
[self.innerCircle removeFromSuperview];
}
- (void)viewDidAppear:(BOOL)animated
{
self.innerCircle = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"inner-circle.png"]];
self.innerCircle.frame = CGRectMake(self.innerCircle.frame.origin.x, self.innerCircle.frame.origin.y, 30, 30);
self.outerCircle = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"outer-circle.png"]];
self.outerCircle.frame = CGRectMake(self.outerCircle.frame.origin.x, self.outerCircle.frame.origin.y, 40, 40);
[self.view insertSubview:self.innerCircle belowSubview:HUD];
[self.view insertSubview:self.outerCircle belowSubview:HUD];
//other code
}
with these changes, it behaves as i want it too.
i think it had something to do with trying to animate the outerCircle a second time (it was already animating from first viewDidAppear, and when viewDidAppear was called a second time, it re-animated an already animating image and just borked it completely).
Related
I have implemented refreshControl as shown below in viewDidLoad():
refreshControl = [[UIRefreshControl alloc] init];
if (#available(iOS 10.0, *)) {
self.tableView.refreshControl = refreshControl;
} else {
[self.tableView addSubview:refreshControl];
}
Now I am presenting another viewController which has options to select filters. And after selecting those filters you come back again to current viewController having refreshControl.
I have added below code in viewDidAppear() for manually calling beginRefreshing:
if (self.filterChanged) {
self.filterChanged = NO;
[self.activityTableView setContentOffset:CGPointMake(0, - refreshControl.frame.size.height) animated:YES];
[refreshControl setHidden:NO];
[refreshControl beginRefreshing];
}
I have used setContentOffset for scrolling back to top and showing refreshControl.
The only problem is suppose my tableView is half scrolled in between then there is a big gap between refreshControl.
If my tableView is not scrolled then it works fine like I have pulled down to refresh, but if it is half scrolled then inspite of giving setContentOffset there is a big gap between refreshControl and tableview.
You need to wait for the scroll to finish before you can start the refresh. Unfortunately there is no completion block on setContentOffset, so try this.
After creating your refresh control set the target and create a corresponding method.
[_refreshControl addTarget:self action:#selector(refreshRequested) forControlEvents:UIControlEventValueChanged];
- (void)refreshRequested {
[_activityTableView reloadData];
}
In your viewDidAppear you scroll to top and refresh when done.
[UIView animateWithDuration:0.25 delay:0 options:0 animations:^(void){
self.activityTableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
} completion:^(BOOL finished){
[self.refreshControl beginRefreshing];
[self refreshRequested];
}];
When finished loading you need to end refresh and make sure to scroll back to zero position.
- (void)finishedLoading {
[_refreshControl endRefreshing];
[self.activityTableView setContentOffset:CGPointMake(0, 0) animated:YES];
}
I have no idea, why it is not working.
All I want to do is a simple UIView animation in the viewDidLoad.
Here's my code:
[UIView animateWithDuration:3.0f animations:^{
[self.headline setCenter:CGPointMake(0.0, 200.0)];
}];
Nothing happens. When I test the general approach of calling a animation method on that particular object like this:
[UIView animateWithDuration:3.0f animations:^{
[self.headline setAlpha:0.0];
}];
it works!!! Why am I not able to move the view across the screen? I am using latest Xcode 4.5.
Thanks for any advice!
UPDATE:
When I add a view manually in code it works. But for the UIViews I create as Outlets in the Interface Builder it doesn't work.
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 200.0, 100.0)];
testLabel.backgroundColor = [UIColor redColor];
[self.view addSubview:testLabel];
[UIView animateWithDuration:3.0 animations:^{
testLabel.center = CGPointMake(0.0, 200);
}];
So obviously I am doing something wrong in the .xib file
Dont do it in viewDidLoad. The view is not pressent at that time yet.
Try it in viewDidAppear.
Well, I think the reason for the missing animation was the fact that I called a different push navigation animation from the view controller that was pushing the actual view on screen:
- (IBAction)goForSelection:(id)sender
{
SelectionViewController *selectionViewController = [[SelectionViewController alloc] initWithNibName:#"SelectionViewController" bundle:nil];
//[self.navigationController pushViewController:selectionViewController animated:YES];
[UIView transitionWithView:self.navigationController.view duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
[self.navigationController pushViewController:selectionViewController animated:NO];
} completion:^(BOOL finished) {
[selectionViewController startIntroAnimation];
}];
}
First I checked what happens when I use the default navigation controller segue. And to my surprise the animation did start. Then I inserted the call to the [selectionViewController startIntroAnimation] to the completion block and this works as well.
I use a bunch of custom segues to segue from one view controller view to another using:
[self performSegueWithIdentifier:#"createTeamAccountSegue" sender:self];
My question is, do the previous views automatically get destroyed in iOS5 and 6?
I keep having to create custom segues to go to the next view, and then create yet another new segue animation in reverse to go back to the last view. As long as they dont keep stacking up and up then this should be fine right?
EDIT: I should probably show you the general layout of what my custom UIStoryboardSegue class looks like:
- (void) perform {
UIViewController *sourceViewController = (UIViewController *) self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *) self.destinationViewController;
UIView *parent = sourceViewController.view.superview;
[parent addSubview:destinationViewController.view];
[parent sendSubviewToBack:destinationViewController.view];
sourceViewController.view.layer.masksToBounds = NO;
sourceViewController.view.layer.cornerRadius = 8; // if you like rounded corners
sourceViewController.view.layer.shadowOffset = CGSizeMake(0,0);
sourceViewController.view.layer.shadowRadius = 10;
sourceViewController.view.layer.shadowOpacity = 1;
destinationViewController.view.frame = CGRectMake(0, 20, destinationViewController.view.frame.size.width, destinationViewController.view.frame.size.height);
sourceViewController.view.frame = CGRectMake(0, 20, sourceViewController.view.frame.size.width, sourceViewController.view.frame.size.height);
[UIView animateWithDuration:.3 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^
{
sourceViewController.view.frame = CGRectMake(0, parent.frame.size.height, sourceViewController.view.frame.size.width, sourceViewController.view.frame.size.height);
} completion:^(BOOL finished)
{
[sourceViewController presentViewController:destinationViewController animated:NO completion:NULL];
}];
}
If you are doing there segues in a UINavigationController then no, they aren't destroyed. To go back to one you should use [self.navigationController popViewControllerAnimated:YES];
I'm following the example on how to create a tab bar with a center button like Path,Instagram, etc from here: http://idevrecipes.com/2010/12/16/raised-center-tab-bar-button/
The problem I have is that when a view is pushed onto the stack that sets HidesBottomBarWhenPushed to hide the tab bar, the center button is still displayed.
In the comments, several other people have had this problem, but there's no working solution. (I've tried all the suggested solutions in the comments)
I came up with a hacky solution-- store a reference to the center button in an unrelated singleton class, and then have the pushed view hide the button when it is loaded, and unhide it when it dissapears-- but this just feels wrong, and it looks funny because you can see the button dissapear before the push view animation starts.
Has anyone got this working?
I had the same problem.
I edited the BaseViewController.m (my UITabBarController subclass) by overriding the following viewDidLayoutSubviews method (button is my center button) as followed.
- (void)viewDidLayoutSubviews{
button.center = self.tabBar.center;
}
Now your button follows the tabbar.
You have to do this same but with UIImageView and add it to tabBar:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController: (UIViewController *)viewController
{
if (tabBarController.selectedIndex != AUCenterTabBarButtonIntex) {
self.centerImageView.highlighted = NO;
} else {
self.centerImageView.highlighted = YES;
self.selectedIndex = AUCenterTabBarButtonIntex;
}
}
- (void)addCenterImageViewWithImage:(UIImage *)image highlitedImage:(UIImage *)highlitedImage
{
UIImageView *centerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, image.size.width/2, image.size.height/2)];
centerImageView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;
centerImageView.image = image;
centerImageView.highlightedImage = highlitedImage;
CGFloat heightDifference = centerImageView.frame.size.height - self.tabBar.frame.size.height;
if (heightDifference < 0)
centerImageView.center = CGPointMake(self.tabBar.center.x, centerImageView.center.y);
else
{
CGPoint center = self.tabBar.center;
center.y = (self.tabBar.frame.size.height/2) - (heightDifference/2);
centerImageView.center = center;
}
[self.tabBar addSubview:centerImageView];
self.centerImageView = centerImageView;
}
Before push UIViewController,add your custom button to UITabBar
After pop UIViewController, restore custom button to self.view
Subclass UITabViewController
NSArray *array= self.viewControllers;
for(UIViewController *controller in array){
if([controller isKindOfClass:[UINavigationController class]]){
UINavigationController *navigationController=(UINavigationController*)controller;
navigationController.delegate=self;
}
}
Implement delegate method
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (viewController.hidesBottomBarWhenPushed) {
CGRect rect= [button convertRect:button.bounds toView:self.tabBar];
[button removeFromSuperview];
[self.tabBar addSubview:button];
button.frame=rect;
}
}
-(void)navigationController:(nonnull UINavigationController *)navigationController didShowViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated{
if(!viewController.hidesBottomBarWhenPushed){
CGRect rect= [button convertRect:button.bounds toView:self.view];
[button removeFromSuperview];
[self.view addSubview:button];
button.frame=rect;
}
}
I currently show a modal UIViewController in the formSheet style that was presented with the coverVertical animation. I am trying to present another modal UIViewController from it, using currentContext for the presentation style and flipHorizontal for the animation style. It does work, but there is a solid white white background behind the flip as it occurs. Any advice on how to successfully present another formsheet modal UIViewController using the flipHorizontal style from a pre-existing modal UIViewController in the formSheet style would be appreciated please! Thanks
Code:
// Loading of first modalVC
- (void)showModalVC {
Modal1VC *modal1VC = [[Modal1VC alloc] init];
modal1VC.modalPresentationStyle = UIModalPresentationFormSheet;
modal1VC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:modal1VC animated:YES];
[modal1VC release];
modal1VC.view.superview.bounds = CGRectMake(0, 0, 400, 400);
}
// Loading of second modalVC in Modal1VC
- (void)buttonTapped:(id)sender {
UIViewController *modal2VC = [[UIViewController alloc] init];
modal2VC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
modal2VC.modalPresentationStyle = UIModalPresentationCurrentContext;
modal2VC.view.backgroundColor = [UIColor greenColor];
[self presentModalViewController:modal2VC animated:YES];
[modal2VC release];
modal2VC.view.superview.bounds = CGRectMake(0, 0, 400, 400);
}
UIViewController *presentingViewController = //allocate your VC
[modalViewController setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
UIViewController *modalViewController = //your modal VC
[presentingViewController presentModalViewController:modalViewController animated:YES];
This is all the code you need ;)
It sounds like your transition is working, but the white background shown on the flip transition is the problem?
During the flip transition, the white background that is shown is actually the window. You can change the color that is shown by setting the backgroundColor property of window in the AppDelegate.
That would seem to be a limitation of presentModalViewController:animated:.
Instead of [self presentModalViewController:modal2VC animated:YES], you may be able to get the effect you want using UIView animations. Perhaps something like this:
[UIView transitionWithView:self.view.window
duration:0.3
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[self presentModalViewController:modal2VC animated:NO];
} completion:NULL];