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.
Related
I have a tableView with textFields inside of them, and I have animation that slides the tableView up when the textFieldDidBeginEditing method is called. Here is my code:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
self.headerView.alpha = 0.2;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.18];
[UIView setAnimationDelegate:self];
self.theTableView.frame = CGRectMake(0, 130, 320, 209);
[UIView commitAnimations];
}
The problem is that the animation happens whenever one of the cells is tapped, but I only want it to happen the first time a cell is tapped. So I was thinking that I should make an if statement that checks whether the tableView is at the (0, 130) coordinates. Does anyone know how I would do this?
For an exact comparison, CGPointEqualToPoint() will suffice. For a broader comparison (checking if the rect of the view contains the given point), CGRectContainsPoint() is perfect.
Of course, all of this is a little much. Subclass your view and keep a flag on it to track whether or not they've been slid up. Not only does it keep your code more self-contained, but it keeps the logic for the view out of your controller.
I am performing an animation to correctly keep the UITextView at the bottom of the screen if I expand the view. For some reason if I perform the animation, the UITextView stop responding to touch events, so there is no keyboard that will show up.
All I am doing is:
CGRect newSendTextView = self.commTextView.frame;
newSendTextView.origin.y = (newSendTextView.origin.y + (height - self.defaultSize.size.height));
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.5];
self.commTextView.frame = newSendTextView;
[UIView commitAnimations];
I know the UITextView is still on the screen after I do the transformation since I colored the UITextView background a bright blue, but it doesn't want to respond to any touch events.
If I comment out self.commTextView.frame = newSendTextView; so that it doesn't move, the touch events register.
I have no idea why this happens, I tried
[self.commTextView becomeFirstRespond];
and I have checked if isEditable and isUserInteractionEnabled is set to 1 and it is.
I guess, new position of TextView might be getting overlayed by other view. Check any other View is having same frame on your TextView new position. Use clipsToBounds property to find it.
- (void)viewDidLoad
{
[super viewDidLoad];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:4];
[UIView setAnimationRepeatCount:50];
[UIView setAnimationRepeatAutoreverses:NO];
CGPoint abc =chem1.center;
abc.y= 480;
chem1.center=abc;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:4];
[UIView setAnimationRepeatCount:50];
[UIView setAnimationRepeatAutoreverses:NO];
CGPoint def =chem2.center;
def.y= 480 ;
chem2.center=def;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:4];
[UIView setAnimationRepeatCount:50];
[UIView setAnimationRepeatAutoreverses:NO];
CGPoint hij =nat1.center;
hij.y= 480;
nat1.center=hij;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:4];
[UIView setAnimationRepeatCount:50];
[UIView setAnimationRepeatAutoreverses:NO];
CGPoint klm =nat2.center;
klm.y= 480;
nat2.center=klm;
}
I'd really appreciate the help
There are two parts to your question: how to tap an animated image and how to drag an image.
How to tap an animated image.
Background
When you are animating a view (or more accurately its layer) the property that you change (in your case the position (by setting center)) is changed to its final value right away. If you only animate (like with a CABasicAnimation, then the properly might not change at all.
This means that if you try to tap the view (or layer) it will be at the position that you moved it to (its final position (despite any duration or repeat count of the animation).
Hit test a moving layer
To be able to hit test something that is moving you need to hit test against the presentationLayer of the layer of the view that you are trying to tap.
CGPoint touchPoint = [gestureRecognizer locationInView:[self view]];
if ([[[[self movingView] layer] presentationLayer] hitTest:touchPoint]) {
// Yeah, you hit the moving (animating) layer!
}
Now that the user has tapped a moving view (image in your case) you can begin to handle the drag.
How to drag an image
When you are dragging an image you move the layer to wherever the users finger is dragging the image.
Remove to animation that moves the view
First you should cancel the ongoing animation for that view (having a name for the animation enables you to cancel only one animation.
[[[self movingView] layer] removeAllAnimations];
Or if you have set a name to the movement animation.
[[[self movingView] layer] removeAnimationForKey:#"nameOfMovingAnimation"];
Move the view to the location of the users finger
Next you should (continuously) update the position of the view as the user moves its finger. You should not animate this since it will increase the time between the movement of the finger and the view and will make it seem like your application is lagging. Animating while dragging does not make it look smooth.
Note: since your question doesn't say what you want to do once the user are dragging the images or what happens when they drop them. I can't go much further in the explanation.
Need more help?
Search the web (or StackOverflow) for something like: "iOS drag view" and you will probably find more information about how to drag your imageViews.
Otherwise ask another question on StackOverflow once you have gotten this far (i.e. you can tap on the moving images and they stop moving).
I have a grouped style UITableView on my navigation stack, and when I click on a cell, I push a UIDatePicker onto the stack. The problem is that I want this custom view to have the same background color as my table view.
I tried setting the background color of my custom view like:
datePicker.backgroundColor = [UIColor groupTableViewBackgroundColor];
But this comes out transparent. I also tried modifying the underlying CGColor object to have an alpha of 1.0, which caused the background color to be black.
The following does work as expected:
datePicker.backgroundColor = [UIColor lightGrayColor];
But, of course, this color doesn't quite match the grouped table background color.
Am I going about this all wrong? I found a similar post about this here, but no helpful response.
What do you mean you "push a UIDatePicker onto the stack"? Why dont you try animating the UIDatePicker into view?
when the view loads, create the picker and set the frame off screen, such as
[picker setFrame:CGRectMake(0,960,320,216)];
then instead of "pushing" the picker, animate it into view like:
[UIView beginAnimations:nil context:NULL];
[picker setFrame:CGRectMake(0,200,320,216)];
[UIView commitAnimations];
And when you want to dismiss the picker, just hide it like:
[UIView beginAnimations:nil context:NULL];
[picker setFrame:CGRectMake(0,960,320,216)];
[UIView commitAnimations];
If you need to, you can also add a toolbar with a "done" button to dismiss the picker, works great for me.
If the contents of the picker are going to be displayed on the table, then you can set the frame of the table in that animation sequence. in the first one, make the table half the size (like 150 for my example would work perfect), then in the hide sequence, make the table the original size (415 for this example). And when you hide the picker, call [tableView reloadData]; to refresh the table.
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.