When I press my textfield, the keyboard hides it. So I have implemented this code to "scroll" the view up:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField: textField up: YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField: textField up: NO];
}
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
The UIView I'm trying to do this on is in another nib. I think since I have two UIViews, the program is getting confused and doesn't know which one to set the animation to.
I don't get any errors, but the animation isn't happening.
I've declared the UIView "surveyPage" for the view I'm trying to animate. Is there somewhere in the code above where I have to specify the UIView I want to animate?
Update:
The suggestion below didn't work for me. I tried changing self.view to surveyPage.
Above the code I posted above, I have this in my program:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
The above code works without a problem, yet the animation does not.
You're specifying the UIView here:
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
it's self.view.
Try:
[UIView animateWithDuration:movementDuration animations:^{
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
}];
instead of
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
Related
I have set up some text fields and labels to look like a simple form which will have to get some user input. My problem is however that whenever some of the text fields are selected and the keyboard slides out, the text fields are covered making it impossible to see the input. My question is how can I move up the text fields so that they stay in view when selected. Maybe someone who is more experienced can help me on this.
A good solution for this which I like to do is listen to when the textfield begins editing with the following delegate function:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
//keep a member variable to store where the textField started
_yPositionStore = textField.frame.origin.y;
//If we begin editing on the text field we need to move it up to make sure we can still
//see it when the keyboard is visible.
//
//I am adding an animation to make this look better
[UIView beginAnimations:#"Animate Text Field Up" context:nil];
[UIView setAnimationDuration:.3];
[UIView setAnimationBeginsFromCurrentState:YES];
commentTextField.frame = CGRectMake(commentTextField.frame.origin.x,
160 , //this is just a number to put it above the keyboard
commentTextField.frame.size.width,
commentTextField.frame.size.height);
[UIView commitAnimations];
}
and then in this callback you can return it to its original location:
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView beginAnimations:#"Animate Text Field Up" context:nil];
[UIView setAnimationDuration:.3];
[UIView setAnimationBeginsFromCurrentState:YES];
commentTextField.frame = CGRectMake(commentTextField.frame.origin.x,
_yPositionStore ,
commentTextField.frame.size.width,
commentTextField.frame.size.height);
[UIView commitAnimations];
}
}
You will need to declare _yPositionStore as a member variable of CGFloat and have your textFields delegate be set to the view controller that owns it(either using Interface builder and dragging delegate to files owner or setting yourTextField.delegate = self)
I hope that helps
Do do this you need to follow next 2 steps:
- put all your UITextViews into UIScrollView
- register for keyboard notifications and slide your UIScrollView when keyboard appears
Both steps explained here: "Moving Content That Is Located Under the Keyboard"
You can call delegate methods of UITextfield and customize it according to requirement.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField: textField up: YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField: textField up: NO];
}
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
const int movementDistance = 110;
const float movementDuration = 0.3f;
int movement = (up ? movementDistance : -movementDistance);
[UIView beginAnimations: #"aimation" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
yourView.frame= CGRectOffset(yourView.frame,0, movement);
[UIView commitAnimations];
}
For my applications I use the following code assuming that keyboardHeight is 216 for portrait and 162 for landscape mode:
#pragma mark - textField delegate
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
// keyboard is visible, move views
CGRect myScreenRect = [[UIScreen mainScreen] bounds];
int keyboardHeight = 216;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35];
int needToMove = 0;
CGRect frame = self.view.frame;
if (textField.frame.origin.y + textField.frame.size.height + self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height > (myScreenRect.size.height - keyboardHeight)) {
needToMove = (textField.frame.origin.y + textField.frame.size.height + self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height) - (myScreenRect.size.height - keyboardHeight);
}
frame.origin.y = -needToMove;
[self.view setFrame:frame];
[UIView commitAnimations];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
// resign first responder, hide keyboard, move views
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35];
CGRect frame = self.view.frame;
frame.origin.y = 0;
[self.view setFrame:frame];
[UIView commitAnimations];
}
This formula takes into account the status bar, navigation bar and display size. And of course do not forget to set the delegate for your fields.
And with:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[[UIApplication sharedApplication] sendAction:#selector(resignFirstResponder) to:nil from:nil forEvent:nil];
}
you can hide the keyboard, when the user tap outside the field.
I am havng one textfield and two textViews...while writting something in 1 conrol the keyboard is poped up...but when I want to shift on another control my keyboard doesn't let me write as it covers the whole view...hw can I solve my problem?
you should move your view up, so that the keyboard doesnt cover the textfield/ textview. something like this...
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if (textField == *textFieldName*)
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.5];
[UIView setAnimationBeginsFromCurrentState:YES];
self.view.frame = CGRectMake(self.view.frame.origin.x, (self.view.frame.origin.y - 65.0), self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];
}
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if (textField == *textFieldName*)
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.5];
[UIView setAnimationBeginsFromCurrentState:YES];
self.view.frame = CGRectMake(self.view.frame.origin.x, (self.view.frame.origin.y + 65.0), self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];
}
}
and for the textView use:
- (void)textViewDidBeginEditing:(UITextView *)textView
and
- (void)textViewDidEndEditing:(UITextView *)textView
Use delegate functions provided for uitextview and uitextfiled ....
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
const int movementDistance = 150; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
[self animateTextField: textField up: YES];
}
- (void)textViewDidEndEditing:(UITextView *)textView{
[self animateTextField: textField up: NO];
}
you can shift your whole view up or just shift the controls (text field and text view) up .. or make your view scrollable so the user can scroll down while the keyboard is visible.
I have a textField which is at bottom of the screen. When I begin editing, the keyboard appears and hides the textField.
Can anyone suggest how to solve this?
Generally you would put your content in a scroll view and move your scroll view up when the keyboard appears. There are many tutorials out there so google them. Here is one of them.
You can use following code in two diffrent method, call it when editing began and end, to move your view up and down,(just change the valuew that is been subtracted in yourView.frame.origin.y-100 to adjust according to your need)
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.5];
yourView.frame = CGRectMake(yourView.frame.origin.x, yourView.frame.origin.y-100, yourView.frame.size.width, yourView.frame.size.height);
[UIView commitAnimations];
See this code snippet. And use one UIButton to dismiss UIKeyboard.
- (void) animateTextField: (UITextField *)textField up:(BOOL) up
{
const int movementDistance = 200;
const float movementDuration = 0.4f;
int movement = (up ? -movementDistance : movementDistance);
up ? (self.button.enabled= YES) : (self.button.enabled = NO);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
-(void)textFieldDidBeginEditing:(UITextField*) inTextField
{
[self animateTextField:mText up:YES];
[self addObservers];
}
- (void)addObservers
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textFieldDidChange:) name:#"UITextFieldTextDidChangeNotification" object:nil];
}
- (void)textFieldDidChange:(NSNotification*)aNotification
{
NSLog(#"TextField data=%#",mText.text);
}
- (IBAction) doneBtn:(id)sender
{
[mText resignFirstResponder ];
[self animateTextField:mText up:NO];
}
When you tap on textField keyboard up then your textField hide by it. so waht you need, you need to make your view up not keyboardresign is a solution. so for making you view up use
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField delegate for the logic. now see the code
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField.tag==1) //add tag to your textField to identify it
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.3];
CGRect viewFrame=self.view.frame;
viewFrame=sinViewFrame.size.height+100;
viewFrameorigin.y-=100; // as required
self.view.frame=viewFrame;
[UIView commitAnimations];
}
}
hope it helps you.
I use auto layout constraint to solve this problem. I hold constraint as a property, and play with it when keyboard appears / disappears. I simply move views above the textfield out of screen, and textfield to the top. After finishing edit, I move them by the constraint to their original position.
-(void)keyboardWillShow:(NSNotification*)notification{
[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{
self.topSpaceLayoutConstraint.constant = -150;
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
} completion:NULL];
}
-(void)keyboardWillHide:(NSNotification*)notification
{
[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{
self.topSpaceLayoutConstraint.constant = 10;
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
} completion:NULL];
}
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *topSpaceLayoutConstraint;
i am placing a tableview,textview,buttons in a view as like this.
when ever i click on the textview keypad hides textview.To animate up textview i am writing the code as fallows.
- (void) textViewDidBeginEditing:(UITextView *)textView {
[self animateTextField:textView up:YES];
}
- (void) textViewDidEndEditing:(UITextView *)textView {
[self animateTextField:textView up:NO];
}
- (void) animateTextField: (UITextView*) textView up: (BOOL) up {
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
But it does n't take any effect.
And To hide the keypad i am writing this code
-(void) touchesBegan :(NSSet *) touches withEvent:(UIEvent *)event {
[mytextview resignFirstResponder];
}
it is also does n't take any effect.
can any one please help me.
Thank u in advance.
For resigning keyboard;
Make a ToolBar with bar button and add an IBAction for this and set its y coordinate below the 480(screen hieght)
-(IBAction)hide
{
[mytextview resignFirstResponder];
}
and in viewWillAppear use
myTextView.inputAccessoryView=tlBar;
And add two notification in viewWillAppear for keyboard
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:#selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil];
and then use these methods for Animation
-(void) keyboardWillShow:(NSNotification *) note
{
if(isAnimate)
[self viewAnimateUpper];
}
-(void)viewAnimateUpper
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.3];
CGRect viewFrame=self.view.frame;
viewFrame.origin.y -=95;//according to you
self.view.frame=viewFrame;
[UIView commitAnimations];
}
-(void)viewAnimatedown
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.3];
CGRect viewFrame=self.view.frame;
viewFrame.origin.y +=95;//according to you
self.view.frame=viewFrame;
[UIView commitAnimations];
}
-(void) keyboardWillHide:(NSNotification *) note
{
if(isAnimate)
{
[self viewAnimatedown];
}
}
Edit:
use textviewShouldBegainEditing
and in this set a boolvariable to yes if your desired textView call this method
isAnimate=YES;
I didn't find a chance to see you view,since my browser says "The image cant be dispalyed,It contains errors."
So try the following options.
Chk whether you have set the delegate of the textField to the files owner.If you have set and still not working,please try the below one.Its like animating the entire view up and down on textedits.
Please make use of the below code.This works for me.What you have to do is double click the .xib file where you want to add text fields.The view along with a window containing file's owner,first responder and a view will also be opened.
Use cmd+shift+l to open the library and add another view.In your .h file add a IBOutlet for the view as IBOutlet UIView *secondview and map to the file's owner.
Now put the text fields whichever has to moved in the second view.Now the default view which will appear when open the .xib file will contain nothing.It will be blank and the controls whichever you have to display will be on the second view.
In the .m file add the second view to the main view as
[self.view addSubview:secondView];
and use this code by customizing the text field names as you wish.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
CGRect viewFrame = self.view.frame;
if(textField==textfield1)
{
[textfield1 resignFirstResponder];
[textfield2 becomeFirstResponder];
}
else if(textField== textfield2)
{
[textfield2 resignFirstResponder];
[textfield3 becomeFirstResponder];
}
else if(textField== textfield3)
{
[textfield3 resignFirstResponder];
[textfield4 becomeFirstResponder];
}
else if(textField== textfield4)
{
[textfield4 resignFirstResponder];
}
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect viewFrame = secondView.frame;
CGRect textFieldRect =[secondView.window convertRect:textField.bounds fromView:textField];
CGRect viewRect =[secondView.window convertRect:secondView.bounds fromView:secondView];
CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator =midline - viewRect.origin.y- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator =(MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction 1.0)
{
heightFraction = 1.0;
}
UIInterfaceOrientation orientation =[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
viewFrame.origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[secondView setFrame:viewFrame];
[UIView commitAnimations];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect viewFrame = secondView.frame;
viewFrame.origin.y +=animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[secondView setFrame:viewFrame];
[UIView commitAnimations];
}
Let me know does this worked.
I'd like a UIView to slide up from the bottom of the screen (and stay mid-screen) like a UIActionSheet. How can I accomplish this?
UPDATE:
I am using the following code:
TestView* test = [[TestView alloc] initWithNibName:#"TestView" bundle:nil];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
test.view.center = CGPointMake(160,100);
//test.view.frame = CGRectMake(0, 0, 160, 210);
[[[UIApplication sharedApplication] keyWindow] addSubview:test.view];
[UIView commitAnimations];
The view seems to be animating from the corner and appearing in the corner. How can I make it slide up from the bottom? Getting close!
Do what Matt did here, but just change the values and direction. I have code at home to do this from the bottom if you need it later (I'll update this post).
Link: http://cocoawithlove.com/2009/05/intercepting-status-bar-touches-on.html
Also, don't forget to take out the bit of code that shifts the main view downward (so instead the UIView just pops over top like an ActionSheet)
Updated with code:
This is what I use in one of my apps to show/hide a little "options" view:
- (void)toggleOptions:(BOOL)ViewHidden
{
// this method opens/closes the player options view (which sets repeat interval, repeat & delay on/off)
if (ViewHidden == NO)
{
// delay and move view out of superview
CGRect optionsFrame = optionsController.view.frame;
[UIView beginAnimations:nil context:nil];
optionsFrame.origin.y += optionsFrame.size.height;
optionsController.view.frame = optionsFrame;
[UIView commitAnimations];
[optionsController.view
performSelector:#selector(removeFromSuperview)
withObject:nil
afterDelay:0.5];
[optionsController
performSelector:#selector(release)
withObject:nil
afterDelay:0.5];
optionsController = nil;
}
else
{
optionsController = [[PlayOptionsViewController alloc] init];
//
// Position the options at bottom of screen
//
CGRect optionsFrame = optionsController.view.frame;
optionsFrame.origin.x = 0;
optionsFrame.size.width = 320;
optionsFrame.origin.y = 423;
//
// For the animation, move the view up by its own height.
//
optionsFrame.origin.y += optionsFrame.size.height;
optionsController.view.frame = optionsFrame;
[window addSubview:optionsController.view];
[UIView beginAnimations:nil context:nil];
optionsFrame.origin.y -= optionsFrame.size.height;
optionsController.view.frame = optionsFrame;
[UIView commitAnimations];
}
}
One way would be to use the present modal view controller on the view controller:
presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
For more info take a look at the UIViewController documentation.
EDIT: If you want a mid-screen view you'll need to animate it into position as #jtbandes has pointed out. I suggest also adding some candy to UIView animation block:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
myView.center = CGPointMake(x,y);
[UIView commitAnimations];
You can then move it again if you need to go full screen or dismiss it.
You'll have to move the view yourself, by setting its center or frame. I'll let you figure out what to set those to. But for the animation:
// set the view to its initial position here...
[UIView beginAnimations:nil context:NULL];
// move the view into place here...
[UIView commitAnimations];
Check out this post: http://blog.yetanotherjosh.com/post/33685102199/3-ways-to-do-a-vertical-transition-with
I'm going with the modal window approach.
Try this solution.... it works
#pragma mark - Date Selector View PresentModelView with Transparent ViewController
- (void) showModal:(UIView*) modalView {
CGRect rect=modalView.frame;
rect.origin=CGPointMake(0, 0);
self.tutorialView.frame=rect;
UIWindow *mainWindow = [(AppDelegate *)[UIApplication sharedApplication].delegate window];
CGPoint middleCenter;
middleCenter = CGPointMake(modalView.center.x, modalView.center.y);
CGSize offSize = [UIScreen mainScreen].bounds.size;
CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
modalView.center = offScreenCenter;
if ([[mainWindow subviews] containsObject:modalView]) {
[modalView removeFromSuperview];
}
[mainWindow addSubview:modalView];
[mainWindow bringSubviewToFront:modalView];
// Show it with a transition effect
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
// animation duration in seconds
modalView.center = middleCenter;
[UIView commitAnimations];
}
// Use this to slide the semi-modal view back down.
- (void) hideModal:(UIView*) modalView {
CGSize offSize = [UIScreen mainScreen].bounds.size;
CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
[UIView beginAnimations:nil context:(__bridge void *)(modalView)];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(hideModalEnded:finished:context:)];
modalView.center = offScreenCenter;
[UIView commitAnimations];
}
- (void) hideModalEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIView *modalView = (__bridge UIView *)context;
[modalView removeFromSuperview];
}