Rotating One UIView Causes Another To Be Pushed OffScreen - objective-c

I have a ViewController which contains a couple of UILabels, a UIImageView and an ADBannerView. There are two relevant movements: The UIImageView rotates based on the angle at which the user is holding their device, and the ADBannerView slides into view based on whether it has an iAD to display.
If the UIImageView is stationary, the ADBannerView slides into view correctly. However, once the UIImageView starts rotating, the ADBannerView disappears. AFAIK the two views are completely independent.
- (void) updateFloatingBar
{
double angleToUpright = [self calculateAngleToUpright];
double newAngle = angleToUpright - self.currentAngle;
[self.FloatingBarImageView setTransform:CGAffineTransformMakeRotation(newAngle*(CGFloat)(M_PI/180))];
}
- (void) hideAd
{
NSLog(#"Ad Hidden");
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:self.adBannerView cache:YES];
self.adBannerView.frame = CGRectMake(0,self.view.bounds.size.height + 50,50,320);
[UIView commitAnimations];
}
- (void) showAd
{
NSLog(#"Ad Shown");
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:self.compassADBannerView cache:YES];
self.compassADBannerView.frame = CGRectMake(0,self.view.bounds.size.height - 50,50,320);
[UIView commitAnimations];
}
Again, the first method works correctly, it just also has the secondary effect of pushing offscreen the adBannerView placed by showAd:

Related

Fading UIView allows subviews to be seen

I have a UIScrollView which contains various subviews (UIImageViews, UILabels and standard UIViews). Some of the UIImageViews are partially covered by other UIViews.
However, when I fade out the UIScrollView, the partially covered parts of the UIImageViews are being exposed for the brief moment of the animation.
I want to be able to fade the scrollview and all it's contents at the same time in the same animation - i.e. not revealing any of the partially covered images.
If it's not possible, I can always add a UIView on top of all the other controls and fade it from alpha 0 upto 1 to hide everything, but I'm sure there's a way to perform a complete fade on a view and all it's subviews.
I tried this:
[UIView beginAnimations:nil context:NULL];
[scrollViewResults setAlpha:0.0f];
[UIView commitAnimations];
And I've tried this:
- (IBAction)questionGroupChanged:(UIButton*)sender {
[UIView beginAnimations:nil context:NULL];
[self fadeViewHierarchy:scrollViewResults toAlpha:0.0f];
[UIView commitAnimations];
}
- (void)fadeViewHierarchy:(UIView*)parentView toAlpha:(float)alpha {
[parentView setAlpha:alpha];
for (UIView *subView in parentView.subviews) {
[self fadeViewHierarchy:subView toAlpha:alpha];
}
}
But I've still not cracked it. Any ideas?
This happens because of the way the compositor works. You need to enable rasterization on the view's layer when fading it in/out:
view.layer.shouldRasterize = YES;
You should probably only enable this for the duration of the animation because it will take up some extra memory and graphics processing time.
Mike's answer is the correct one and he deserves all credit for this. Just to illustrate, it might look like:
- (void)fadeView:(UIView*)view toAlpha:(CGFloat)alpha
{
view.layer.shouldRasterize = YES;
[UIView animateWithDuration:0.75
animations:^{
view.alpha = alpha;
}
completion:^(BOOL finished){
view.layer.shouldRasterize = NO;
}];
}
Thus, using your scrollViewResults, it would be invoked as:
[self fadeView:scrollViewResults toAlpha:0.0f];
Did you try with UIView class methods +animateWithDuration:* (available on iOS 4 and +)
Like :
- (void)fadeAllViews
{
[UIView animateWithDuration:2
animations:^{
for (UIView *view in allViewsToFade)
view.alpha = 0.0;
}
completion:^(BOOL finished){}
];
}

I want to slide a transparent menu in from the left

