Keyboard hide UITableView issue - objective-c

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.

Related

Hide iAd Banner SKScene

Hi Guys What Do You Think Should I Use In The Handle Notifications (hideAd,showAd) to show and hide my iAd Banner In My Project and here is what i use to show iAd Banner `#import "GameViewController.h"
import "GameScene.h"
#interface GameViewController(){
bool adOnTop;
bool iadsBannerIsVisible;
ADBannerView* theBanner;
}
#end
#implementation GameViewController
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleNotification:) name:#"hideAd" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleNotification:) name:#"showAd" object:nil];
[super viewDidLoad];
// Configure the view.
SKView * skView = (SKView *)self.view;
skView.showsFPS = YES;
skView.showsNodeCount = YES;
skView.multipleTouchEnabled = YES;
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = YES;
// Create and configure the scene.
GameScene *scene = [GameScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFit;
// Present the scene.
[skView presentScene:scene];
[self showThinBanner];
}
-(void) showThinBanner {
iadsBannerIsVisible = YES;
theBanner = [[ADBannerView alloc] initWithFrame:CGRectZero];
[theBanner setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
theBanner.delegate = self;
[self.view addSubview:theBanner];
}
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave {
NSLog(#"Banner view is beginning an ad action");
BOOL shouldExecuteAction = YES; // your app implements this method
if (!willLeave && shouldExecuteAction){
// insert code here to suspend any services that might conflict with the advertisement, for example, you might pause the game with an NSNotification like this...
[[NSNotificationCenter defaultCenter] postNotificationName:#"PauseScene" object:nil]; //optional
}
return shouldExecuteAction;
}
-(void) bannerViewActionDidFinish:(ADBannerView *)banner {
NSLog(#"banner is done being fullscreen");
//Unpause the game if you paused it previously.
[[NSNotificationCenter defaultCenter] postNotificationName:#"UnPauseScene" object:nil]; //optional
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
if (iadsBannerIsVisible == YES) {
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
// Assumes the banner view is placed at the bottom of the screen.
banner.frame = CGRectOffset(banner.frame, 0, banner.frame.size.height);
[UIView commitAnimations];
iadsBannerIsVisible = NO;
NSLog(#"banner unavailable");
}
}
- (void)handleNotification:(NSNotification *)notification
{
if ([notification.name isEqualToString:#"hideAd"])
{
// hide your banner;
}else if ([notification.name isEqualToString:#"showAd"])
{
// show your banner
}
}
Sloved
- (void)handleNotification:(NSNotification *)notification
{
if ([notification.name isEqualToString:#"hideAd"])
{
// hide your banner;
[theBanner removeFromSuperview];
}else if ([notification.name isEqualToString:#"showAd"])
{
// show your banner
[self.view addSubview:theBanner];
}
}

About Hide the keyboard

My question is :
When I write a user login UI, because the keyboard hide the password textfield, so I write some code to scroll up the login UI, but when the keyboard is hidden and the UI is scrolled to the old position, I find I touch the textfield which I can't get any response.
registe notification:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillshow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillhide:)
name:UIKeyboardWillHideNotification
object:nil];
_username.delegate = self;
_password.delegate = self;
will show keyboard code:
- (void) keyboardWillshow:(NSNotification *)noti
{
NSDictionary *userInfo = [noti userInfo];
NSValue *keyValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [keyValue CGRectValue];
int height = keyboardRect.size.height;
userInfo = nil;
keyValue = nil;
[UIView animateWithDuration:0.5f animations:^{
self.containView.frame = CGRectMake(0, -height+20, WIDTH/2, HEIGHT/2-20);
}];
}
will hide keyboard code:
- (void)keyboardWillhide:(NSNotification *)noti
{
[UIView animateWithDuration:0.5f animations:^{
self.containView.frame = CGRectMake(0, 20, WIDTH/2, HEIGHT/2-20);
}];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[_password resignFirstResponder];
[_username resignFirstResponder];
}
Could some one help me? I use the storyboard to write the code.

How Popup Keyboard After Segue to New Naviagtion Controller Animation Has Finished

I segue from a tableview to detail view controller using custom segues.
#implementation QuickNoteFlipSegue
- (void) perform {
UIViewController *src = (UIViewController *) self.sourceViewController;
UIViewController *dst = (UIViewController *) self.destinationViewController;
dst.navigationItem.hidesBackButton = YES;
[UIView transitionWithView:src.navigationController.view duration:1.00
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
[src.navigationController pushViewController:dst animated:NO];
}
completion:^(BOOL finished){
if (finished) {
}
}];
}
#end
What I would like to do it when the transition has finished, popup the keyboard for my textview.
I currently do this by calling
[textView becomeFirstResponder];
This pops up the keyboard OK but before the transition animation has finished. How to detect when the animation has finished before I popup the keyboard?
I should maybe put something is the completion of the animation, but how to make the custom segue aware of the textview in it's destination?
Do:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[textView becomeFirstResponder];
}
Add a method to your DestinationViewController:
-(void)openKeyboard
{
[textView becomeFirstResponder];
}
Then change your perform method:
- (void) perform {
UIViewController *src = (UIViewController *) self.sourceViewController;
DestinationViewController *dst = (DestinationViewController *) self.destinationViewController;
dst.navigationItem.hidesBackButton = YES;
[UIView transitionWithView:src.navigationController.view duration:1.00
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
[src.navigationController pushViewController:dst animated:NO];
}
completion:^(BOOL finished){
if (finished) {
[dst openKeyboard];
}
}];
}

call method AFTER textFieldShouldReturn

I would like to call my login method AFTER the keyboard was dismissed - since I want to start animation and change the UIView alpha to 0.5 until the response.
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (theTextField == self.passwordText){
//hide the keyboard
[theTextField resignFirstResponder];
[self validateCredentialsRemotely];
}else{
[self.passwordText becomeFirstResponder];
}
return YES;
}
The keyboard is not being dismissed before the call to the method validateCredentialsRemotely and the screen freezes while the keyboard is displayed. I would like it to be dismissed first, and then call the method.
Use this notifications..
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
In keyboardWillHide method call your validateCredentialsRemotely method,This may solve your first issue
try this!
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (theTextField == self.passwordText){
//hide the keyboard
[theTextField resignFirstResponder];
[self performSelector:#selector(doAnim) withObject:nil afterDelay:0];
}else{
[self.passwordText becomeFirstResponder];
}
return YES;
}
- (void)doAnim {
//start animation
self.view.alpha =0.5;
[activityWheel startAnimating];
//validate user
[self validateCredentialsRemotely];
//end animation
[activityWheel stopAnimating];
self.view.alpha =1;
}

Logic For Moving Text Field Above Keyboard On Tap

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.