Adding subviews programmatically on iPad, hard coding - objective-c

I'm adding a custom status bar in my application to monitor upload progress. This works fine in portrait mode, but when I am in landscape and my custom status bar appears, it always appears on the opposite side of the home button. I think it's because I'm hard coding my frame.
I have the XIB file set to auto adjust its length.
take a look:
-(void) animateStatusBarIn {
float x = window.frame.origin.x;
float y = window.frame.origin.y;
float height = 20;
float width = window.frame.size.width;
CGRect statusFrame = CGRectMake(x, y-20, width, height);
iPadUploadStatusBar *statusView = [[iPadUploadStatusBar alloc] initWithNibName:#"iPadUploadStatusBar" bundle:nil];
self.status = statusView;
[statusView release];
status.view.frame = statusFrame;
[window addSubview:status.view];
[UIView beginAnimations:#"slideDown" context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:)];
statusWindow.frame = CGRectMake(0.0f, 0.0f, 1024.0f, 20.0f);
[UIView commitAnimations];
}
All is good in portrait orientation, but like I said, it always decides that the new status bar should go opposite of the home button.
By the way, this is inside AppDelegate.m, so I'm using the existing window that's in the default appDelegate file

Firstly, where are you calling your -animateStatusBarIn method from?
You dont have to set the frame for iPadUploadStatusBar's view when rotation occurs (in case if you are calling the method animateStatusBar each time when orientation changes).
All you have to do is, set the autoresizing masks for the view properly in your iPadUploadStatusBar nib and add it as a subview to window or a viewController's view which is already a subview of window. The rotation and its animation is all handled automatically for you.

Related

Change background colour BEHIND ViewController frame (when frame.origin is altered)?

I have an app which intakes client details, built for iPad. When the user taps a UITextField towards the bottom half of the ViewController, the frame programatically shifts upwards so that the fields aren't hidden behind the keyboard. (I tried to implement a UIScrollView but just cannot seem to get it working.) The slight issue I'm having now is when the frame shifts up, you can vaguely see the black behind it. This isn't a huge issue because I have changed the animation time and the black background is barely visible, but I have a feeling there is a more elegant solution.
Here is my code to shift the frame:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
// Animate frame up if lower textfields are tapped
if (([textField isEqual:_emailField]) || ([textField isEqual:_dobField]) || ([textField isEqual:_niNumField])) {
[UIView beginAnimations:nil
context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frame = self.view.frame;
frame.origin.y = -210;
[self.view setFrame:frame];
[UIView commitAnimations];
} else {
// Return frame to original position if other textfields are tapped
[self dismissKeyboard];
}
return YES;
}
- (void)dismissKeyboard {
[UIView beginAnimations:nil
context:NULL];
[UIView setAnimationDuration:0.15f];
CGRect frame = self.view.frame;
frame.origin.y = 0;
[self.view setFrame:frame];
[UIView commitAnimations];
}
Here is a brief screenshot of what I'm trying to describe. Left picture is the ViewController normally, right picture is when the frame has been shifted upwards. You can see (vaguely) almost in line with the second row of characters is where the frame stops.
I realise this doesn't seem like an issue because it is barely visible at all, but I have had to speed up the animation hiding the keyboard or else the frame drags behind and the black background becomes visible. I am wondering: is there a way to change this colour? Or is that something we don't have access to? If anyone can suggest a more elegant method for what I am trying to do, I'd gladly take a better solution. Thanks in advance.
Your UIViewController's view is added to the main UIWindow. So you should be able to achieve what you want by changing the UIWindow's background color.
In the UIApplicationDelegate:
self.window.backgroundColor = [UIColor whiteColor];
However, what you're doing isn't the best way to solve the problem of the keyboard covering up the text fields. You should use a UIScrollView or a UITableView to manage this view and use content insets to shift the view up or down.

How to get object position and size in UIView objective c

I put UIImageView in my Scene from Object library, and give it an image and defined OUTLET in .h file. Now I want to check its coordinates, or center point, or frame X,Y,Width,Height.
I am using
This
CGRect newFrameSize = CGRectMake(recycleBin.frame.origin.x, recycleBin.frame.origin.y,
recycleBin.frame.size.width, recycleBin.frame.size.height);
or
CGRect newFrameSize = recycleBin.frame;
by using this
NSLog(#"%#", NSStringFromCGRect(newFrameSize));
gives same result that is
2013-01-16 21:42:25.101 xyzapp[6474:c07] {{0, 0}, {0, 0}}
I want its actual position and size when viewcontroller loaded, so when user click on image view it will fadeout by zoom-in towards users and will disappear, and when user tap on reset button, it fadein and zoom-in back to original form (reverse to the previous animation).
Also give me hint, how to perform this animation on UIImageView or any button or label. Thx
Unfortunately, you can't check an item's actual frame as set in IB in -viewDidLoad. The earliest you can check it (that I've found) is by overriding -viewDidAppear:. But, since -viewDidAppear: could be called multiple times throughout the life of the view, you need to make sure you're not saving the frame it's in the modified state.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if(savedFrame == CGRectZero) {
savedFrame = self.recycleBin.frame;
NSLog(#"Frame: %#", NSStringFromCGRect(savedFrame));
}
}
Where savedFrame is a member variable (or you could make it a property).
From the description of the animation you're wanting, it sounds like adjusting the frame isn't the way to go about it. It sounds like you're wanting to get the effect of the view stretching and fading out (and the reverse when being reset)? If so, some code like this might be more so what you're looking for...
Fade out:
float animationDuration = 2.0f; // Duration of animation in seconds
float zoomScale = 3.0f; // How much to zoom in duration the animation
[UIView animateWithDuration:animationDuration animations:^{
CGAffineTransform transform = CGAffineTransformMakeScale(zoomScale, zoomScale);
self.recycleBin.transform = transform;
self.recycleBin.alpha = 0; // Make fully transparent
}];
And then, to reset the view:
float animationDuration = 2.0f; // Duration of animation in seconds
[UIView animateWithDuration:animationDuration animations:^{
CGAffineTransform transform = CGAffineTransformMakeScale(1.0f, 1.0f);
self.recycleBin.transform = transform;
self.recycleBin.alpha = 1.0; // Make fully opaque
}];
You can play around with the numbers to see if you get the effects you desire. Most animations in iOS are actually extremely simple to do. This code would work for any UIView subclass.
It sounds as if your IBOutlet is not attached to your class.
Open up your view controller header file (if that is where you property declaration is) and look beside the declaration:
Notice how on the first IBOutlet, the circle (to the left of the line number) is filled in. This means that it is connected to your scene. However, the second one is not (the circle is not filled in).

Animating an image view to slide upwards

I am attempting to make an image view (logo below) slide upwards by 100 pixels. I am using this code, but nothing happens at all:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:3];
logo.center = CGPointMake(logo.center.x, logo.center.y - 100);
[UIView commitAnimations];
This code is in the viewDidLoad method. Specifically, the logo.center = ... is not functioning. Other things (like changing the alpha) do. Maybe I'm not using the right code to slide it upwards?
For non-autolayout storyboards/NIBs, your code is fine. By the way, it's now generally advised that you animate using blocks:
[UIView animateWithDuration:3.0
animations:^{
self.logo.center = CGPointMake(self.logo.center.x, self.logo.center.y - 100.0);
}];
Or, if you want a little more control over options and the like, you can use:
[UIView animateWithDuration:3.0
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^{
self.logo.center = CGPointMake(self.logo.center.x, self.logo.center.y - 100);
}
completion:nil];
But your code should work if you're not using autolayout. It's just that the above syntax is preferred for iOS 4 and later.
If you're using autolayout, you (a) create an IBOutlet for your vertical space constraint (see below), and then (b) you can do something like:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
static BOOL logoAlreadyMoved = NO; // or have an instance variable
if (!logoAlreadyMoved)
{
logoAlreadyMoved = YES; // set this first, in case this method is called again
self.imageVerticalSpaceConstraint.constant -= 100.0;
[UIView animateWithDuration:3.0 animations:^{
[self.view layoutIfNeeded];
}];
}
}
To add an IBOutlet for a constraint, just control-drag from the constraint to your .h in the assistant editor:
By the way, if you're animating a constraint, be sensitive to any other constraints that you might have linked to that imageview. Often if you put something right below the image, it will have its constraint linked to the image, so you may have to make sure you don't have any other controls with constraints to your image (unless you want them to move, too).
You can tell if you're using autolayout by opening your storyboard or NIB and then selecting the "file inspector" (the first tab on the right most panel, or you can pull it up by pressing option+command+1 (the number "1")):
Remember, if you planning on supporting pre-iOS 6, make sure to turn off "autolayout". Autolayout is an iOS 6 feature and won't work on earlier versions of iOS.
have u try
logo.frame = CGRectMake(logo.frame.origin.x, logo.frame.origin.y - 100,logo.frame.size.width,logo.frame.size.height)

GMGridView appears offscreen, but overlaps with onscreen view

I am using a custom controller for transitions (could not use navigation controller due to inherent cycles in project, which would allow the navigation controllers stack to grow unbounded [which I assume would cause memory issues]). I am emulating a navigation controllers sliding animation (when transitioning to new screens) using UIView animateWithDuration:animations:completion:
When a button triggering the transition is pressed, the frame of the new view I want to transition to is set to an offscreen position. In the animation for the transition (UIView animateWithDuration:animations:completion:), the view currently on screen has its frame set to an offscreen position, and the new view is set to an onscreen position.
This is inside my custom controller for transitions:
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 == TransitionDirectionForward)
{
if (dragBackgroundOnscreen){
[self.mainView addSubview:self.backgroundView];
[self.mainView sendSubviewToBack:self.backgroundView];
self.backgroundView.frame = offScreenRight;
}
self.currentViewController.view.frame = offScreenRight;
[UIView animateWithDuration:0.65
animations:^{
oldViewController.view.frame = offScreenLeft;
if (dragBackgroundOffscreen)
self.backgroundView.frame = offScreenLeft;
else if (dragBackgroundOnscreen)
self.backgroundView.frame = onScreen;
self.currentViewController.view.frame = onScreen;
}
completion:^(BOOL finished){
[oldViewController.view removeFromSuperview];
if (dragBackgroundOffscreen)
[self.backgroundView removeFromSuperview];
[oldViewController willMoveToParentViewController:nil];
[oldViewController removeFromParentViewController];
[self.currentViewController didMoveToParentViewController:self];
}];
}
else if (direction == TransitionDirectionBackward)
{
if (dragBackgroundOnscreen){
[self.mainView addSubview:self.backgroundView];
[self.mainView sendSubviewToBack:self.backgroundView];
self.backgroundView.frame = offScreenLeft;
}
self.currentViewController.view.frame = offScreenLeft;
[UIView animateWithDuration:0.65
animations:^{
oldViewController.view.frame = offScreenRight;
if (dragBackgroundOffscreen)
self.backgroundView.frame = offScreenRight;
else if (dragBackgroundOnscreen)
self.backgroundView.frame = onScreen;
self.currentViewController.view.frame = onScreen;
}
completion:^(BOOL finished){
[oldViewController.view removeFromSuperview];
if (dragBackgroundOffscreen)
[self.backgroundView removeFromSuperview];
[oldViewController willMoveToParentViewController:nil];
[oldViewController removeFromParentViewController];
[self.currentViewController didMoveToParentViewController:self];
}];
}
I also want the background (self.backgroundView) to remain static unless moving to a screen that has its own background (i.e. I dont want the background to slide if the new views background is the same background).
I am using TransitionDirectionBackward and TransitionDirectionForward just to differentiate between sliding left and sliding right.
Everything works great, except when transitioning involves a GMGridView. the problem when the Gridviews frame is set to an offscreen frame its really setting its currently selected page's frame to that offscreen frame. Other pages of the gridview are not bounded by this frame, so they can appear on screen even before the transition. I tried setting the frame and bounds property on the GridView's viewcontroller's view, but I can still get a page of the gridview appearing onscreen before the transition animation.
Anyone see a solution to this? I was trying to find a way to clip the view of the GridView during the transition so pages dont appear except for the currently selected page, but havent found anything useful.
UPDATE: I found a possible fix by setting alpha = 0.0 for cells that are visible but shouldnt be (later setting alpha = 1.0 when the transition animation is complete). However, I need to know which cells to do this for. I need a way to access the page that the GMGridView is currently on so I can set the adjacent page's cells to have an alpha of 0.0.
UPDATE: Found a way to get it to work by using myGridView convertPoint:(A cgpoint i found by trial and error to be on the first cell of a page.) fromView:myGridView.window. NOTE: I needed an if/else if to check if i was in lanscape left or landscape right since the window coordinates do not rotate when the device is rotated. with this i was able to get the index of the cell at the point on the screen i had specified and then set the previous page to be transparent until after the transition animation.
I would still like to know if there is a way of "clipping" the gridview so that if the cells could be opaque, but just never displayed....?
I think I over complicated the problem. I was looking for the clipsToBounds method of a UIView (although I could have sworn I tried that before). In any case, its working now!

