使用iOS SDK:
我有一个带UITextFields的UIView,可以启动键盘。我需要它能够:
启动键盘后,允许滚动UIScrollView的内容以查看其他文本字段自动“跳转”(通过向上滚动)或缩短
我知道我需要一个UIScrollView。我已经尝试将UIView的类更改为UIScrollView,但仍然无法上下滚动文本框。
我需要UIView和UIScrollView吗?一个在另一个里面吗?
要自动滚动到活动文本字段,需要执行哪些操作?
理想情况下,尽可能多的组件设置将在Interface Builder中完成。我只想编写需要的代码。
注意:我使用的UIView(或UIScrollView)是由一个选项卡(UITabBar)启动的,它需要正常工作。
我正在添加滚动条,只为键盘出现时使用。尽管不需要它,但我觉得它提供了一个更好的界面,例如,用户可以滚动和更改文本框。
当键盘上下移动时,我可以改变UIScrollView的框架大小。我只是在使用:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
//Keyboard becomes visible
scrollView.frame = CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y,
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50); // Resize
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
// Keyboard will hide
scrollView.frame = CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y,
scrollView.frame.size.width,
scrollView.frame.size.height + 215 - 50); // Resize
}
然而,这不会自动“向上移动”或将可见区域中的下部文本字段居中,这是我真正想要的。
实际上,最好只使用苹果的实现,正如文档中所提供的那样。然而,他们提供的代码是错误的。将keyboardWasShow:注释下方的部分替换为以下内容:
NSDictionary* info = [aNotification userInfo];
CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
CGSize kbSize =keyPadFrame.size;
CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
CGRect aRect = self.view.bounds;
aRect.size.height -= (kbSize.height);
CGPoint origin = activeRect.origin;
origin.y -= backScrollView.contentOffset.y;
if (!CGRectContainsPoint(aRect, origin)) {
CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height));
[backScrollView setContentOffset:scrollPoint animated:YES];
}
苹果代码存在以下问题:(1) 他们总是计算该点是否在视图的框架内,但它是一个ScrollView,因此它可能已经滚动,您需要考虑该偏移:
origin.y -= scrollView.contentOffset.y
(2) 他们按键盘的高度移动contentOffset,但我们希望相反(我们希望按屏幕上可见的高度而不是不可见的高度移动contentOffset):
activeField.frame.origin.y-(aRect.size.height)
使用ViewModifier快速切换UI
可以使用SwiftUI的ViewModifier。这要简单得多。
import SwiftUI
import Combine
struct KeyboardAwareModifier: ViewModifier {
@State private var keyboardHeight: CGFloat = 0
private var keyboardHeightPublisher: AnyPublisher<CGFloat, Never> {
Publishers.Merge(
NotificationCenter.default
.publisher(for: UIResponder.keyboardWillShowNotification)
.compactMap { $0.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue }
.map { $0.cgRectValue.height },
NotificationCenter.default
.publisher(for: UIResponder.keyboardWillHideNotification)
.map { _ in CGFloat(0) }
).eraseToAnyPublisher()
}
func body(content: Content) -> some View {
content
.padding(.bottom, keyboardHeight)
.onReceive(keyboardHeightPublisher) { self.keyboardHeight = $0 }
}
}
extension View {
func KeyboardAwarePadding() -> some View {
ModifiedContent(content: self, modifier: KeyboardAwareModifier())
}
}
在你看来
struct SomeView: View {
@State private var someText: String = ""
var body: some View {
VStack {
Spacer()
TextField("some text", text: $someText)
}.KeyboardAwarePadding()
}
}
KeyboardAwarePadding()将自动为视图添加填充。它更优雅。
在这里,我找到了处理键盘的最简单的解决方案。
您只需复制粘贴到示例代码下面,然后更改文本字段或任何要向上移动的视图。
步骤-1
只需在控制器中复制粘贴以下两种方法
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
- (void)deregisterFromKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
步骤-2
在视图中注册和注销键盘通知WillAppear和viewWillDisappear方法。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self registerForKeyboardNotifications];
}
- (void)viewWillDisappear:(BOOL)animated
{
[self deregisterFromKeyboardNotifications];
[super viewWillDisappear:animated];
}
步骤-3
灵魂部分来了,只要替换你的文本字段,然后改变高度你想向上移动多少。
- (void)keyboardWasShown:(NSNotification *)notification
{
NSDictionary* info = [notification userInfo];
CGSize currentKeyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
//you need replace your textfield instance here
CGPoint textFieldOrigin = self.tokenForPlaceField.frame.origin;
CGFloat textFieldHeight = self.tokenForPlaceField.frame.size.height;
CGRect visibleRect = self.view.frame;
visibleRect.size.height -= currentKeyboardSize.height;
if (!CGRectContainsPoint(visibleRect, textFieldOrigin))
{
//you can add yor desired height how much you want move keypad up, by replacing "textFieldHeight" below
CGPoint scrollPoint = CGPointMake(0.0, textFieldOrigin.y - visibleRect.size.height + textFieldHeight); //replace textFieldHeight to currentKeyboardSize.height, if you want to move up with more height
[self.scrollView setContentOffset:scrollPoint animated:YES];
}
}
- (void)keyboardWillBeHidden:(NSNotification *)notification
{
[self.scrollView setContentOffset:CGPointZero animated:YES];
}
参考:好吧,请感谢这位分享了这个漂亮的代码片段、干净的解决方案的人。
希望这对外面的人会很有帮助。
试试这个,效果很好:
if Firstnametxt.text == "" || Passwordtxt.text == "" || emailtxt.text == ""
{
if Firstnametxt.text == ""
{
Firstnametxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal)
Firstnametxt.becomeFirstResponder()
}
else if Passwordtxt.text == ""
{
Passwordtxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal)
Passwordtxt.becomeFirstResponder()
}
else if emailtxt.text == ""
{
emailtxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal)
emailtxt.becomeFirstResponder()
}
}
else
{
let isValidEmail:Bool = self.isValidEmail(emailtxt.text!)
if isValidEmail == true
{
}
else
{
emailtxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal)
emailtxt.becomeFirstResponder()
}
}