In my app I've this login screen:
Above the first test field I've an image, the configuration in Interface Builder is the follow:
Now when I tap on the UITextField they should move up otherwise in iPhone 4/4s the field will be covered by keyboard.
Now I'm using the following code:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frameView = self.view.frame;
CGRect frameImage = self.imageViewLogo.frame;
CGRect frameTextFieldUsername = self.textFieldUsername.frame;
CGRect frameTextFieldPassword = self.textFieldPassword.frame;
CGRect frameButtonLogin = self.buttonLogin.frame;
frameView.origin.y = -100;
frameImage.origin.y = -100;
frameTextFieldUsername.origin.y = -100;
frameTextFieldPassword.origin.y = -100;
frameButtonLogin.origin.y = -100;
[self.view setFrame:frameView];
[self.imageViewLogo setFrame:frameImage];
[self.textFieldUsername setFrame:frameTextFieldUsername];
[self.textFieldPassword setFrame:frameTextFieldPassword];
[self.buttonLogin setFrame:frameButtonLogin];
[UIView commitAnimations];
}
When I try to run the app in simulator or on a real device the view scrolls up of 100 but the image, the text fields and button doesn't scrolls up... I thought that the problem depend on the constraints, can you help me to fix this issue?
Thank you
The way in which you are trying to do this will get you in trouble. As you are giving hardcoded values of frame.
Try to use keyboard avoiding library it's the better and safer way of doing it.
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frameView = self.view.frame;
CGRect frameImage = self.imageViewLogo.frame;
CGRect frameTextFieldUsername = self.textFieldUsername.frame;
CGRect frameTextFieldPassword = self.textFieldPassword.frame;
CGRect frameButtonLogin = self.buttonLogin.frame;
frameView.origin.y = -100;
// no need of changing frames of TextFields inside the View, Just change the y-padding of View
[self.view setFrame:frameView];
[UIView commitAnimations];
}
reduce the y-padding to -120 and check
Hope this helps thanks
If your views are set up to use AutoLayout, changing frame will do nothing.
You should subscribe to UIKeyboardWillChangeFrameNotification and perform your changes there. In case of constraints you would update the constrains constants here and the call -setNeedsUpdateConstraints on the superview.
You have to figure out if the keyboards is appearing or disappearing at all if you want to support external keyboard.
Otherwise you can listen for UIKeyboardWillShowNotification and UIKeyboardWillHideNotification
For auto up the textFields while keyboard comes not need to use the thirdParty Classes.
Create a static tableView and design each textFields and button in each static cells.
TableView automatically handle the auto up textFields while keyboard comes.
Hi the simple and easy trick for doing it is :-
Take outlet of top constraint of username or email id textfield in your class and on textfield did begin editing delegate decrease the constraint's constant value so it will goes up when u select the textfield and at textField did end editing delegate again set constraint's constant value to previous one so it will reset on previous position.
eg:-Assuming you set Top Constraint value in Storyboard is 150
-(void)textFieldDidBeginEditing:(UITextField *)textField {
_topConstraint.constant = 10.00;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
_topConstraint.constant = 150.00;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
Hope it will help you.
Related
so I have a very simple button that when clicked goes to fullscreen and when clicked again goes back to the same position it was initially in. For some reason it works perfectly without the animation. When I uncomment the animation part when I initially click the button it does nothing, the second time I click it slightly enlarges. The third time I click it animates slowly but back to it's smaller original size... Why is it animating the opposite way?
- (IBAction)viewImage1:(id)sender {
UIButton *btn = (UIButton*) sender;
if (btn.tag == 0)
{
CGRect r = [[UIScreen mainScreen] bounds];
/*[UIView animateWithDuration:0.5f delay:0.0f options:0 animations:^{*/
[sender setFrame: r];
/*}completion:nil];*/
btn.tag = 1;
}
else
{
btn.tag = 0;
[sender setFrame:CGRectMake(0,0,370,200)];
}
}
There are two solutions to your problem either of which will work:
Disable Autolayout. (discouraged)
You can do that in Interface Builder by opening the File Inspector
in the right pane and unchecking the respective check box.
However, if you want to use Autolayout for constraining other UI elements in your view (which is quite a good idea in most cases) this approach won't work which is why I would recommend the second solution:
Keep Autolayout enabled, create an outlet for your button in your view controller and set
self.myButton.translatesAutoresizingMaskIntoConstraints = YES;
in your view controller's viewDidLoad method.
You could also add layout constraints to your button and animate those. (This excellent Stackoverflow post explains how it's done.)
The reason for this tricky behavior is that once you enable Autolayout a view's frame is no longer relevant to the actual layout that appears on screen, only the view's layout constraints matter. Setting its translatesAutoresizingMaskIntoConstraints property to YES causes the system to automatically create layout constraints for your view that will "emulate" the frame you set, in a manner of speaking.
It is easier to do this with auto layout and constraints. Create an IBOutlet for the height constraint of your button call it something like btnHeight. Do the same for the width constraint call it something like btnWidth. Then create an IBAction like so:
- (IBAction)buttonPress:(UIButton *)sender {
UIButton *btn = (UIButton *) sender;
CGRect r = [[UIScreen mainScreen] bounds];
if (CGRectEqualToRect(btn.frame, CGRectMake(0.0, 0.0, 370, 200))) {
[UIView animateWithDuration:0.5 delay:0.0 options:0 animations:^{
self.btnHeight.constant = r.size.height;
self.btnWidth.constant = r.size.width;
[self.view layoutIfNeeded];
} completion:^(BOOL finished){
}];
}else{
[UIView animateWithDuration:0.5 delay:0.0 options:0 animations:^{
self.btnHeight.constant = 200.0;
self.btnWidth.constant = 370.0;
[self.view layoutIfNeeded];
} completion:^(BOOL finished){
}];
}
}
In my experience animating the frame of a UIButton does not work well, a, the only method, I'm aware of, is to use CGAffineTransformScale which will rasterize the title of the button and scale it as well.
I have a screen within an iPhone app that consist of a UITextView. This text view is contained within a UIScrollView. The purpose of the screen is for the user to type in text, and to optionally attach an image to what he is writing. Therefore, the screen also has a UIToolbar with a camera button at the bottom of the screen. The structure of the screen is as follows:
-View
--UIScrollView
---UITextView
--UIToolbar
---UIButton
When the user navigates to this screen, the viewDidAppear method assigns first responder to the uitextview element, so the keyboard shows up, which hides the toolbar and the camera button.
I would like the entire toolbar to re-draw itself right above the keyboard, and to position itself again at the bottom of the screen when the keyboard hides.
I have found related posts on SO (like this one). However, such methods introduce undesired behaviours. For example, implementing the solution in the article above, the toolbar does move with the keyboard, but the UIScrollView gets its frame.origin.y coordinate shifted way above the top of the screen, so it's impossible for the user to see what he is typing.
I have also tried to reset the frame of the toolbar, by adding it as an IBOutlet and using cgrectmake to reposition it. However, after several tries, the toolbar remains stuck at the bottom of the screen and hidden by the keyboard:
- (void) liftMainViewWhenKeybordAppears:(NSNotification*)aNotification{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:<#(UIViewAnimationCurve)#>]
CGRect frame = self.keyboardToolbar.frame;
frame.origin.y = self.keyboardToolbar.frame.origin.y - 280;
self.keyboardToolbar.frame = frame;
[UIView commitAnimations];
}
I have tried several iterations similar to the code above and they all fail at repositioning the toolbar.
So in short, what is the right way to float a toolbar right on top of a keyboard in a screen whose space is completely utilised by a uitextview element?
Thanks to RoryMcKinnel for the pointer. As the article referenced is in Swift, I thought I might paste the solution that worked for be on ObjC
- (void)keyboardWillShowNotification:(NSNotification *)notification{
NSDictionary *userInfo = notification.userInfo;
double animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardEndFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect convertedKeyboardFrame = [self.view convertRect:keyboardEndFrame fromView:self.view.window];
UIViewAnimationOptions rawAnimationCurve = (UIViewAnimationOptions)[userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
_toolBarBottomGuide.constant = CGRectGetMaxY(self.view.bounds) - CGRectGetMinY(convertedKeyboardFrame);
[UIView animateWithDuration:animationDuration delay:0.0 options:rawAnimationCurve animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
Bear in mind, this code did make the toolbar move as required, but the toolbar was not visible at all. It turned out that it was being hidden behind the UIScrollView. This was easily fixed by shifting the order between the scroll view and the toolbar element in the IB hierarchy.
The method above works for the keyboardWillShow event. You'll need to add the corresponding one for when the keyboard hides, like this:
- (void)keyboardWillHideNotification:(NSNotification *)notification{
NSDictionary *userInfo = notification.userInfo;
double animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardEndFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
UIViewAnimationOptions rawAnimationCurve = (UIViewAnimationOptions)[userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
_toolBarBottomGuide.constant = 0.0f;
[UIView animateWithDuration:animationDuration delay:0.0 options:rawAnimationCurve animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
I'm trying to move a text field to the right when a button is pressed. It works fine, however when I click on another text field or any other element the text field re-appears in its current location. I browsed the internet and found it works when I don't have autolayout enabled, however I need autolayout for setting variable positions. Any advice? Here's the method that moves the box:
- (IBAction)EnterInfo:(id)sender {
CGRect newFrame = _UsernameField.frame;
newFrame.origin.x += 500; // shift right by 500pts
[UIView animateWithDuration:1.0
animations:^{
_UsernameField.frame = newFrame;
}];
}
New code for last question:
- (IBAction)EnterInfo:(id)sender {
[UIView animateWithDuration:1.0
animations:^{
_usernameX.constant = 130;
}];
}
If you have auto layout turned on, you can't manipulate the frame like that. You need a reference to a NSLayoutConstraint and update the constant.
like this:
myXConstraint.constant = originalX + 500;
Edit -- and then your animate block should look like this:
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutIfNeeded];
}];
This code was working beautifully in ios 7. However, with ios8 and xcode 6.0.1 it has stopped working. When a user clicked on a text field to enter text, the field animated to float just above the top of the keyboard so they can see what they are typing. Any thoughts on why this fails to work now. I can see it start to animate for a split second, but then the textfield disappears. Frustrating.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.4];
[UIView setAnimationBeginsFromCurrentState:YES];
textField.frame = CGRectMake(textField.frame.origin.x, (textField.frame.origin.y - 200.0),
textField.frame.size.width, textField.frame.size.height);
_searchBtn.frame = CGRectMake(_searchBtn.frame.origin.x, (_searchBtn.frame.origin.y - 200.0),
_searchBtn.frame.size.width, _searchBtn.frame.size.height);
[UIView commitAnimations];
textField.alpha = .75;
}
The problem is that your code adjusts your TextField's position by a fixed value of 200.0
This was probably great for iOS7 but things have changed in iOS8 for two reasons:
The system keyboard has an additional view for showing predicted words while typing
Custom keyboards can be as high as the developer chooses
You need to change your approach move moving the location of your TextField whenever the keyboard is shown or hidden using the following two notifications:
UIKeyboardWillShowNotification
UIKeyboardWillHideNotification
In the following thread I explain the problems that can arise and how to properly move your views around as the keyboard opens:
can't get correct value of keyboard height in iOS8
EDIT 1:
Assuming the textbox has an outlet called "yourTextBox", the code to modify the position of your textbox could look something like:
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
CGFloat keyboardHeight = <<calculated keyboard height as previously discussed>>;
CGFloat textBoxHeight = _yourTextBox.frame.size.height;
// Change the current frame of your textbox in order to reposition it
CGFrame textBoxFrame = _yourTextBox.frame;
textBoxFrame.origin.y = screenHeight - keyboardHeight - textBoxHeight;
_yourTextBox.frame = textBoxFrame;
Note: If you are using AutoLayout constraints to position your subviews you will need to avoid modifying the frame and change your constraints instead. Post if you are having problems in this area because it can get tricky.
Im curious about a feature in iOS. Please help me out here if you can.
Scenario: I am using a text box where name is entered. Its on lower half of the screen. Just below the text box is a label which displays the number of characters remaining(e.g.like in a twitter feed).
Problem: When i place the text box in upper half of the screen. both the text field and label are visible. But when I place them in lower half, the apple keyboard covers the label part.
Is there a way where I control the area covered in such a way that the label below is also visible?
I hope I have made myself clear enough.
Thanks.
Here i have used delegate method for UITextView Same way you can do for UITextField
-Here in this code when user starts entering values in textview it makes your view's hight lesser then its original with animation
-When user Ends Entering values, it will make your view's size original size.
-(void)textViewDidBeginEditing:(UITextView *)textView
{
CGRect frame = self.view.frame;
frame.origin.y = -100;
[self.view setFrame:frame];
[UIView commitAnimations];
}
-(void)textViewDidEndEditing:(UITextView *)textView
{
CGRect frame = self.view.frame;
frame.origin.y = 0;
[self.view setFrame:frame];
[UIView commitAnimations];
}
If you want to know about delegates this link helps you
Well in that case you have to move the textbox when the keyboard pops up.You can have the notification registered to know when the keyboard pops up and a scrollview to scroll the whole content up the screen can do the job for you
See this question,It explains well how to manage something like this
AFAIK You can't control the size of iOS native Keyboard, all you can and should be doing is, making them a subivew of a scroll view and scroll it up.
So the usual practice go something like this.
Subscribe to the Keyboard notification. UIKeyboardWillShowNotification
In the method which the Notification listener will be invoking, set the scrollView's content size accordingly and set the content offset.
self.scrollView.contentSize = CGSizeMake(320, 267);
self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, localKeyboardFrame.size.height, 0);
[self.scrollView scrollRectToVisible:<rect of view you want to scroll to> animated:YES];
Undo the changes when the keyboard hides, with the help of appropriate notification.UIKeyboardWillHideNotification
self.scrollView.contentInset = UIEdgeInsetsZero
And here is iOS Human Interface Guide's explanation on it.
Add following to your viewDidLoad Method
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showKeyboard) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(hideKeyboard) name:UIKeyboardWillHideNotification object:nil];
And after that-- Declare the following 2 methods in your .m file
-(void)showKeyboard {
[UIView beginAnimations:#"slide" context:nil];
[UIView setAnimationDuration:0.3];
self.view.transform = CGAffineTransformMakeTranslation(0, -100);
[UIView commitAnimations]; }
-(void)hideKeyboard {
[UIView beginAnimations:#"slide" context:nil];
[UIView setAnimationDuration:0.1];
self.view.transform = CGAffineTransformMakeTranslation(0, 0);
[UIView commitAnimations]; }