I would like to implement a menu as shown above. I'm a total iOS newbie. I've been searching for that kind of control since couple of days.
Can someone guide me step by step, from scratch?
You can implement the above in following steps :-
1>Left Menu view is a UIView added as a subview with various cutom UIButtons over it added as subview.
2>Initially you have to set the frame so that only a particular part of the view is shown(Panel Part).
3> On the click of indicator button , expand the frame to its full to show the buttons.
4>On next click i.e(odd clicks) collase the frame.
Above animation can be achieved using simple UIView Animation.
Sample code(Original frame width=300,Height 300) :-
yourMenuView.frame=CGRectMake(0,10,100,300);
[yourViewController addSubview:yourMenuView];
-(IBAction)expandMenu:(id)sender
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
CGRect frame=yourMenuView.frame;
frame.size.width+=200;
yourMenuView.frame=frame;
[myview removeFromSuperview];
[UIView commitAnimations];
}
-(IBAction)collapseMenu:(id)sender
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
CGRect frame=yourMenuView.frame;
frame.size.width-=200;
yourMenuView.frame=frame;
[myview removeFromSuperview];
[UIView commitAnimations];
}

UIPickerView : Keyboard not hiding

I have 3 UITexfield, the user can fill in the first two, but the last one is a category field and displays a UIPickerView when it's clicked.
What I've managed to do so far is :
The user clicks on the catergory textfield -> the picker view appears
Then the user clicks on another textfield -> the picker view disappears and the keyboard shows up
But know I would like to hide the keyboard when the user clicks agains on the category textfield and show the picker view.
This is what I have so far :
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if(textField == categoryTextField){
[categoryTextField resignFirstResponder];
[UIView beginAnimations:#"picker" context:nil];
[UIView setAnimationDuration:0.3];
pickerView.transform = CGAffineTransformMakeTranslation(0,-236);
[UIView commitAnimations];
}else{
[UIView beginAnimations:#"picker" context:nil];
[UIView setAnimationDuration:0.3];
pickerView.transform = CGAffineTransformMakeTranslation(0,236);
[UIView commitAnimations];
}
}
But it doesn't work. Any thought why ?
You're making it too difficult. Set the picker view as the input view of the textfield, and the OS will take care of the animations for you. As each field becomes first responder, the appropriate input view (default keyboard for the text ones, your picker for the third one) will be displayed. You don't need to do any animations yourself.
I don't really see where your problem comes from. I think that maybe your translation makes the pickerView move too far. You should try that :
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if(textField == categoryTextField){
[categoryTextField resignFirstResponder];
[UIView beginAnimations:#"picker" context:nil];
[UIView setAnimationDuration:0.3];
CGRect frame = pickerView.frame;
frame.origin.y = 480 - 236; // assuming your on an iPhone and your picker appears from bottom
pickerView.frame = frame;
[UIView commitAnimations];
}else{
[UIView beginAnimations:#"picker" context:nil];
[UIView setAnimationDuration:0.3];
CGRect frame = pickerView.frame;
frame.origin.y = 480; // assuming your on an iPhone and your picker disappears to bottom
pickerView.frame = frame;
[UIView commitAnimations];
}
}
Hope that helps

iOS - animating UIView on iPad, change x origin and width simultaneously?

I'm having some trouble with UIView animations on iPad.
I'm working on a project in which I have implemented a "facebook style" menu on the left, using the JTRevealSidebar framework.
This framework works perfectly, however, instead of "pushing" the right side view off the screen, I would like to resize it, so the user can still see the whole content of the right-side view.
I have managed to do this by changing the view's frame as well as doing the offset.
This is what it looks like with the sidebar open:
And when it's closed:
This right-side view contains a navigation bar with two buttons (one button on the left to toggle the left sidebar, and another button on the right to dismiss the controller), and the content itself is a simple UIWebView.
The problem I am facing is during the animation (from the full-screen state to the sidebar open state):
When I change the view's frame, even after doing the translate, the view resizes before the animation starts, which gives a weird effect like this:
I would like to keep the right side of the webview anchored to the right side of the screen and only have the left side change position when animating (basicaly so that the "done" button is always in the same position).
Here is the animation code:
- (void)revealSidebar:(BOOL)shouldReveal {
if (shouldReveal) {
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:0.3];
// Push the view to the right
contentView.transform = CGAffineTransformTranslate(contentView.transform, CGRectGetWidth(sidebarView.frame), 0);
// Resize the view so it fits on remaining part of the screen
contentView.frame = CGRectMake(contentView.frame.origin.x, contentView.frame.origin.y, contentView.frame.size.width-sidebarView.frame.size.width, contentView.frame.size.height);
// The problem is here: the view's frame is changed before the
// Translate transformation actualy starts...
//
// Is there a way to change the x origin and the width simultaneously ?
[UIView commitAnimations];
} else {
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:0.3];
// Reset the frame so that it takes up whole screen
contentView.frame = CGRectMake(contentView.bounds.origin.x,contentView.bounds.origin.y,contentView.frame.size.width+sidebarView.frame.size.width,contentView.frame.size.height);
[UIView commitAnimations];
}
_state.isShowing = shouldReveal ? 1 : 0;
}
I've had no luck so far, and was wandering if anyone had any ideas as to how I could achieve this.
Thank you
EDIT 2:
It seems that the subviews are being immediately resized dueto translations being used. So maybe you could just animate the move to the right and then when that has finished set the width:
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
contentView.frame = CGRectMake(CGRectGetWidth(sidebarView.frame), 0, contentView.frame.size.width-CGRectGetWidth(sidebarView.frame), contentView.frame.size.height);
}
- (void)animationDidStopBack:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
contentView.frame = contentView.bounds;
}
- (void)revealSidebar:(BOOL)shouldReveal {
if (shouldReveal) {
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:0.1];
[UIView setAnimationDelegate:self];
contentView.frame = CGRectOffset(contentView.bounds, CGRectGetWidth(sidebarView.frame), 0);
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
[UIView commitAnimations];
} else {
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
contentView.frame = CGRectMake(0, 0, contentView.frame.size.width+CGRectGetWidth(sidebarView.frame), contentView.frame.size.height);
[UIView setAnimationDidStopSelector:#selector(animationDidStopBack:finished:context:)];
[UIView commitAnimations];
}
_state.isShowing = shouldReveal ? 1 : 0;
}
It's not perfect but does avoid the blank space on the right and I feel looks better because of that. Particularly if you speed up the animation.
EDIT 1:
try:
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:0.3];
if (shouldReveal) {
contentView.frame = CGRectMake(CGRectGetWidth(sidebarView.frame), 0, contentView.frame.size.width-CGRectGetWidth(sidebarView.frame), contentView.frame.size.height);
} else {
contentView.frame = CGRectMake(0, 0, contentView.frame.size.width+CGRectGetWidth(sidebarView.frame), contentView.frame.size.height);
}
[UIView commitAnimations];
Old Answer:
sounds /looks like you just need your x position modifying to always be at the edge of the sidebar. untested code assuming your contentview's origin is at far left:
- (void)revealSidebar:(BOOL)shouldReveal {
if (shouldReveal) {
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:0.3];
// Push the view to the right
contentView.transform = CGAffineTransformTranslate(contentView.transform, CGRectGetWidth(sidebarView.frame), 0);
// Resize the view so it fits on remaining part of the screen
contentView.frame = CGRectMake(contentView.frame.origin.x, contentView.frame.origin.y, contentView.frame.size.width-sidebarView.frame.size.width, contentView.frame.size.height);
[UIView commitAnimations];
} else {
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:0.3];
// Resize the view so it fits on full screen
contentView.frame = CGRectMake(sidebarView.frame.size.width, contentView.frame.origin.y, contentView.frame.size.width-sidebarView.frame.size.width, contentView.frame.size.height);
[UIView commitAnimations];
}
_state.isShowing = shouldReveal ? 1 : 0;
}
if the origin is actually centred then:
contentView.frame = CGRectMake(sidebarView.frame.size.width+(contentView.frame.size.width/2), contentView.frame.origin.y, contentView.frame.size.width-sidebarView.frame.size.width, contentView.frame.size.height);

swapping views with cool page turn animation

Below is code that I'm using to swap views
MySecondViewController *tempVC = [[MySecondViewController alloc] initWithNibName:#"MySecondView"];
[self presentModalViewController:tempVC animated:YES];
[tempVC passDataWithString:#"a string" andColor:yellowcolor];
How can I get the cool page turning animation (as with iBook or ROAD RAGE SIGN)
I don't want the user to actually tap and drag his finger on the screen. I want him to push a button and the animation occurs by itself.
Have you looked at UIViewAnimationTransition values? Use them in a UIView animation block. eg:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition: UIViewAnimationTransitionCurlUp
forView:self.view cache:YES];
[UIView commitAnimations];