Right now, I have basic code for moving the textfield above the keyboard when you start editing. However, the size of the textfield varies based on device and orientation. So, I wrote a crude way of doing it, which doesn't stay consistently right above the keyboard, but instead will go up further when you rotate it, and so it doesn't look as professional as I would like.
The basic sense of my question is if there is a logic for getting the size of the keyboard based on device and orientation and using that value automatically and hopefully faster than this.
If that is the best way, please let me know. Otherwise, please provide input. Here is the code that I have.
(This is just the move-up code, not the move down code, in order to prevent taking up too much space)
- (void)textFieldDidBeginEditing:(UITextField *)textField {
//Get Device Type
NSString *deviceType = [[UIDevice currentDevice] model];
//Animate Text Field
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.4];
[UIView setAnimationBeginsFromCurrentState:YES];
if ([deviceType isEqualToString:#"iPhone"]) {
//Size For iPhone
googleBar.frame = CGRectMake(googleBar.frame.origin.x - 62.0, (googleBar.frame.origin.y - 210.0), googleBar.frame.size.width + 120.0, googleBar.frame.size.height);
} else if ([deviceType isEqualToString:#"iPad"]) {
//Size for iPad
googleBar.frame = CGRectMake(googleBar.frame.origin.x - 62.0, (googleBar.frame.origin.y - 320.0), googleBar.frame.size.width + 120.0, googleBar.frame.size.height);
} else if ([deviceType isEqualToString:#"iPod touch"]) {
//Size For iPod Touch
googleBar.frame = CGRectMake(googleBar.frame.origin.x - 62.0, (googleBar.frame.origin.y - 210.0), googleBar.frame.size.width + 120.0, googleBar.frame.size.height);
}
[UIView commitAnimations];
}
What you really want to do is observe the UIKeyboard(Did|Will)(Show|Hide) notifications. They contain in their userInfo dictionaries the beginning and ending frame, as well as the correct animation curve and durations.
So after observing this notification, when it's posted move your text field based on the size of the frame passed in the notification, according to the animation hints provided.
You can see more information in the UIWindow class reference's "notifications" section: https://developer.apple.com/library/ios/#documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html
Below is a sample view controller implementation. The nib for this view controller was just a single text field, with an outlet connected to it, and the text field's delegate set to the view controller.
#interface ViewController ()
- (void)viewControllerInit;
#end
#implementation ViewController
#synthesize textField;
- (id)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self viewControllerInit];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
[self viewControllerInit];
}
return self;
}
- (void)viewControllerInit
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Notification Handlers
- (void)keyboardWillShow:(NSNotification *)notification
{
// I'll try to make my text field 20 pixels above the top of the keyboard
// To do this first we need to find out where the keyboard will be.
NSValue *keyboardEndFrameValue = [[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardEndFrame = [keyboardEndFrameValue CGRectValue];
// When we move the textField up, we want to match the animation duration and curve that
// the keyboard displays. So we get those values out now
NSNumber *animationDurationNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration = [animationDurationNumber doubleValue];
NSNumber *animationCurveNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey];
UIViewAnimationCurve animationCurve = [animationCurveNumber intValue];
// UIView's block-based animation methods anticipate not a UIVieAnimationCurve but a UIViewAnimationOptions.
// We shift it according to the docs to get this curve.
UIViewAnimationOptions animationOptions = animationCurve << 16;
// Now we set up our animation block.
[UIView animateWithDuration:animationDuration
delay:0.0
options:animationOptions
animations:^{
// Now we just animate the text field up an amount according to the keyboard's height,
// as we mentioned above.
CGRect textFieldFrame = self.textField.frame;
textFieldFrame.origin.y = keyboardEndFrame.origin.y - textFieldFrame.size.height - 40; //I don't think the keyboard takes into account the status bar
self.textField.frame = textFieldFrame;
}
completion:^(BOOL finished) {}];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
NSNumber *animationDurationNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration = [animationDurationNumber doubleValue];
NSNumber *animationCurveNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey];
UIViewAnimationCurve animationCurve = [animationCurveNumber intValue];
UIViewAnimationOptions animationOptions = animationCurve << 16;
[UIView animateWithDuration:animationDuration
delay:0.0
options:animationOptions
animations:^{
self.textField.frame = CGRectMake(20, 409, 280, 31); //just some hard coded value
}
completion:^(BOOL finished) {}];
}
#pragma mark - View lifecycle
- (void)viewDidUnload
{
[self setTextField:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self.textField resignFirstResponder];
return YES;
}
#end
Using notification keyboard register , you can place your textfield inside a scroll and manage the content offset of scroll to turn the actual first responder above keyboard if it's neccesary.
so after register controller to keybard appear , you must to obtain the gap between keyboard origin and scroll origin relative to parent.
you must know if an specific first responder can change content offset of scroll, therefore is neccesary to know the possible bounds between keyboard origin and first responder.
by the way you need to know the gap betwen the scroll content offset and the first responder for place your first responder in specific position.
#interface MainViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIScrollView *scroll;
#end
#interface MainViewController ()
{
CGPoint scrollOffset;
}
#end
#implementation MainViewController
#synthesize scroll
-(void)viewWillAppear:(BOOL)animated
{
[[ NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillAppear:) name:UIKeyboardDidShowNotification object:nil];
[[ NSNotificationCenter defaultCenter ] addObserver:self selector:#selector(keyboardWillDisAppear:) name:UIKeyboardDidHideNotification object:nil];
}
-(void)viewWillDisappear:(BOOL)animated
{
[[ NSNotificationCenter defaultCenter ] removeObserver:self ];
}
-(void)keyboardWillAppear:(NSNotification*) note
{
const CGFloat default_gap = 25.0f;
NSValue *keyBoardEndFrameValue = [[ note userInfo ] objectForKey:UIKeyboardFrameEndUserInfoKey ];
CGRect keyBoardFrame = [ keyBoardEndFrameValue CGRectValue ];
offset = scroll.contentOffset;
UIWindow *window = [[ UIApplication sharedApplication ] keyWindow];
UITextField *textField = (UITextField*)[ window performSelector:#selector(firstResponder) ];
//Gap between keyboard origin and the scroll origin, relative to parent.
CGFloat distanceRelativeToParent = keyBoardFrame.origin.y - scroll.frame.origin.y;
//Distance between superview to textfield inside scroll. to determine if it's necesary to scroll.
CGFloat bound = (textField.frame.origin.y + textField.frame.size.height)+scroll.frame.origin.y;
CGFloat gapScroll = textField.frame.size.height+default_gap;
if( bound >= keyBoardFrame.origin.y )
{
[ UIView animateWithDuration:.3 delay:0.0 options:UIViewAnimationCurveEaseOut
animations:^{
[ scroll setContentOffset:CGPointMake(0, textField.frame.origin.y - distanceRelativeToParent + gapScroll ) animated:YES ];
}
completion:^(BOOL finished){
}];
}
}
-(void) keyboardWillDisAppear:(NSNotification*) note
{
[ scroll setContentOffset:offset animated:YES ];
}
#end
UIViewControllers have a property called interfaceOrientation and the function UIInterfaceOrientationIsPortrait/Landscape so essentially you can do:
if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation){
//portrait logic
}
else{
//landcapeLogic
}
inside for each the iPhone and iPad in your view controller. From there you can do your pixel measurement way as you had done before, because as far as I know that's the simplest way to do it.
P.S. There is a function to check for landscape checker too, but if the first if statement is false meaning the device is not in portrait, then it must be in landscape hence the plain else.
Related
The scene auto pauses on applicationWillResignActive and auto unpauses when applicationDidBecomeActive is run. I am looking to either have the scene pause on applicationWillResignActive via the nsnotification and not auto resume when applicationDidBecomeActive is run. Any ideas? Thanks in advance.
AppDelegate
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
[[NSNotificationCenter defaultCenter] postNotificationName:#"backgroundPause" object:nil];
}
GameViewController
- (void)handleNotification:(NSNotification *)notification {
if ([notification.name isEqualToString:#"backgroundPause"]) {
SKView *skView = (SKView *)self.view;
skView.scene.paused = YES; //pauses scene
[self.lblPaused removeFromSuperview];//removes any lingering pause menu items
[self.lblPausedHelp removeFromSuperview];
self.lblPaused = [[UILabel alloc] init];
self.lblPaused.center = CGPointMake(self.view.frame.size.width/2 - 125, self.view.frame.size.height/2 - 40);
self.lblPaused.text = #"PAUSED";
[self.lblPaused setFont:[UIFont boldSystemFontOfSize:66]];
[self.lblPaused sizeToFit];
self.lblPaused.textColor = [UIColor blackColor];
[self.view addSubview:self.lblPaused];//adds pause label
self.lblPausedHelp = [[UILabel alloc] init];
self.lblPausedHelp.center = CGPointMake(self.view.frame.size.width/2 - 145, self.view.frame.size.height/2 + 40);
self.lblPausedHelp.text = #"tap anywhere to resume";
[self.lblPausedHelp setFont:[UIFont boldSystemFontOfSize:26]];
[self.lblPausedHelp sizeToFit];
self.lblPausedHelp.textColor = [UIColor blackColor];
[self.view addSubview:self.lblPausedHelp];//adds pause label
}
}
I'm pretty sure it's a bug in spritekit. No matter what you do, the game will unpause itself in applicationDidBecomeActive
I asked the same question here. pausing spritekit game on app launch / exit .. iOS8 You have to subclass SKScene and override the paused property to get it to work. It's weird you have to do that. It really shouldnt have so many problems, but thats the only way I could get my game to stay paused
EDIT: okay, I translated the code to objective-c. I hope this is useful to you because my objective-c was rustier than i expected.
AppDelegate.m
- (void)applicationWillResignActive:(UIApplication *)application {
[[NSNotificationCenter defaultCenter]postNotificationName:#"pauseGameScene" object:nil];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[NSNotificationCenter defaultCenter]postNotificationName:#"stayPausedNotification" object:nil];
}
SKView Subclass
#interface MySKView : SKView
- (void) setStayPaused;
#end
#implementation MySKView
bool _stayPaused = false;
- (void) setPaused:(BOOL)paused{
if (!_stayPaused) {
super.paused = paused;
}
_stayPaused = NO;
}
- (void) setStayPaused{
_stayPaused = YES;
}
#end
GameViewController
#interface GameViewController : UIViewController
-(void)pauseGame;
#end
#implementation GameViewController
SKScene *_scene;
MySKView *_skView;
-(void)pauseGame{
_skView.paused = YES;
_skView.scene.view.paused = YES;
}
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(pauseGame) name:#"pauseGameScene" object:nil];
// Configure the view.
_skView = [[MySKView alloc]initWithFrame:self.view.frame];
_skView.showsFPS = YES;
_skView.showsNodeCount = YES;
/* Sprite Kit applies additional optimizations to improve rendering performance */
_skView.ignoresSiblingOrder = YES;
// Create and configure the scene.
_scene = [[GameScene alloc]initWithSize:_skView.frame.size];
_scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[self.view addSubview:_skView];
[_skView presentScene:_scene];
}
- (void)viewDidAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter]addObserver:_skView selector:#selector(setStayPaused) name:#"stayPausedNotification" object:nil];
}
#end
I have a video playing app where an NSView is shown, tracked to the mouse coordinates, to show the time position when the user hovers over a certain area.
This works perfectly 70% of the time, however it frequently doesn't fire at all. The times when this is most likely to occur seem to be when bringing the mouse inside the view for the first time and after hovering the mouse outside of the area and then back inside again.
The code inside the NSView subclass is as follows:
- (void)viewDidMoveToWindow
{
if ([self window]) {
[self resetTrackingRect];
}
}
- (void)clearTrackingRect
{
if (rolloverTrackingRectTag > 0)
{
[self removeTrackingRect:rolloverTrackingRectTag];
rolloverTrackingRectTag = 0;
}
}
- (void)resetTrackingRect
{
[self clearTrackingRect];
rolloverTrackingRectTag = [self addTrackingRect:[self visibleRect]
owner:self userData:NULL assumeInside:NO];
}
- (void)resetCursorRects
{
[super resetCursorRects];
[self resetTrackingRect];
}
- (void)mouseEntered:(NSEvent *)theEvent
{
// Only ask for mouse move events when inside rect because they are expensive
[[self window] setAcceptsMouseMovedEvents:YES];
[[self window] makeFirstResponder:self];
// Tells the observer to show the time view
[[NSNotificationCenter defaultCenter] postNotificationName:#"MWTimelineHover" object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:theEvent,#"event",nil]];
}
- (void)mouseExited:(NSEvent *)theEvent
{
[[self window] setAcceptsMouseMovedEvents:NO];
[[self window] resignFirstResponder];
// Tells the observer to hide the time view
[[NSNotificationCenter defaultCenter] postNotificationName:#"MWTimelineHoverLeave" object:self];
}
- (void)mouseMoved:(NSEvent *)theEvent
{
[super mouseMoved:theEvent];
// Tells the observer to show the time view
[[NSNotificationCenter defaultCenter] postNotificationName:#"MWTimelineHover" object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:theEvent,#"event",nil]];
}
Note: on the occasions when it stalls, mouseExited is not called and the view has not lost firstResponder status. I am also not dragging the mouse, simply moving it normally.
You need to use NSTrackingArea. Here is reference NSTrackingArea Class Reference.
- (void)commonInit {
CGRect rect = CGRectMake(0.0f, 0.0f, self.frame.size.width, self.frame.size.height);
NSTrackingAreaOptions options = NSTrackingActiveInKeyWindow | NSTrackingMouseMoved | NSTrackingInVisibleRect;
_trackingArea = [[NSTrackingArea alloc] initWithRect:rect options:options owner:self userInfo:nil];
[self addTrackingArea:_trackingArea];
}
Hope it helps you.
I have a view controller on which I have a table view, in table view each row have text field when i tap on the text field keyboard appear and hide the table view, and then can't see the editing, how can I fix this issue? I put observer that fix the alignment of view controller but it didn't work here is the code..
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
return YES;
}
-(void)keyboardWillShow {
// Animate the current view out of the way
[UIView animateWithDuration:0.3f animations:^ {
self.viewFrame = CGRectMake(0, -160, 320, 480);
}];
}
you have to write below code, it will hide and show keyboard.
====>.h file: declare one UITextField as below:
UITextField *actifText;
====>.m file:
-(void)viewDidAppear:(BOOL)animated
{
// Register notification when the keyboard will be show
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
// Register notification when the keyboard will be hide
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
-(void)viewDidDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void) keyboardWillShow:(NSNotification *)note
{
// Get the keyboard size
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];
// Detect orientation
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect frame = self.tblName.frame;
// Start animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3f];
// Reduce size of the Table view
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
frame.size.height -= keyboardBounds.size.height;
else
frame.size.height -= keyboardBounds.size.width;
// Apply new size of table view
self.tblName.frame = frame;
// Scroll the table view to see the TextField just above the keyboard
if (self.actifText)
{
CGRect textFieldRect = [self.tblName convertRect:self.actifText.bounds fromView:self.actifText];
[self.tblName scrollRectToVisible:textFieldRect animated:NO];
}
[UIView commitAnimations];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
self.actifText = nil;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
self.actifText = textField;
}
-(void) keyboardWillHide:(NSNotification *)note
{
// Get the keyboard size
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];
// Detect orientation
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect frame = self.tblName.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3f];
// Reduce size of the Table view
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
frame.size.height += keyboardBounds.size.height;
else
frame.size.height += keyboardBounds.size.width;
// Apply new size of table view
self.tblName.frame = frame;
[UIView commitAnimations];
}
When you tap on some textfield inside cell, you must know current cell's indexpath, so when keyboard is shown, you can focus it.
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField
{
UITableViewCell *cell = (UITableViewCell *)[textField superview].superview;
NSIndexPath *idxPath = [table indexPathForCell:cell];
selectedIndex = idxPath.row;//instance variable
return YES;
}
-(void)keyboardWillShow {
[table scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:selectedIndex inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
Also add following line to ViewDidLoad, keeping in mind to observe when keyboard have appeared. If you use UIKeyboardWillShowNotification, first keyboardWillShow will be called followed by textFieldShouldBeginEditing: which is wrong.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardDidShowNotification
object:nil];
and set
textfield.delegate = self;
in cellForRowAtIndexPath while creating textfield. It will call required methods.
I have uiscrollview, 2 textviewfields and I read all the posts about keyboard hiding textview and tried many methods, but still it hides it.
My code is like this:
ViewController.h
#property(nonatomic,retain) IBOutlet UITextView *campaignTitle;
#property (weak, nonatomic) IBOutlet UITextView *campaignDescription;
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property UITextView *activeTextView;
ViewController.m
#synthesize campaignTitle;
#synthesize campaignDescription;
#synthesize scrollView;
#synthesize activeTextView;
#define SCROLLVIEW_CONTENT_HEIGHT 460
#define SCROLLVIEW_CONTENT_WIDTH 320
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
scrollView.contentSize=CGSizeMake(0, self.view.frame.origin.y+self.view.frame.size.height+50);
[super viewDidLoad];
}
- (BOOL) textViewShouldBeginEditing:(UITextView *)textView
{
textView.text = #"";
self.activeTextView = textView;
return YES;
}
- (BOOL) textViewShouldEndEditing:(UITextView *)textView
{
self.activeTextView = nil;
return YES;
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:#"\n"])
[textView resignFirstResponder];
return YES;
}
- (void)keyboardWasShown:(NSNotification *)notification
{
// Step 1: Get the size of the keyboard.
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
// Step 2: Adjust the bottom content inset of your scroll view by the keyboard height.
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// Step 3: Scroll the target text field into view.
CGRect aRect = self.view.frame;
aRect.size.height -= keyboardSize.height;
if (!CGRectContainsPoint(aRect, activeTextView.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, activeTextView.frame.origin.y - (keyboardSize.height-15));
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
- (void) keyboardWillHide:(NSNotification *)notification {
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
- (IBAction)dismissKeyboard:(id)sender
{
[self.activeTextView resignFirstResponder];
}
There is delegation from the scroll view and campaignTitle, campaignDescription.
What is wrong? why the keyboard still hiding the bottom uitextview? The extra code that you may see is to support Return button in UITextView
Or use TPKeyboardAvoiding.
It is working great, and is very easy to setup:
Add a UIScrollView into your view controller's xib
Set the scroll view's class to TPKeyboardAvoidingScrollView (still
in the xib, via the identity inspector)
Place all your controls within that scrollview
It also automatically hooks up "Next" buttons on the keyboard to switch through the text fields.
Make sure your UITextFields are actually inside of your UIScrollView inside your storyboard and not accidentally placed on the UIView below it.
setContentOffset should do SOMETHING, even if it is not the intended effect. Since it seems to be doing nothing, I'd suspect that either your UITextFields are not subviews of it or your UIScrollView is not wired up in interface builder.
I have a view with several embedded UITextFields, this UIView is subordinated to a UIScrollView in IB. Each text field is supposed to invoke a method called updateText defined in the viewcontroller implementation file when the user is done editing the field. For some reason, the method updateText never gets invoked. Anyone have any ideas how to go about fixing this? The method fired off just fine when the UIScrollView was not present in the project but the keyboard would cover the text fields during input, which was annoying. Now my textfields move up above the keyboard when it appears, but won't fire off the method when done editing.
Here is my implementation file:
#import "MileMarkerViewController.h"
#implementation MileMarkerViewController
#synthesize scrollView,milemarkerLogDate,milemarkerDesc,milemarkerOdobeg,milemarkerOdoend,milemarkerBusiness,milemarkerPersonal,milemarker;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Initialization code
}
return self;
}
- (BOOL) textFieldShouldReturn: (UITextField*) theTextField {
return [theTextField resignFirstResponder];
}
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardWasShown:)
name: UIKeyboardDidShowNotification
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardWasHidden:)
name: UIKeyboardDidHideNotification
object: nil];
keyboardShown = NO; // 1
[scrollView setContentSize: CGSizeMake( 320, 480)]; // 2
}
- (void)keyboardWasShown:(NSNotification*)aNotification {
if (keyboardShown) return;
NSDictionary* info = [aNotification userInfo];
// Get the size of the keyboard.
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
// Resize the scroll view (which is the root view of the window)
CGRect viewFrame = [scrollView frame];
viewFrame.size.height -= keyboardSize.height;
scrollView.frame = viewFrame;
// Scroll the active text field into view.
CGRect textFieldRect = [activeField frame];
[scrollView scrollRectToVisible:textFieldRect animated:YES];
keyboardShown = YES;
}
- (void)keyboardWasHidden:(NSNotification*)aNotification {
NSDictionary* info = [aNotification userInfo];
// Get the size of the keyboard.
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
// Reset the height of the scroll view to its original value
CGRect viewFrame = [scrollView frame];
viewFrame.size.height += keyboardSize.height;
[scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
scrollView.frame = viewFrame;
keyboardShown = NO;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
activeField = nil;
}
- (IBAction)updateText:(id) sender {
NSLog(#"You just entered: %#",self.milemarkerLogDate.text);
self.milemarker.logdate = self.milemarkerLogDate.text;
self.milemarker.desc = self.milemarkerDesc.text;
self.milemarker.odobeg = self.milemarkerOdobeg.text;
self.milemarker.odoend = self.milemarkerOdoend.text;
self.milemarker.business = self.milemarkerBusiness.text;
self.milemarker.personal = self.milemarkerPersonal.text;
NSLog(#"Original textfield is set to: %#",self.milemarker.logdate);
[self.milemarker updateText];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)dealloc {
[super dealloc];
}
#end
I think you have already known a solution because of post date.
You can implement textFieldShouldReturn method and resign first responder from textField in the method.
textFieldDidEndEditing is called after textField resign first responder.