I'm using the following code to attempt to flip a UIView. It's a playing card. There's a container view, with two children, front and back. I've read in similar questions here that this should be the correct way to do it, but the actual flip itself is not being performed.
I'm intending for this to animate moving the card to the centre of the screen, and flip it from its back to front. The movement to centre is fine, but the flip never occurs.
If I change the View: argument to self, it flips the entire view controller, and if I leave it on the cardContainer, it does nothing at all.
Puzzled :(
UIView *cardContainer = [[UIView alloc] initWithFrame:CGRectMake(20, self.view.frame.size.height + 20, [Card size].width, [Card size].height)];
[self.view addSubview:cardContainer];
Card *card = _playerOneCards[_playerOneNextCardIndex];
card.frame = CGRectMake(0, 0, [Card size].width, [Card size].height);
card.delegate = self;
[cardContainer addSubview:card];
CardBack *back = [[CardBack alloc] initWithFrame:CGRectMake(0, 0, [Card size].width, [Card size].height)];
[cardContainer addSubview:back];
[UIView transitionWithView:cardContainer
duration:duration
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
back.alpha = 0.0f;
cardContainer.center = self.center;
}
completion:nil];
Try this. The container view has to be placed in the hierarchy before the animation starts.
//Add container views and subviews
[CATransaction flush];
[UIView transitionWithView:cardContainer
duration:duration
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
back.alpha = 0.0f;
cardContainer.center = self.center;
}
completion:nil];
You can also wrap your function up in a dispatch_after call.
For more information check : http://andrewmarinov.com/working-with-uiviews-transition-animations/
Related
My problem is...
I have the object of parent view controller and i wanted to animate second view controller over that.
So i added a subview called backgroundview over the view of parentvc.view and then the view which needs to be drawn over the backgroundView.
But after animation completes for a second, i can see the views the way i want them to be but then it is replaced by a complete black screen.
I think my topmost view is redrawn so how do i rectify this issue.
Code :-
- (void)viewDidLoad {
[super viewDidLoad];
//_colorCaptureOptions = [NSArray arrayWithObjects: #"Camera", #"Color Slider / Color Wheel", nil];
mExtractionQueue = [[NSOperationQueue alloc] init];
[mExtractionQueue setMaxConcurrentOperationCount:1];
CGRect screenRect = [[UIScreen mainScreen] bounds];
//CGRect screenRect = self.view.frame;
self.backgroundView = [[UIView alloc] initWithFrame:screenRect];
self.backgroundView.backgroundColor = [UIColor clearColor];
[self.parentVC addChildViewController:self];
[self.parentVC.view addSubview:self.backgroundView];
//[self didMoveToParentViewController:self.parentVC];
UITapGestureRecognizer *guideTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleScrimSelected)];
[self.backgroundView addGestureRecognizer:guideTap];
[self.backgroundView addSubview:self.view];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat viewHeight = 150;
self.backgroundView.alpha = 0.0;
self.view.alpha = 1;
self.view.frame = CGRectMake(0, screenRect.size.height, screenRect.size.width, viewHeight);
[UIView animateWithDuration:0.2
delay:0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
self.backgroundView.alpha = 1.0;
self.view.frame = CGRectMake(0, screenRect.size.height - viewHeight, screenRect.size.width, viewHeight);
}
completion:^(BOOL _finished) {
}];
}
}
Well, for clarity you'd better to provide few screenshots.
For all the rest:
Possibly, your background view is simply black that leads to black screen. Or it even is [UIColor clearColor]
better not use childViewController, it breaks MVC
better not change frame inside animation directly
If you want present another controller with animation, use this UIViewControllerTransitioningDelegate and this UIViewControllerAnimatedTransitioning in your objects, so do not reinvent transitions. Refer to this custom controller transition tutorial
Hope this may help you
EDIT:
[UIColor clearColor] removes colour entirely, so that means you will have no color at all.
The best solution for you now is rewrite those controllers, split up one from another, get rid of container for viewControllers, change animation to custom and than problem will disappear as a magic. If you solve you problem, do not forget to mark question as resolved, please
I'm trying to show a fullscreen picture from a smaller one included in a custom UITableViewCell. My code is highly linked to this article
By the way, in this example, the frame : [[UIScreen mainScreen] bounds]is not the good one for me. It's the an UIScrollView's bounds that I've got. I this to add the main screen through a variable inside the cell directly when each cell is created. So I've customized the previous example like this :
//viewDidLoad
self.globalView.frame = [[UIScreen mainScreen] bounds];
//cellForRowAtIndexPath
[cell setFullScreenView:self.globalView];
//fullScreenMethod
if (!isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = imageView.frame;
[imageView setFrame:self.fullScreenView.frame];
}completion:^(BOOL finished){
isFullScreen = YES;
}];
return;
}
My problem is that the imageView's new frame is not a full screen but still the UIScrollView's one.
Thank you for your help !
Best approach is create one temporary UIImageView and Show it in full screen,
For animation simply add the temporary UIImageView to location where the image view exists and animate it to full-screen and do revers for normal
Add tap gesture to UIImageView and add this bannerTapped as selector
//This will create a temporary imaget view and animate it to fullscreen
- (void)bannerTapped:(UIGestureRecognizer *)gestureRecognizer {
NSLog(#"%#", [gestureRecognizer view]);
//create new image
temptumb=(UIImageView *)gestureRecognizer.view;
//fullview is gloabal, So we can acess any time to remove it
fullview=[[UIImageView alloc]init];
[fullview setContentMode:UIViewContentModeScaleAspectFit];
[fullview setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"bckgrd.png"]]];
fullview.image = [(UIImageView *)gestureRecognizer.view image];
CGRect point=[self.view convertRect:gestureRecognizer.view.bounds fromView:gestureRecognizer.view];
[fullview setFrame:point];
[self.view addSubview:fullview];
[UIView animateWithDuration:0.5
animations:^{
[fullview setFrame:CGRectMake(0,
0,
self.view.bounds.size.width,
self.view.bounds.size.height)];
}];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(fullimagetapped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[fullview addGestureRecognizer:singleTap];
[fullview setUserInteractionEnabled:YES];
}
//This will remove the full screen and back to original location.
- (void)fullimagetapped:(UIGestureRecognizer *)gestureRecognizer {
CGRect point=[self.view convertRect:temptumb.bounds fromView:temptumb];
gestureRecognizer.view.backgroundColor=[UIColor clearColor];
[UIView animateWithDuration:0.5
animations:^{
[(UIImageView *)gestureRecognizer.view setFrame:point];
}];
[self performSelector:#selector(animationDone:) withObject:[gestureRecognizer view] afterDelay:0.4];
}
//Remove view after animation of remove
-(void)animationDone:(UIView *)view
{
//view.backgroundColor=[UIColor clearColor];
[fullview removeFromSuperview];
fullview=nil;
}
It can't take a full screen frame because its parent view is the scrollView. Either show view modally or somehow move imageView directly under view controller's main view.
I'm trying to create sort of a slide-out slide-in motion for my views when the user presses the forward or backwards button.
I made the first view slide out just fine, but the second one just won't slide in.
Here's my code:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelay:0.1];
[UIView setAnimationDuration:0.7];
UIView *currentView = [[contentScrollView subviews] objectAtIndex:0];
currentView.center = CGPointMake(contentScrollView.frame.size.width+contentScrollView.frame.size.width/2, currentView.center.y);
UIView *newView = [[contentScrollView subviews] objectAtIndex:1];
newView.center = CGPointMake(newView.center.x+newView.frame.size.width, newView.center.y);
[UIView commitAnimations];
I don't really see what the problem is, it should work. But the currentView just slides out, and the newView is still out in the -x values, hidden from the user.
I already tried changing to transformations, but that didn't do anything.
What could cause this?
Try this code (tested):
Copy and paste it to see it in action and adjust the frames for your views to suit your needs.
UIView *viewOne = [[UIView alloc] initWithFrame:(CGRect){{0, 0}, 200, 200}]; //currentView
UIView *viewTwo = [[UIView alloc] initWithFrame:(CGRect){{200, 0}, 200, 200}]; //newView
viewOne.backgroundColor = [UIColor lightGrayColor];
viewTwo.backgroundColor = [UIColor darkGrayColor];
[self addSubview:viewOne];
[self addSubview:viewTwo];
[UIView animateWithDuration:5.0f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^
{
viewOne.frame = (CGRect){{300, 0}, 200, 200};
viewTwo.frame = (CGRect){{-100, 0}, 200, 200};
} completion:^(BOOL finished) {
}];
This is to show you how these two view sliding in and out.
You have to adjust the frames for your views accordingly to your needs.
I'm new iphone developer i have problem uiview animation for ipad landscape mode.i have two view view1(like a split view) and view2(covered remaining window).when i touch move right to left view2 it will be overriding the view1 with moving animation.at same time when i touch move left to right view2 come and fit the old position.please share your ideas
With Regards,
Rajesh.
Hi all i found the answer finally,
- (void)viewDidLoad
{
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(rightSwipeHandle:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[recognizer setNumberOfTouchesRequired:1];
[secondView addGestureRecognizer:recognizer];
[recognizer release];
UISwipeGestureRecognizer *recognizerleft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(leftSwipeHandle:)];
[recognizerleft setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[recognizerleft setNumberOfTouchesRequired:1];
[secondView addGestureRecognizer:recognizerleft];
[recognizerleft release];
[self.view addSubview:secondView];
[super viewDidLoad];
}
//To set the frame position of the view
- (void)rightSwipeHandle:(UISwipeGestureRecognizer*)gestureRecognizer
{
NSLog(#"rightSwipeHandle");
[UIView beginAnimations:#"viewanimations" context:nil];
[UIView setAnimationDuration:0.8];
[UIView setAnimationDelegate:self];
secondView.frame=CGRectMake(360, 0, 660, 768);
[UIView commitAnimations];
}
//To set the frame position of the view
- (void)leftSwipeHandle:(UISwipeGestureRecognizer*)gestureRecognizer
{
NSLog(#"leftSwipeHandle");
[UIView beginAnimations:#"viewanimations" context:nil];
[UIView setAnimationDuration:0.8];
[UIView setAnimationDelegate:self];
secondView.frame=CGRectMake(200, 0, 858, 768);
[UIView commitAnimations];
}
if i understand correctly, you want a sliding animation between 2 views. if so:
Make a ViewController that will hold these two views. inside this view controller's .m file define a transition method that contains the following and gets called by your buttons/other action triggers:
CGFloat windowWidth = self.mainView.frame.size.width;
CGFloat windowHeight = self.mainView.frame.size.height;
CGRect offScreenLeft = CGRectMake(-1*windowWidth, 0.0, windowWidth, windowHeight);
CGRect onScreen = self.mainView.frame;
CGRect offScreenRight = CGRectMake(windowWidth, 0.0, windowWidth, windowHeight);
if (direction == rightToLeft)
{
rightView.frame = offScreenRight;
[self.view addSubview:rightView];
[UIView animateWithDuration:0.65
animations:^{
leftView.frame = offScreenLeft;
rightView.frame = onScreen;
}
completion:^(BOOL finished){
[leftView removeFromSuperview];
}];
}else if (direction == leftToRight){
self.leftViewController.view.frame = offScreenLeft;
[UIView animateWithDuration:0.65
animations:^{
rightView.frame = offScreenRight;
leftView.frame = onScreen;
}
completion:^(BOOL finished){
[rightView removeFromSuperview];
}];
}
}
In general, make sure you are adding your subview to the view currently on screen, and make sure you set the appropriate bounds. Check that your view is not nil:
if(myView){
// not nil. thats good
}else {
// nil. this is bad. make sure myView is being initialized properly (if at all)
}
Finally, make sure neither the opacity nor the alpha property on your subview is set to 0 (you'll want these at 1 if you want it to show up completely and between 0 and 1 for a transparency effect).
I have a custom UIView with nested views of type UIImageView, UILabel and UIButton. The view is created in code like this:
- (void)setupView
{
popupView = [[UIView alloc] initWithFrame:CGRectMake(-116, -61, 247, 59)];
popupView.autoresizingMask = 63;
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bubble.png"]];
bgImageView.autoresizingMask = 63;
[popupView addSubview:bgImageView];
[bgImageView release];
textLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 8, 180, 20)];
textLabel.autoresizingMask = 63;
textLabel.font = [UIFont fontWithName:#"DefaultNormal" size:16];
textLabel.text = #"DYNAMIC TEXT";
[popupView addSubview:textLabel];
popupButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
[rightAccessoryButton setImage:[UIImage imageNamed:#"btn-tick.png"] forState:UIControlStateNormal];
popupButton.frame = CGRectMake(208, 8, 32, 32);
popupButton.autoresizingMask = 63;
[popupView addSubview:rightAccessoryButton];
}
I've set all their autoresizingMasks to 63 which is basically everything in the ON position (I don't know a better way of doing that except putting all the constants on a huge line of code!). Then when they need to animate the popup, I do this:
- (void)animateIn
{
float pw = 247;
float ph = 59;
// set the view's initial position
popupView.frame = CGRectMake(-pw*0.005+8, -ph*0.01-2, pw*0.01, ph*0.01);
[self addSubview:popupView];
[UIView animateWithDuration:0.12 delay:0.0 options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionLayoutSubviews animations:^(void) {
popupView.frame = CGRectMake(-pw*0.55+8, -ph*1.1-2, pw*1.1, ph*1.1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^(void) {
popupView.frame = CGRectMake(-pw*0.475+8, -ph*0.95-2, pw*0.95, ph*0.95);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.075 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^(void) {
popupView.frame = CGRectMake(-round(pw/2-8), -ph-2, pw, ph);
} completion:nil];
}];
}];
}
Bit of a complicated looking animation, but effectively this is the same animation as the mapview callout view animation.
Only thing is, it works perfectly on iOS 5 devices, but on iOS 4 devices, everything is wrong! The label doesn't show at all, the button appears and then flies off shrinking into the top right hand corder, and the background image stretches to the wrong size and in the wrong place.
Anyone else had any problems with animations in iOS 4? Do I have to do things differently than how they are currently in order to get it to work?
(1) Are you doing manual layout in a UIView subclass's layoutSubviews implemention? If not, you should not be using UIViewAnimationOptionLayoutSubviews in your options bitmask. I don't know if that's the problem but there's no point adding extra sources of possible error.
(2) When in doubt, use Core Animation. You could describe your animation sequence very handily as a nice CAAnimationGroup.