有没有办法防止键盘被解雇?
Posted
技术标签:
【中文标题】有没有办法防止键盘被解雇?【英文标题】:Is there a way to prevent the keyboard from dismissing? 【发布时间】:2011-05-15 01:57:37 【问题描述】:我知道这与大多数帖子相反,但我希望键盘保持向上即使按下“键盘向下”按钮。
具体来说,我有两个UITextField
s 的视图。使用以下委托方法
- (BOOL)textFieldShouldReturn:(UITextField *)textField
return NO;
即使用户按下键盘上的Done
按钮或点击屏幕上的任何其他位置(除了键盘右下角那个讨厌的键盘向下按钮),我也能够保持键盘向上。
我像模态视图一样使用这个视图(尽管该视图与被推送到 UINavigationController 中的 ViewController 相关联),所以从用户的角度来看,它确实最适合让键盘始终保持打开状态。如果有人知道如何实现这一点,请告诉我!谢谢!
更新仍然没有解决方案!当Done
被按下时,它会触发textFieldShouldReturn
,但是当Dismiss
按钮被按下时,它会触发textFieldDidEndEditing
。我无法阻止 textField
结束编辑,否则它永远不会消失。不知何故,我真的很想有一种方法可以检测到Dismiss
按钮并忽略它。如果你知道方法,请赐教!
【问题讨论】:
这是您设计的 UI 交互不符合 Apple 官方指南的情况之一。我认为你应该花时间重新思考应用程序,而不是“打破”基本 ios SDK 的规则。 哪条指南建议在屏幕上保留带有文本字段的键盘是糟糕的 UI? UI 交互很差,无法让用户移除键盘,就像在所有 iOS 应用程序中一样。如果您查看 iOS 应用程序的默认外观和感觉,您正在尝试做一些“奇怪”的事情。我不记得有一个(有效)应用程序不能让我卸下键盘。这就是我要你思考的问题。 我尊重您对此事的看法,但不同意。我相信关闭键盘只会出错,在这种特殊情况下,用户可能会不知如何与屏幕交互。在这种情况下,我认为键盘类似于选择器,但我很欣赏你的观点。 我应该补充一点,我的评估基于测试用户的反馈,我相信这胜过假设场景。 【参考方案1】:有办法做到这一点。 因为UIKeyboard
是UIWindow
的子类,所以唯一一个大到足以进入UIKeyboard
的方式是另一个UIWindow
.
- (void)viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(coverKey) name:UIKeyboardDidShowNotification object:nil];
[super viewDidLoad];
- (void)coverKey
CGRect r = [[UIScreen mainScreen] bounds];
UIWindow *myWindow = [[UIWindow alloc] initWithFrame:CGRectMake(r.size.width - 50 , r.size.height - 50, 50, 50)];
[myWindow setBackgroundColor:[UIColor clearColor]];
[super.view addSubview:myWindow];
[myWindow makeKeyAndVisible];
这适用于 iPhone 应用程序。 iPad 没试过。您可能需要调整myWindow
的大小。另外,我没有对myWindow
进行任何内存管理。所以,也考虑这样做。
【讨论】:
我应该补充一点,我假设了一个实例字段方法,其中 previousTextField 和 someTextField 是实例字段。因此,keyboardWillHide 方法不需要参数。 即使这涵盖了“隐藏键盘”按钮,您仍然应该使用 UITextField 委托方法处理第一响应者逻辑,以便适当的 UITextField 接收来自 UIKeyboard 的输入。 我对这个想法的问题是它取决于键盘的特定布局/语言。总的来说,我并不反对 hack,但必须针对每个键盘以及不同的方向定制这个。 您可能只需要创建一个实用程序类,它会根据方向更改、UITextField 之间的焦点更改等触发类方法。类方法将负责添加/删除/修改所需的 UIWindows覆盖键盘的特定区域。这很骇人听闻,但它可能是唯一的方法。 由于赏金即将到期,我在忘记之前奖励它。这个解决方案并非没有问题,我仍然希望有一个更好的解决方案(因此我不接受这个答案),但在建议的答案中,这是唯一能达到预期结果的解决方案。它绝对值得我赏金。谢谢 JacobB。【参考方案2】:我想我找到了一个很好的解决方案。
添加一个 BOOL 作为实例变量,我们称之为shouldBeginCalledBeforeHand
然后实现以下方法:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
shouldBeginCalledBeforeHand = YES;
return YES;
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
return shouldBeginCalledBeforeHand;
- (void)textFieldDidBeginEditing:(UITextField *)textField
shouldBeginCalledBeforeHand = NO;
还有
- (BOOL)textFieldShouldReturn:(UITextField *)textField
return NO;
防止键盘随着返回按钮消失。诀窍是,从一个文本字段到另一个文本字段的焦点切换将预先触发 textFieldShouldBeginEditing。如果按下关闭键盘按钮,则不会发生这种情况。在文本字段获得焦点后重置标志。
【讨论】:
@PengOne 找到了另一个解决方案。 这仅适用于模态视图,但它可以防止键盘完全消失,即使视图消失了:-( 你想把这个分成两个答案吗?我更喜欢旧的解决方案,因为虽然不完美,但它不会破坏其他任何东西。由于解决方案如此不同,我认为将它们分开是有意义的。 @PengOne 划分了答案,你能添加一些代码来告诉我你是如何关闭模态视图的吗?我认为键盘不消失的问题可以解决。 谢谢!这有助于我在使用页面视图控制器时防止键盘消失。【参考方案3】:旧的不完美的解决方案
我只能想到一个不完美的解决方案。收听通知UIKeyboardDidHideNotification
并再次使文本字段成为第一响应者。这会将键盘移出视线并再次移回。您可以通过监听 UIKeyboardWillHideNotification 来记录哪个文本字段是最后一个 firstResponder,并将焦点放在 didHide 中。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
...
- (void)keyboardDidHide:(id)sender
[myTextField becomeFirstResponder];
【讨论】:
+1,因为它是一个接近解决方案。键盘下降然后备份的事实使这一点变得不那么好。我真的希望有一个-(BOOL)keyboardWillHide
方法,我可以从中返回 NO
。
有一个 UIKeyboardWillHideNotification,见UIWindow doc,使用它应该让你设置另一个文本字段作为第一响应者,这应该取消键盘隐藏/显示动画(但我不是一定)。
@progrmr 试过了,没用。也许您对此有解决方案?【参考方案4】:
对于 iOS 9/10 和 Swift 3,使用它来创建一个与“隐藏键盘”重叠的矩形 - 按钮
override func viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(coverKey), name: .UIKeyboardDidShow, object: nil)
func coverKey()
if let keyboardWindow = UIApplication.shared.windows.last
let r = UIScreen.main.bounds
let myWindow = UIWindow.init(frame: CGRect(x: r.size.width - 50 , y: r.size.height - 50, width: 50, height: 50))
myWindow.backgroundColor = UIColor.clear
myWindow.isHidden = false
keyboardWindow.addSubview(myWindow)
keyboardWindow.bringSubview(toFront: myWindow)
请注意,这会将子视图添加到键盘窗口而不是主窗口
【讨论】:
运行良好,需要在键盘隐藏时移除此视图? 添加到键盘窗口后,如果隐藏键盘应该会自动移除。【参考方案5】:尝试在键盘关闭按钮的顶部添加一个自定义项,这样用户将无法点击关闭按钮。我在我的一个应用程序中使用了这种方法。
- (void)addButtonToKeyboard
// create custom button
UIButton *blockButton = [UIButton buttonWithType:UIButtonTypeCustom];
blockButton.frame = //set the frame here, I don't remember the exact frame
[blockButton setImage:[UIImage imageNamed:@"block_button.png"] forState:UIControlStateNormal];
// locate keyboard view
UIWindow *appWindows = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
UIView *keyboard;
for (int i=0; i<[appWindows.subviews count]; i++)
keyboard = [appWindows.subviews objectAtIndex:i];
// keyboard found, add the button
if ([[keyboard description] hasPrefix:@"<UIPeripheralHost"] == YES && [self.textField isFirstResponder])
[keyboard addSubview:doneButton];
【讨论】:
这是 JabocB 的解决方案。一个 hack,而且是特定于键盘的。【参考方案6】:试试这个...
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
return NO;
您可以使用 Nick Weaver 提到的通知。
【讨论】:
如多处提到的,有多个文本字段,因此实现这一点将不允许用户在文本字段之间移动。以上是关于有没有办法防止键盘被解雇?的主要内容,如果未能解决你的问题,请参考以下文章
Swift 防止 TabBar 在键盘处于活动状态时向上移动
如何防止通过推送 SFSafariViewController 解雇 UITabBarController?