iOS 8 Keyboard Hides My Textview

iOS 8 keyboard hides my textview

@Oleg's solution is good but it doesn't take into consideration keyboard changes in size while its already showing.. also, he hardcoded the animation duration and a few other parameters. See my solution below:

Add an observer of UIKeyboardWillChangeFrameNotification to the viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardFrameWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];

And then add the method:

- (void)keyboardFrameWillChange:(NSNotification *)notification
{
CGRect keyboardEndFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardBeginFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
UIViewAnimationCurve animationCurve = [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
NSTimeInterval animationDuration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] integerValue];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];

CGRect newFrame = self.view.frame;
CGRect keyboardFrameEnd = [self.view convertRect:keyboardEndFrame toView:nil];
CGRect keyboardFrameBegin = [self.view convertRect:keyboardBeginFrame toView:nil];

newFrame.origin.y -= (keyboardFrameBegin.origin.y - keyboardFrameEnd.origin.y);
self.view.frame = newFrame;

[UIView commitAnimations];
}

Don't forget to remove the keyboard observer in both viewDidUnload and in Dealloc.

iPhone - Keyboard hides TextField

To scroll when the keyboard appears, I like this tutorial from Cocoa With Love.

To dismiss the number keypad, you can put a custom "Done" button on the keypad or make an invisible button over the rest of the screen. I have done the latter with code, but this tutorial uses Interface Builder.

iOS 8 Keyboard - disturbing my UI

Ok, this worked for me.

First I binded a NSLayoutConstraint that already had.

__weak IBOutlet NSLayoutConstraint *bottomInputConstraint;

Then I subscribed to the keyboard's notification on viewDidLoad.

- (void)viewDidLoad{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
}

keyboardWillShow: method looks something like this:

- (void)keyboardWillShow:(NSNotification *)aNotification{
NSDictionary* keyboardInfo = [aNotification userInfo];
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];

bottomInputConstraint.constant = keyboardFrameBeginRect.size.height + kBottomKeyboardMargin;
}

iOS 15 Keyboard hides textfield

You really have a lot of code in there - and two reasons to clean it up:

  1. To get a good answer, you need to post a minimal, reproducible example, which may also help you debug the code before posting it
  2. Many lines of code are redundant or useless, for example:
  • Why using things like HStack{Spacer()} instead of Spacer(), which by the way is not needed in this context?
  • Why having a stack that has only another stack inside?

Coming to your issue, the problem is that one of the redundant modifiers is preventing the text file to move up, and this is the line to delete:

.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)

Why setting a frame that is as high and large as much as the screen? This is forcing the text field to stay at the bottom.

I tried to do some clean up, I bet some more can be done - see the code below, now the keyboard does not cover the text field anymore:

struct MessagingPage: View {

// Removed some lines of code to reproduce your issue
@State var screenWidth = UIScreen.main.bounds.width
@State var imageSize = UIScreen.main.bounds.width / 12
@State var text = ""
@State var show = false
@Environment(\.presentationMode) var presentationMode

var body: some View {
NavigationView{

// What is the purpose of this ZStack???
// ZStack{
VStack{

HStack{
Spacer()

NavigationLink(destination: Text("Hello")) {
Text("Top bar")
}
Spacer()

HStack{
Button{
presentationMode.wrappedValue.dismiss()
} label: {
Image(systemName: "chevron.down")
.font(.title)
.foregroundColor(.white)
}
}
.padding(.trailing)

}
.padding(.top, 30)
.frame(height: 75)
.background(Color.black)

ScrollView{

// All the views inside the Scrollview need to be inside a VStack
VStack {

// Why this spacer???
// Spacer()
ForEach(0..<2){ num in
HStack{
Spacer()
HStack{
Text("Hello username")
.foregroundColor(.orange)
}
.padding()
.background(Color.black)
.cornerRadius(15)
.shadow(color: .orange, radius: 2)
}
.padding(.horizontal)
.padding(.top, 8)
}
HStack{Spacer()}

HStack{
HStack{
Text("User is unable to receive your message at this time. Please try again at a later time.")
.foregroundColor(.green)
}
.padding()
.background(Color.black)
.cornerRadius(15)
.shadow(color: .green, radius: 2)

Spacer()
}
.padding(.horizontal)
.padding(.top, 8)

// Why a Spacer inside an HStack???
// HStack{Spacer()}
}
.background(Color.black)
}


// What is the purpose of this ZStack???
// ZStack{

// Why an HStack that has only an HStack inside??
// HStack{

// Why an HStack that has only an HStack inside??

// HStack{

HStack{
TextField("Say Something...", text: self.$text)
.frame(width: screenWidth - 200, height: screenWidth/25)
.foregroundColor(.cyan)
.accentColor(.cyan)
.background(Color.white)
.textContentType(.emailAddress)

if !text.isEmpty{
Button{
print(text)
self.text = ""
}label: {
Image(systemName: "paperplane")
.foregroundColor(.cyan)
.font(.system(size: 20))
}
}
else{
Button{
print("Show more options")
}label: {
Image(systemName: "plus")
.foregroundColor(.cyan)
.font(.system(size: 20))
}
}

}

// Are you sure you want set the height of this stack based on the width?
// .frame(width: screenWidth - 150, height: screenWidth/25)
.frame(width: screenWidth - 150)
.padding()
.background(Color.black)
.cornerRadius(30)
.shadow(color: .black, radius: 5)
.padding(.bottom,5)
// }

// }
.padding(.bottom, 50)
.frame(width: screenWidth)
// }
}
// }

// Why setting a frame that is high and large as much as the screen??
// .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
.background(Color.black)
.navigationBarTitle("")
.navigationBarHidden(true)

}

}
}

Sample Image

iPhone Keyboard Covers UITextField

The usual solution is to slide the field (and everything above it) up with an animation, and then back down when you are done. You may need to put the text field and some of the other items into another view and slide the view as a unit. (I call these things "plates" as in "tectonic plates", but that's just me). But here is the general idea if you don't need to get fancy.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField: textField up: YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField: textField up: NO];
}

- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed

int movement = (up ? -movementDistance : movementDistance);

[UIView beginAnimations: @"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}


Related Topics



Leave a reply



Submit