in my table I use cells with UITextField as subview. I also can edit it but only for the upper cells in the table I also see, what I edit, because the keyboard hides the lower cells.
Now what must I do, to scroll the cell I whant to edit move to the top?
I tried
selectRowAtIndexPath:indexPathOfCurrrentCell animated:NO scrollPostion:UITableViewSchrollPositionTop
and
scrollToRowAtIndexPath:idexPathOfCurrentCell atScrollPosition:UITableViewSchrollPositionTop animated:NO
but none of it works. Must I use an other command or add something additional? What must I change?
Thanks
If you can't manually scroll the tableView to somewhere where the cell is visible; the code won't either.
The solution is to set the frame of the tableView to have a height that respects the keyboard's height of 170 points.
You could try something like this:
tableView.frame = CGRectMake(tableView.frame.origin.x, tableView.frame.origin.y, tableView.frame.size.width, tableView.frame.size.height-170);
Do this in your method which gets called when the textField becomes the first responder.
Take a look at this post. I think you'll find what you need.
Get UITableView to scroll to the selected UITextField and Avoid Being Hidden by Keyboard
Use Delegate Method of UITextField
Even I encountered this scrolling problem and i use the below logic to get rid of this.
This Works fine
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
if (textField==textFieldOfYourInterest )
{
CGRect frame = self.view.frame;
if ([textField isFirstResponder] && self.view.frame.origin.y >= 0)
{
frame.origin.y -= 70;
}
else if (![textField isFirstResponder] && self.view.frame.origin.y < 0)
{
frame.origin.y += 70;
}
[self.view setFrame:frame];
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
CGRect frame = self.view.frame;
if (![topTextFieldName isFirstResponder] && self.view.frame.origin.y < 0)
{
frame.origin.y += 70;
}
[self.view setFrame:frame];
NSLog(#"text field should return");
[textField resignFirstResponder];
return YES;
}
If any problem revert to me.
Thanks
Nagaraja Sathe
Related
I've a viewController composed by an UIImageView that fills the whole view and two textField located at the center of the view. All this is located inside a ScrollView.
I use Storyboard and I disabled the autolayout.
When I click on a textField, and thus opens the keyboard, I'd like that the scroll is displaced directly on textField. How can I do that?
Consider that your TextField outlet is named txtField then implement UITextField Delegate using
txtField.delegate = self;
Considering that your ScrollView outlet is named scrollView. Implement the Textfield Delegate method:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(#"%#",NSStringFromCGRect(textField.frame));
[scrollView scrollRectToVisible:textField.frame animated:YES];
}
Hope this helps.
Do let me know if you need more help.
I usually use this successfully:
http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
Add your controller as an observer of the keyboard notifications. When you receive the notification, resize the scroll view frame and / or set the content offset (depending on the exact effect you want and content size you have).
Here are several options that I've used before:
Apple's Doco. See the section titled Moving Content That Is Located Under the Keyboard
Cocoa With Love article, Sliding UITextFields around to avoid the keyboard
If you have several text fields or other form elements in your view, you could alternatively use something like EZForm. It does automatic repositioning of views to keep input fields visible, and also handles input validation and other useful form-related stuff.
You can convert the text field coordinate system into Scroll view coordinate system. Use the below code
-(void)rearrangeView{
// previous
if (txtActiveField == txtUsername) {
CGPoint pt;
CGRect rc = [txtUsername bounds];
rc = [txtUsername convertRect:rc toView:scrollViewLogin];
pt = rc.origin;
pt.x = 0;
pt.y -= 40;
[scrollViewLogin setContentOffset:pt animated:YES];
}
else if (txtActiveField == txtPassword) {
// [self.txtEmail becomeFirstResponder];
CGPoint pt;
CGRect rc = [txtPassword bounds];
rc = [txtPassword convertRect:rc toView:scrollViewLogin];
pt = rc.origin;
pt.x = 0;
pt.y -= 40;
[scrollViewLogin setContentOffset:pt animated:YES];
}
}
#pragma mark- UITextField Delegate
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
txtActiveField = textField;
//txtActiveField.placeholder = #"";
[self rearrangeView];
return YES;
}
Here txtActiveField is instance variable of type UItextField
I have an app where you have textfields and one textview but when I get the keyboard it hides the lower textfields. How would I do it.
I have tried:
.m:
- (void)textFieldDidBeginEditing:(UITextField *)sender {
CGSize content = _scrollView.contentSize;
_scrollView.contentSize = CGSizeMake(content.width, content.height + 200);
svos = _scrollView.contentOffset;
CGPoint pt;
CGRect rc = [sender bounds];
rc = [sender convertRect:rc toView:_scrollView];
pt = rc.origin;
pt.x = 0;
pt.y -= 200;
[_scrollView setContentOffset:pt animated:YES];
}
- (IBAction)textFieldShouldReturn:(UITextField *)textField {
CGSize content = _scrollView.contentSize;
_scrollView.contentSize = CGSizeMake(content.width, content.height - 200);
[_scrollView setContentOffset:svos animated:YES];
[textField resignFirstResponder];
}
.h:
CGPoint svos;
Although the bottom text fields are still hidden it does scroll to the visible ones
You have obtained the origin of the sender textfield but only move up by 60, thus, the lower textfields are covered by the keyboard. You will need to know the height of the keyboard and calculate the distance to move up. Check this out. It has much of the answer so I will not explain again.
To scroll to the bottom textfield inside a scrollview, add these lines in textFieldDidBeginEditing:
CGSize content = _scrollview.contentSize;
_scrollview.contentSize = CGSizeMake(content.width, content.height + 200);
This will extend your contentSize programmatically so you can scroll to the last textfield and allow the keyboard to cover the empty space.
In textFieldDidEndEditing or textFieldShouldReturn, in your case, add these:
CGSize content = _scrollview.contentSize;
_scrollview.contentSize = CGSizeMake(content.width, content.height - 200);
I used an arbitrary 200 as example. You will need to figure out how much you want.
A drop-in universal solution for moving text fields out of the way of the keyboard in iOS
https://github.com/michaeltyson/TPKeyboardAvoiding
It works perfect for me.
Simply you need to copy the required classes(TPKeyboardAvoidingScrollView or TPKeyboardAvoidingTableView) in your project and in your interface builder file you have to change the UIScrollView class to TPKeyboardAvoidingScrollView or UITableView to TPKeyboardAvoidingTableView, the remaining things will be handled by these classes.
Have you seen the documentation about managing the keyboard? (apple documentation) There is an example of what i think you are working on. Hope it helps.
How can I scroll my UITextView programmatically when user enters each line.
It is necessary for my textView since keypad hides it at some point as shown below.
I searched lot, but didn't found any appropriate solution, as I am a newbie to iPhone development. I need your valuable help.
when you are opening the keyboard, you should adjust the frame of your textview. In this case reduce the height of your frame by the height of keyboard.
Implement proper code for these two delegate methods.
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
CGRect frm = textView.frame;
frm.height -= KEY_BOARD_HEIGHT;
textView.frame = frm;
}
- (BOOL)textViewShouldEndEditing:(UITextView *)textView;
{
CGRect frm = textView.frame;
frm.height += KEY_BOARD_HEIGHT;
textView.frame = frm;
}
Take a variable for Scrolling position :: int scrollY;
Code for TextView ::
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if ([text isEqualToString:#"\n"])
{
scrollY += 10;
scrMain.contentOffset = CGPointMake(0, scrollY);
}
return YES;
}
Then, when user resign from keyboard, set it to again 0 and scroll to its origin position.
scrollY = 0;
scrMain.contentOffset = CGPointMake(0, 0);
Hope, it may help you.
Thanks.
UITextView scroll text automatically when enter text, you only change UITextView frame to above keyboard and when you dismiss key board reset UITextView frame
- (void)textViewDidBeginEditing:(UITextView *)textView
{
//set frame for text view here
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
//set frame for text view here
}
I'm having a peculiar problem. I have a view with two UITextFields that start out 280px wide. On focus, I want them to shorten to reveal a button - I'm doing that with the following code:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect revealButton = CGRectMake(textField.frame.origin.x, textField.frame.origin.y, 221, textField.frame.size.height);
[UIView beginAnimations:nil context:nil];
textField.frame = revealButton;
[UIView commitAnimations];
NSLog(#"%f",textField.frame.size.width);
}
Once editing has ended, they should go back to their original frame:
- (void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect hideButton = CGRectMake(textField.frame.origin.x, textField.frame.origin.y, 280, textField.frame.size.height);
[UIView beginAnimations:nil context:nil];
textField.frame = hideButton;
[UIView commitAnimations];
}
The first time I focus a text field, it works perfectly. However, if I focus the first text field after focusing something else (for example, if I focus the first text field initially, focus the second, and then refocus the first, or if I initially focus the second and then focus the first), it simply won't change its frame. Even more puzzling is the fact that it will log 221 as its width - it just won't show that on the screen. Furthermore, this problem doesn't apply to the second text field.
Any ideas? Thanks in advance...
That's strange, I ran a quick test using two text fields with the exact same code and works every time.
I'd suggest deleting the text fields and connections and rebuild them. Clean all targets and try again.
Edit according to your comments:
If you're using Auto Layout you must not modify the frame of the text fields directly. The actual frames of UI elements are calculated by the system.
For your purpose I'd suggest to set up a width constraint for every text field. Make sure that you only have a left or right spacing constraint not both in addition to the width constraint. To animate it use the following code:
- (NSLayoutConstraint *)widthConstraintForView:(UIView *)view
{
NSLayoutConstraint *widthConstraint = nil;
for (NSLayoutConstraint *constraint in textField.constraints)
{
if (constraint.firstAttribute == NSLayoutAttributeWidth)
widthConstraint = constraint;
}
return widthConstraint;
}
- (void)animateConstraint:(NSLayoutConstraint *)constraint toNewConstant:(float)newConstant withDuration:(float)duration
{
[self.view layoutIfNeeded];
[UIView animateWithDuration:duration animations:^{
constraint.constant = newConstant;
[self.view layoutIfNeeded];
}];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
float newWidth = 221.0f;
NSLayoutConstraint *widthConstraint = [self widthConstraintForView:textField];
[self animateConstraint:widthConstraint toNewConstant:newWidth withDuration:0.5f];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
float newWidth = 280.0f;
NSLayoutConstraint *widthConstraint = [self widthConstraintForView:textField];
[self animateConstraint:widthConstraint toNewConstant:newWidth withDuration:0.5f];
}
I'm using a UITextView to roughly replicate the SMS text box above the keyboard. I'm using a UITextView instead of a field so that it can expand with multiple lines.
The problem is that, in my UITextView, the correction suggestions pop up below the text, causing them to be partially obscured by the keyboard.
In the SMS app, the suggestions pop up above the text. The placement does not appear to be a property of UITextView, or UITextInputTraits.
Any idea how to replicate this behavior? Thanks!
The problem is that the Keyboard is implemented as a separate UIWindow, rather than as a view within the main UIWindow, so layout with it is tricky. Here are some pointers in the right direction:
Hunt through the application's -windows property to find the private UITextEffectsWindow window and figure out its frame. This is the keyboard
Hunt through the TextView's subviews to find the private UIAutocorrectInlinePrompt view. This is the autocorrect bubble.
Move that subview into a separate wrapper view (added to the TextView) and then move that wrapper view so it's above the above-mentioned keyboard window.
You'll notice two mentions of "private" above. That carries all the relevant caveats. I have no idea why Apple has allowed the problem to persist when even their apps have had to work around it.
By doing the search for the UIAutocorrectInlinePrompt in an overridden or swizzled layoutSubViews it is possible to alter the layout of the correction so that it appears above. You can do this without calling any private APIs by looking for the subs views of particular classes positioned in a way you'd expect them. This example works out which view is which, checks to see that the correction is not already above the text and moves the correction above, and draws it on the window so that it is not bounded by the UITextView itself. Obviously if apple change the underlying implementation then this will fail to move correction. Add this to your overriden or swizzled layoutSubViews implementation.
- (void) moveSpellingCorrection {
for (UIView *view in self.subviews)
{
if ([[[view class] description] isEqualToString:#"UIAutocorrectInlinePrompt"])
{
UIView *correctionShadowView = nil; // [view correctionShadowView];
for (UIView *subview in view.subviews)
{
if ([[[subview class] description] isEqualToString:#"UIAutocorrectShadowView"])
{
correctionShadowView = subview;
break;
}
}
if (correctionShadowView)
{
UIView *typedTextView = nil; //[view typedTextView];
UIView *correctionView = nil; //[view correctionView];
for (UIView *subview in view.subviews)
{
if ([[[subview class] description] isEqualToString:#"UIAutocorrectTextView"])
{
if (CGRectContainsRect(correctionShadowView.frame,subview.frame))
{
correctionView = subview;
}
else
{
typedTextView = subview;
}
}
}
if (correctionView && typedTextView)
{
CGRect textRect = [typedTextView frame];
CGRect correctionRect = [correctionView frame];
if (textRect.origin.y < correctionRect.origin.y)
{
CGAffineTransform moveUp = CGAffineTransformMakeTranslation(0,-50.0);
[correctionView setTransform: moveUp];
[correctionShadowView setTransform: moveUp];
CGRect windowPos = [self convertRect: view.frame toView: nil ];
[view removeFromSuperview];
[self.window addSubview: view];
view.frame = windowPos;
}
}
}
}
}
}
Actually doing
textview.scrollEnabled = NO;
will set the bubble on top of the text... the caveat is that you lose scrolling, in my case it wasn't a problem due to havinng a textfield only for input purposes with character limit
Actually, the keyboard simply uses the result of -[UITextInput textInputView] to determine where to put the correction view (and to ask if your view supports correction). So all you need to do is this:
- (UIView *)textInputView {
for (UIWindow *window in [UIApplication sharedApplication].windows) {
if ([window isKindOfClass:NSClassFromString(#"UITextEffectsWindow")] &&
window != self.window) {
return window;
}
}
// Fallback just in case the UITextEffectsWindow has not yet been created.
return self;
}
Note that you'll likely also need to update -[UITextInput firstRectForRange:] to use the coordinate system of the window / device, so you can do this:
- (CGRect)firstRectForRange:(CoreTextTokenTextRange *)range {
CGRect firstRect = [self firstRectForRangeInternal:range];
return [self convertRect:firstRect toView:[self textInputView]];
}
(In the above context, self is a class that implements UITextInput).
If the bottom of your UITextView clears the keyboard, you should be able to just resize your UITextView to be tall enough to see the corrections. The corrections themselves don't display outside of the UITextView's frame.
If you want to mimic what you are getting in the SMS app (corrections above), you'll probably have to roll your own.
Putting the below method, adjustAutocorrectPromptView in layoutSubviews worked for me in portrait and landscape. I have a category that provides the bottom and top methods on view but you get the idea.
NSArray * subviewsWithDescription(UIView *view, NSString *description)
{
return [view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:#"class.description == '%#'", description]]];
}
- (void) adjustAutocorrectPromptView;
{
UIView *autocorrectPromptView = [subviewsWithDescription(self, #"UIAutocorrectInlinePrompt") lastObject];
if (! autocorrectPromptView)
{
return;
}
UIView *correctionShadowView = [subviewsWithDescription(autocorrectPromptView, #"UIAutocorrectShadowView") lastObject];
if (! correctionShadowView)
{
return;
}
UIView *typedTextView = nil; //[view typedTextView];
UIView *correctionView = nil; //[view correctionView];
for (UIView *subview in subviewsWithDescription(autocorrectPromptView, #"UIAutocorrectTextView"))
{
if (CGRectContainsRect(correctionShadowView.frame,subview.frame))
{
correctionView = subview;
}
else
{
typedTextView = subview;
}
}
if (correctionView && typedTextView)
{
if (typedTextView.top < correctionView.top)
{
correctionView.bottom = typedTextView.top;
correctionShadowView.center = correctionView.center;
}
}
}
Make sure your view controller delegate is listening to the notification when the keyboard pops up so that you resize your UITextView so that the keyboard doesn't obscure the UITextView. Then your correction won't be obscured by the keyboard. See:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/12641-uitextview-scroll-while-editing.html
Here is a copy of the code from that page in case the original link is broken:
// the amount of vertical shift upwards keep the Notes text view visible as the keyboard appears
#define kOFFSET_FOR_KEYBOARD 140.0
// the duration of the animation for the view shift
#define kVerticalOffsetAnimationDuration 0.50
- (IBAction)textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}
- (IBAction)backgroundClick:(id)sender
{
[latitudeField resignFirstResponder];
[longitudeField resignFirstResponder];
[notesField resignFirstResponder];
if (viewShifted)
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:kVerticalOffsetAnimationDuration];
CGRect rect = self.view.frame;
rect.origin.y += kOFFSET_FOR_KEYBOARD;
rect.size.height -= kOFFSET_FOR_KEYBOARD;
self.view.frame = rect;
[UIView commitAnimations];
viewShifted = FALSE;
}
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
if (!viewShifted) { // don't shift if it's already shifted
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:kVerticalOffsetAnimationDuration];
CGRect rect = self.view.frame;
rect.origin.y -= kOFFSET_FOR_KEYBOARD;
rect.size.height += kOFFSET_FOR_KEYBOARD;
self.view.frame = rect;
[UIView commitAnimations];
viewShifted = TRUE;
}
return YES;
}