How to enlarge dynamically an UILabel (label and font size)?

Im currently working on an iPhone project. I want to enlarge dynamically an UILabel in Objective-C like this:
alt text http://img268.imageshack.us/img268/9683/bildschirmfoto20100323u.png
How is this possible? I thought I have to do it with CoreAnimation, but I didn't worked. Here is the code I tried:
UILabel * fooL = //[…]
fooL.frame = CGRectMake(fooL.frame.origin.x, fooL.frame.origin.y, fooL.frame.size.width, fooL.frame.size.height);
fooL.font = [UIFont fontWithName:#"Helvetica" size:80];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.5];
[UIView setAnimationBeginsFromCurrentState:YES];
fooL.font = [UIFont fontWithName:#"Helvetica" size:144]; //bigger size
fooL.frame = CGRectMake(20 , 44, 728, 167); //bigger frame
[UIView commitAnimations];
The problem with this code is that it doesn't change the fontsize dynamically.
All you need to do is apply an affine transform to the UILabel object.
CGFloat scaleFactor = 2.0f;
label.transform = CGAffineTransformMakeScale(scaleFactor, scaleFactor); // Enlarge by a factor of 2.
Scaling your label as suggested by others using the transform property will work great. One thing to keep in mind is that as the label gets larger, the font is not increasing, but just the rendered text, which means it will appear "fuzzier" as it gets larger.
Just scale your Label instead of changing the fontSize.
Try this method:
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition
forView:(UIView *)view
cache:(BOOL)cache
Parameters:
transition
A transition to apply to view. Possible values are described in UIViewAnimationTransition.
view
The view to apply the transition to.
cache
If YES, the before and after images of view are rendered once and used to create the frames in the animation. Caching can improve performance but if you set this parameter to YES, you must not update the view or its subviews during the transition. Updating the view and its subviews may interfere with the caching behaviors and cause the view contents to be rendered incorrectly (or in the wrong location) during the animation. You must wait until the transition ends to update the view.
If NO, the view and its contents must be updated for each frame of the transition animation, which may noticeably affect the frame rate.
Discussion
If you want to change the appearance of a view during a transition—for example, flip from one view to another—then use a container view, an instance of UIView, as follows:
Begin an animation block.
Set the transition on the container view.
Remove the subview from the container view.
Add the new subview to the container view.
Commit the animation block.