I am having a custom cell in my tableview, when showing keyboard some of my cell gets hidden behind the keyboard.
To fix this issue I have tried as below
- (void) textFieldDidBeginEditing:(UITextField *)textField {
CustomCell *cell = (CustomCell*) [[textField superview] superview];
NSIndexPath *indexPath = [self.mySmlMsgTemplatesTbl indexPathForCell:cell];
[self.mySmlMsgTemplatesTbl scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
// [self.mySmlMsgTemplatesTbl scrollToRowAtIndexPath:[self.mySmlMsgTemplatesTbl indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
But it seems to be not working.
You should try following code as I have shown below. I didn't try it but it should work.
- (void)textFieldDidBeginEditing:(UITextField *)textField{
CGPoint point = [self.tableView convertPoint:yourtextview.bounds.origin fromView:yourtextview];
NSIndexPath* path = [self.tableView indexPathForRowAtPoint:point];
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
If it is the last cell for example, this won't work. The tableview can't scroll that far up. You will need to resize the tableview frame or use it's contentInset property to resize it.
There is another way. You could try to move the whole view up and down.
Hope this will help
#define kOFFSET_FOR_KEYBOARD 200.0
- (BOOL)textFieldShouldBeginEditing:(UITextField*)textField {
[txtField addTarget:self action:#selector(setViewMovedUp:)forControlEvents:UIControlEventEditingDidBegin];
[txtField addTarget:self action:#selector(setViewMovedDown:)forControlEvents:UIControlEventEditingDidEndOnExit];
}
-(void)setViewMovedUp:(id)sender
{
if (isKeyboardAppeared) {
return;
}
isKeyboardAppeared = YES;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3]; // if you want to slide up the view
CGRect rect = self.view.frame;
rect.origin.y -= kOFFSET_FOR_KEYBOARD;
rect.size.height += kOFFSET_FOR_KEYBOARD;
self.view.frame = rect;
[UIView commitAnimations];
}
-(void)setViewMovedDown:(id)sender
{
[self actionSaveRegistration];
if (!isKeyboardAppeared) {
return;
}
isKeyboardAppeared = NO;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect rect = self.view.frame;
rect.origin.y += kOFFSET_FOR_KEYBOARD;
rect.size.height -= kOFFSET_FOR_KEYBOARD;
self.view.frame = rect;
[UIView commitAnimations];
}
i do this type of app you just need the textFieldname or textfield tag ..and you can pgive the tag to textField with visiblecell...
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField.tag==3)
{
tableview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y-40,tableview.frame.size.width , tableview.frame.size.height+40);
}
else if(textField.tag==4)
{
tableview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y-40,tableview.frame.size.width , tableview.frame.size.height+40);
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if(textField.tag==3)
{
tableview.frame=CGRectMake(0,0, 320,460);
//tableview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y+70,tableview.frame.size.width , tableview.frame.size.height-70);
}
else if(textField.tag==4)
{
tableview.frame=CGRectMake(0,0, 320,460);
//tableview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y+70,tableview.frame.size.width , tableview.frame.size.height-70);
}
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
if(textField.tag==3)
{
tableview.frame=CGRectMake(0,0, 320,460);
//scrollview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y+70,tableview.frame.size.width , tableview.frame.size.height-70);
}
else if(textField.tag==4)
{
tableview.frame=CGRectMake(0,0, 320,460);
//tableview.frame=CGRectMake(scrollview.frame.origin.x, tableview.frame.origin.y-70,tableview.frame.size.width , tableview.frame.size.height+70);
}
}
i use here scrollView for Registration form here not a perfect code which you want but i think you can get idea from this code...
Hope,this help you..
:)
Related
i have an nsarray of textfields and another of textarea. I have also a toolbar with next and previous button to manage navigation between my fields. I made a fonction in textfieldDidBeginEditing and another in textfieldDidEndEditing but it didn't work correctly.
my function is :
if (textField.frame.origin.y > 180) {
[UIScrollView beginAnimations:nil context:NULL];
[UIScrollView setAnimationDelegate:self];
[UIScrollView setAnimationDuration:0.4];
[UIScrollView setAnimationBeginsFromCurrentState:YES];
CGFloat updatedY = 150;
self.scrollView.frame = CGRectMake(self.scrollView.frame.origin.x,self.scrollView.frame.origin.y - updatedY, self.scrollView.frame.size.width,
self.scrollView.frame.size.height);
[UIScrollView commitAnimations];
}
Any help will be appreciated.
I think you want Keyboard handler. The one I am using is a very good keyboard handler.
Keyboard Handler by Sukhpal Singh
This is a very good tutorial from one of my good friend and You can use this.
For using this you just have to write a single line of code.
AutoScroller * scroller=[AutoScroller addAutoScrollTo:self.scrollView isDoneToolBarNeeded:NO];
yes its done.
Please try to use this one
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:.30];
[self scrollViewToCenterOfScreen:textView];
[UIView commitAnimations];
return YES;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:.30];
[self scrollViewToCenterOfScreen:textField];
[UIView commitAnimations];
return YES;
}
- (void)scrollViewToCenterOfScreen:(UIView *)theView
{
CGFloat y ;
CGFloat viewCenterY = theView.center.y;
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
CGFloat avaliableHeight = applicationFrame.size.height - 250;
y = viewCenterY - avaliableHeight / 2.0f;
if (y < 0)
{
y = 0;
}
[scrollView setContentOffset:CGPointMake(0, y)];
}
try this code:
- (void)textFieldDidBeginEditing:(UITextField *)textField;
{
[clientscrollview setContentOffset:CGPointMake(0, textField.center.y-180) animated:YES];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[clientscrollview setContentOffset:CGPointMake(0, 0) animated:YES];
[textField resignFirstResponder];
return YES;
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
[clientscrollview setContentOffset:CGPointMake(0,textView.center.y-180) animated:YES];
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
[clientscrollview resignFirstResponder];
[clientscrollview setContentOffset:CGPointMake(0,0) animated:YES];
}
In my didSelectRowAtIndexPath method I call [self dismissView]; when the user selects a cell in order to dismiss the view if its already been presented. This clearly isn't very optimal and its overriding the presentView method without it animating the dismissView. Is there a better way to do this? Or at the very least let it wait for the view to finish animating without using NSTimer.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
[self dismissView];
// Do xyz...
[self presentView:twitterLinksView];
Then..
- (void)presentView:(id)sender
{
twitterLinksView.frame = CGRectMake(0, (self.view.frame.size.height + viewHeight), 320, 300);
[UIView animateWithDuration:0.60f animations:^{
CGRect twitterLinkFrame = self.twitterLinksView.frame;
twitterLinkFrame.origin.y = (self.view.frame.size.height - viewHeight);
twitterLinksView.frame = twitterLinkFrame;
}];
}
- (void)dismissView
{
[UIView animateWithDuration:0.75f animations:^{
CGRect twitterLinkFrame = self.twitterLinksView.frame;
twitterLinkFrame.origin.y = (self.view.frame.size.height + viewHeight);
self.twitterLinksView.frame = twitterLinkFrame;
}];
}
[UIView animateWithDuration:1. animations:^{
//firstAnimationBlock
} completion:^(BOOL finished){
[UIView animateWithDuration:1. animations:^{
//animations in this block will be called after firstAnimationBlock has expired
}];
}];
as i understand you wanna fire 2 animation one after the other. this code (block inside block) makes this
this part is after edit:
ok now you can try writing like that
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
[self dismissView];
// Do xyz...
[self performSelector:#selector(presentView:) withObject:twitterLinksView afterDelay:0.75];
//[self presentView:twitterLinksView];
}
I ended up splitting out my creation method and using [[self.view subviews] containsObject:twitterLinksView] to check for the view. Also to be noted is [self performSelector:#selector(createView) withObject:twitterLinksView afterDelay:0.76f] had to be very slightly ahead of the dismissing animation for it to work at all... yeah wtf.
In the didSelectRowAtIndexPath method i used [self performSelector:#selector(presentView:)];
Thanks to meth for solving part of the puzzle.
- (void)presentView:(id)sender
{
if ([[self.view subviews] containsObject:twitterLinksView])
{
[self dismissView];
[self performSelector:#selector(createView) withObject:twitterLinksView afterDelay:0.76f];
NSLog(#"Animating ut old");
}
else
{
NSLog(#"Creating new view");
[self createView];
}
}
-(void)createView
{
twitterLinksView.frame = CGRectMake(0, (self.view.frame.size.height + viewHeight), 320, 300);
[UIView animateWithDuration:0.60f animations:^{
CGRect twitterLinkFrame = self.twitterLinksView.frame;
twitterLinkFrame.origin.y = (self.view.frame.size.height - viewHeight);
twitterLinksView.frame = twitterLinkFrame;
[self.view addSubview:twitterLinksView];
}];
}
- (void)dismissView
{
[UIView animateWithDuration:0.75f animations:^{
CGRect twitterLinkFrame = self.twitterLinksView.frame;
twitterLinkFrame.origin.y = (self.view.frame.size.height + viewHeight);
self.twitterLinksView.frame = twitterLinkFrame;
}completion:^(BOOL finished){
[twitterLinksView removeFromSuperview];
}];
}
I have 2 textview one is on top and other is at bottom. When I am trying to write something on bottom textview keyboard is coming on screen and I am not able to see what I am typing.
How to make keyboard invisible or placed on perfect place while typing below textview?
- (void)textViewDidBeginEditing:(UITextView *)textView {
if (textView == bottomTextView) {
CGRect frame = self.view.frame;
frame.origin.y -= 250;
self.view.frame = frame;
}
}
- (void)textViewDidEndEditing:(UITextView *)textView {
if (textView == bottomTextView) {
CGRect frame = self.view.frame;
frame.origin.y += 250;
self.view.frame = frame;
}
}
You can modify this 250 value.
The Answer to your problem lies here buddy..
Sliding UITextFeilds when keyboard appears
Its Best solution available.
Write This Delegate Methods For TextField
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if (textField == txtUserName) {
[txtUserName becomeFirstResponder];
[scrollView setContentOffset:CGPointMake(0,45) animated:YES];
} else if (textField == txtPassword) {
[txtPassword becomeFirstResponder];
[scrollView setContentOffset:CGPointMake(0,105) animated:YES];
}
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
[scrollView setContentOffset:CGPointMake(0,0) animated:YES];
return YES;
}
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 have a UITableView, which I am controlling from a custom UIViewController. When the user clicks the 'add' button, I add a row to the UITableView with a text field in it, and make it the first responder. The problem is, when the bottom of the table is out of view (or hidden by the keyboard), the UITableView doesn't scroll to bring the text field into view.
UITableViewController does this automatically, but my View Controller can't be a subclass of UITableViewController.
I fixed this by twiddling contentInset on the UITableView when the keyboard appears or disappears.
- (void)registerForKeyboardNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification object:nil];
}
- (void)keyboardWasShown:(NSNotification *)aNotification {
CGRect keyboardBounds;
[[aNotification.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &keyboardBounds];
keyboardHeight = keyboardBounds.size.height;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardBounds.size.height, 0);
[UIView commitAnimations];
[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[items count] inSection:0]
atScrollPosition:UITableViewScrollPositionMiddle
animated:YES];
}
- (void)keyboardWasHidden:(NSNotification *)aNotification {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
tableView.contentInset = UIEdgeInsetsZero;
[UIView commitAnimations];
}
call registerForKeyboardNotifications when you load the UITableView, and everything else should Just Work.
I found -scrollToRowAtIndexPath:atScrollPosition:animated: and guess this would do what you want.
I faced a similar problem, here's my soln: http://www.passiondeveloper.com/discussion/8/uitableview-inline-editing-with-a-textfield-inside-uitableview-not-scrolling-when-keyboard-is-shown
work for ios5
UITextField *activeField;
// Called when the UIKeyboardDidShowNotification is sent.
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWasShown:(NSNotification *)aNotification {
id view = [activeField superview];
while (view && ![view isKindOfClass:[UITableViewCell class]])
{
view = [view superview];
}
UITableViewCell *cell = view;
NSIndexPath *indexPath = [tableview indexPathForCell:cell];
CGRect keyboardBounds;
[[aNotification.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &keyboardBounds];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
tableview.contentInset = UIEdgeInsetsMake(0, 0, keyboardBounds.size.height, 0);
[UIView commitAnimations];
[tableview scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (void)keyboardWasHidden:(NSNotification *)aNotification {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
tableview.contentInset = UIEdgeInsetsZero;
[UIView commitAnimations];
}