Why view moves down while displaying keyboard? - ios

I have a tab controller based app, where I have a uitextview on selecting which I m moving view up as keyboard appears , the entire thing works well until I switch tab , when I come back to this tab and try editing in uitextview view moves down and then back to normal position on keyboard appearing instead of moving up . here is the entire code
- (void)textViewDidBeginEditing:(UITextView *)textField
{
[self keyboardWillShow];
}
-(void)textViewDidEndEditing:(UITextView *)textField
{
[self keyboardWillHide];
}
-(void)keyboardWillShow {
// Animate the current view out of the way
if (self.view.frame.origin.y >= 0)
{
[self setViewMovedUp:YES];
}
else if (self.view.frame.origin.y < 0)
{
[self setViewMovedUp:NO];
}
}
-(void)keyboardWillHide {
if (self.view.frame.origin.y >= 0)
{
[self setViewMovedUp:YES];
}
else if (self.view.frame.origin.y < 0)
{
[self setViewMovedUp:NO];
}
}
//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5]; // if you want to slide up the view
CGRect rect = self.view.frame;
if (movedUp)
{
// 1. move the view's origin up so that the text field that will be hidden come above the keyboard
// 2. increase the size of the view so that the area behind the keyboard is covered up.
rect.origin.y -= kOFFSET_FOR_KEYBOARD;
rect.size.height += kOFFSET_FOR_KEYBOARD;
}
else
{
// revert back to the normal state.
rect.origin.y += kOFFSET_FOR_KEYBOARD;
rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
self.view.frame = rect;
[UIView commitAnimations];
}

Well I had similar issues and figured it out. You can check my recent post:
https://stackoverflow.com/a/28177645/2989374

Related

How to move bottom textFields up when key board appears?

fields in my view, i want to move my text-view up when keyboard appears when i started entering text in 6th, 7th, 8th. text-Fields only.
I tried solution for you question and I simply got.
#define kOFFSET_FOR_KEYBOARD 80.0
#interface ViewController ()
{
NSInteger tagTF;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)setMovedUp:(BOOL)movedUP
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect rect = self.view.frame;
if(movedUP)
{
rect.origin.y -= kOFFSET_FOR_KEYBOARD;
rect.size.height += kOFFSET_FOR_KEYBOARD;
}
else{
rect.origin.y += kOFFSET_FOR_KEYBOARD;
rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
self.view.frame = rect;
[UIView commitAnimations];
}
#pragma mark - UITextFieldDelegate Methods
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
tagTF = textField.tag;
if(textField.tag>=6)
{
if(self.view.frame.origin.y >= 0)
{
[self setMovedUp:YES];
}
}
return YES;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
if(textField.tag>=6)
{
[self setMovedUp:NO];
}
[textField resignFirstResponder];
return YES;
}
From my above answer I set the textField tag from 1 to 8.It works perfectly what you want.Please set the delegate for textField.
I have an extensive blog post explaining how to do this:
Shifting views to make room for the keyboard
The gist of it is that you add notification handlers for the keyboard will show and keyboard will hide notifications. In those handlers, you get the height of the keyboard, then do some math to figure out how much you need to move the field up so the keyboard doesn't cover it. You then move your view controller's view up just enough to keep the field exposed.
It gets more complicated than that, but that's all covered in the blog post (which is part of a larger blog post on animating random shapes that includes a working example of the keyboard technique.)
here is the official documentation by Apple regarding handling the keyboard.
There are lots of options for that.
I was using TPKeyboardAvoidingScrollView for a long time. Right now, i am using IQKeyboardManager much more simple and easy to integrate.
IQKeyboardManager
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
CGRect frame = self.view.frame;
Float y = frame.origin.y - 70;
frame.origin.y = y;
self.view.frame = frame;
return YES;
}
- (void) textFieldDidEndEditing:(UITextField *)textField{
CGRect frame = self.view.frame;
Float y = frame.origin.y + 70;
frame.origin.y = y;
self.view.frame = frame;
}
if you have change y value(like 70, 80, ...)in textFieldShouldBeginEditing method, and add same value to y in textFieldDidEndEditing method.
try this code.

Got a keyboard will show notification, but keyboard window is nil

I am a little bit confused. I am creating an App where user can swipe a scrollview horizontally between pages and every page has a textfield or a textview. I subscribe to UIKeyboardWillShowNotification and UIKeyboardWillHideNotification notifications and cards decrease their height when keyboard pops up and increase it back when keyboard hides.
Also when scrollView is dragged all textViews/textField resign first responder. That is how it looks like:
-(void)keyboardWillHide:(NSNotification*)notification{
// NSLog(#"notification user info = %#",notification.userInfo);
auto userInfo=notification.userInfo;
auto curve=[userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
auto duration=[userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
auto startFrame=[userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
auto endFrame=[userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
auto dY=endFrame.origin.y-startFrame.origin.y;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:(UIViewAnimationCurve)curve];
[UIView setAnimationDuration:duration];
_feedbackTextView.height+=dY;
_feedbackUserDataView.height+=dY;
[UIView commitAnimations];
}
-(void)keyboardWillShow:(NSNotification *)notification{
// NSLog(#"notification user info = %#",notification.userInfo);
auto userInfo=notification.userInfo;
auto curve=[userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
auto duration=[userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
auto startFrame=[userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
auto endFrame=[userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
auto dY=endFrame.origin.y-startFrame.origin.y;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:(UIViewAnimationCurve)curve];
[UIView setAnimationDuration:duration];
_feedbackTextView.height+=dY;
_feedbackUserDataView.height+=dY;
[UIView commitAnimations];
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
[_feedbackTextView resignFirstResponder];
[_feedbackUserDataView resignFirstResponder];
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
// NSLog(#"%s",sel_getName(_cmd));
CGFloat width = scrollView.frame.size.width;
NSInteger page = (scrollView.contentOffset.x + (0.5f * width)) / width;
switch(page){
case 0:{
[_feedbackTextView becomeFirstResponder];
}break;
case 1:{
[_feedbackUserDataView becomeFirstResponder];
}break;
}
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
// NSLog(#"decelerate = %d",decelerate);
if(decelerate==NO){
CGFloat width = scrollView.frame.size.width;
NSInteger page = (scrollView.contentOffset.x + (0.5f * width)) / width;
switch(page){
case 0:{
[_feedbackTextView becomeFirstResponder];
}break;
case 1:{
[_feedbackUserDataView becomeFirstResponder];
}break;
}
}
}
_feedbackTextView is a subview on the first page of scrollView, _feedbackUserDataView is a subview on the second page of scrollView.
I tested my App. I scrolled, tapped textViews/textFields chaotically. And I got warning in my logs
|warning| Got a keyboard will show notification, but keyboard window is nil.
To my surprise there is nothing about this in google so I posted a question here. Sorry for ugly formatting.
This warning seems to be generated when the keyboard is dismissed immediately after being presented, before the animation has been completed.
In this case scrollViewDidEndDecelerating: can get called when the user starts panning again while the scroll view is still decelerating. Then immediately afterwards scrollViewDidScroll: gets called, which results in the keyboard being presented and immediately dismissed.
One fix would be to check the scrollView's panGestureRecogniser state and avoid making the text field first responder if it's in UIGestureRecognizerStateBegan
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
if ([scrollView panGestureRecognizer].state == UIGestureRecognizerStateBegan) {
return;
}
// NSLog(#"%s",sel_getName(_cmd));
CGFloat width = scrollView.frame.size.width;
NSInteger page = (scrollView.contentOffset.x + (0.5f * width)) / width;
switch(page){
case 0:{
[_feedbackTextView becomeFirstResponder];
}break;
case 1:{
[_feedbackUserDataView becomeFirstResponder];
}break;
}
}
This should remove most of the warnings. There may still be some if the user starts panning just as the keyboard is being presented. These would be harder to deal with - you'd need to make sure the keyboard has finished it's presentation animation before dismissing it by also subscribing to the UIKeyboardDidShowNotification and dismissing it there if the user is panning.

iAd covers my view on the first load

I have iAds working almost perfectly using a modified version of UITabBarController-iAds. The only issue I have is on the very first load of an advert my view gets covered. Once the ad refreshes after 30 seconds the view resizes just fine.
I'm using the following code:
- (void)layoutBanner
{
float height = 0.0;
ADBannerView *_banner = (ADBannerView *)[self.view viewWithTag:12];
CGRect bounds = [UIScreen mainScreen].bounds;
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
_banner.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
_banner.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
//When compiling against iOS 8 SDK this needs to be height, regardless of the actual device orientation
height = bounds.size.height;
CGSize bannerSize = [ADBannerView sizeFromBannerContentSizeIdentifier:_banner.currentContentSizeIdentifier];
//Get content view
UIView *_contentView = self.selectedViewController.view;
CGRect contentFrame = _contentView.frame;
CGRect bannerFrame = _banner.frame;
if (_banner.isBannerLoaded) {
if (iOS7) {
contentFrame.size.height = height - bannerSize.height;
bannerFrame.origin.y = contentFrame.size.height - self.tabBar.frame.size.height;
} else {
contentFrame.size.height = height - self.tabBar.frame.size.height - bannerSize.height;
bannerFrame.origin.y = contentFrame.size.height;
}
} else {
if (iOS7) {
contentFrame.size.height = height;
bannerFrame.origin.y = bounds.size.height;
} else {
contentFrame.size.height = height - self.tabBar.frame.size.height;
bannerFrame.origin.y = bounds.size.height;
}
}
[UIView animateWithDuration:0.25 animations:^{
_banner.frame = bannerFrame;
_contentView.frame = contentFrame;
} completion:^(BOOL finished) {
[self.view bringSubviewToFront:_banner];
}];
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
NSLog(#"Did load");
[self layoutBanner];
}
Any ideas?
I managed to fix this issue by playing around with the animation block. I moved the content view line and it resolved the issue
[UIView animateWithDuration:0.25 animations:^{
_banner.frame = bannerFrame;
} completion:^(BOOL finished) {
_contentView.frame = contentFrame;
[self.view bringSubviewToFront:_banner];
}];
I'm not 100% sure, but I suppose the problem is related to:
[self.view bringSubviewToFront:_banner];
The whole animation:
[UIView animateWithDuration:0.25 animations:^{
_banner.frame = bannerFrame;
_contentView.frame = contentFrame;
} completion:^(BOOL finished) {
[self.view bringSubviewToFront:_banner];
}];
is a little strange, because at the completion block you are bringing the banner view to front, so I can suppose that before animation did start - the banner was covered by some other view or views - what is the reason of frame animation if banner view is covered - thus cannot be seen while animation is in progress?
Of course the issue applies only for the first run.
as of iOs8 [[UIScreen mainScreen]bounds] has changed.. previously it would always return portrait (where H > W ) values, regardless of interfaceOrientation, but it now appears to respect interface orientation... (which is not a bad thing, unless you're taking previous behaviour for granted)
Why don't you try CGRectGetMinY(CGRect aRect) ..
eg. (Im assuming from your code the banner goes along the screen bottom, and your TAbBar across the top. (which I think is weird..) )
//once you have calculated bannerFrame
contentFrame.size.height = ( CGRectGetMinY(bannerFrame) - CGRectGetMinY (contentView.frame) );
contentFrame.origin.y = CGRectGetMaxY(self.tabbar.frame);
Do you have any constraints / resizingMasks set? when you load a second ad the view controller's view has already been resized to fit an ad, presumably the first ad is the one trying to change things..

How do you change position of UIView when scrolling a UITableview

i have a uiview and i want to hide and show when you scroll down and up the tableview,
This is what i have done so far:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if ([scrollView.panGestureRecognizer translationInView:scrollView.superview].y > 0) {
NSLog(#"moving up");
} else {
scrollingUp = false;
NSLog(#"moving down");
[self pushUpsearchView];
}
}
pushUpsearchView method:
-(void)pushUpsearchView{
[UIView animateWithDuration:0.3 animations:^{
CGRect frame = self.mysearchView.frame;
frame.origin.x = self.mysearchView.frame.origin.x;
frame.origin.y = 100;
self.mysearchView.frame = frame;
self.mysearchView.frame = frame;
} completion:^(BOOL finished){
NSLog(#"Finished animating!");
}];
}
But this is what i end up with:
However when i remove [self pushUpsearchView] from the scrollViewWillBeginDragging method, and put it in my viewdidload method, it works just fine without duplicating it it simply changes its position

How to create animation for UIview that needs to pull down to up?

I want to create a screen to pull up from down and need to pull down.like iOS notifications screen (but in reverse direction).Please share if any example is there.Thanks in advance.
The full-on way to do this in iOS 7 is with an interactive custom transition. You will use a UIScreenEdgePanGestureRecognizer and respond to the drag gesture from the edge of the screen by performing part of the transition animation to match the distance the user's finger has travelled. Look into the UIPercentDrivenInteractiveTransition class to help you do that.
Here's a complete example you can download and run: it happens that I'm doing it from the left or right, not the top or bottom, but it is the same basic idea.
https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch06p296customAnimation2/ch19p620customAnimation1/AppDelegate.m
But beware: if you try to do it from the top or the bottom you will get interference from the notification center (top) and the control center (bottom). It can be tricky to prevent that interference.
Hi you can use it.
- (void)showShareView {
[self.view bringSubviewToFront:self.view_Email];
[UIView beginAnimations:#"Show"
context:nil];
[UIView setAnimationDuration:0.3F];
CGRect frame = self.view_Email.frame;
if (IS_IPHONE5) {
if(txtFieldActiveFlag==1){
frame.origin.y = 568-420;
}else{
frame.origin.y = 568-220;
}
} else {
frame.origin.y = 480 - 275 - 88;
}
self.view_Email.frame = frame;
[UIView commitAnimations];
}
- (void)hideShareView {
[UIView beginAnimations:#"Show"
context:nil];
[UIView setAnimationDuration:0.3F];
CGRect frame = self.view_Email.frame;
if (IS_IPHONE5) {
if(txtFieldActiveFlag==2){
frame.origin.y = 568-220;
}else{
frame.origin.y = 568;
}
} else {
frame.origin.y = 480;
}
self.view_Email.frame = frame;
[UIView commitAnimations];
}
//call method from any button action.
[self showShareView]; //show the view up
[self hideShareView]; //show the view down
Thanks

Resources