以编程方式对齐 iPhone 键盘顶部的工具栏

Posted

技术标签:

【中文标题】以编程方式对齐 iPhone 键盘顶部的工具栏【英文标题】:Programmatically align a toolbar on top of the iPhone keyboard 【发布时间】:2008-10-01 16:43:33 【问题描述】:

在某些情况下,我想在 iPhone 键盘的顶部添加一个工具栏(例如,当您在 iPhone Safari 中导航表单元素时)。

目前我正在用常量指定工具栏的矩形,但是因为界面的其他元素在不断变化 - 屏幕顶部的工具栏和导航栏 - 每次我们进行小的界面更改时,工具栏都会失去对齐。

有没有办法以编程方式确定键盘相对于当前视图的位置?

【问题讨论】:

【参考方案1】:

ios 3.2 开始,有一种新方法可以实现此效果:

请注意,您使用的视图不应位于其他地方的视图层次结构中,也不应将其添加到某个超级视图中,这是为您完成的。

【讨论】:

让我试试。虽然它看起来是最好的方式。 哇。多么好的发现!谢谢(我做得很辛苦,很乱) 我有一个 UIToolbar,其中一个栏按钮项内有一个 UITextField,但是虽然我在第一次按下时将 textFields inputAccessoryView 设置为该工具栏,但工具栏会上升,但没有出现键盘。在第二次按下时,键盘与工具栏一起出现有什么想法吗? 但是如何在 UIWebView 上添加工具栏呢?:( 我已经通过替换标准 UIWebView 工具栏上的按钮来完成它(与删除它的代码相同)。【参考方案2】:

所以基本上:

在init方法中:

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:@selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil];

然后有上面提到的方法来调整bar的位置:

-(void) keyboardWillShow:(NSNotification *) note

    CGRect r  = bar.frame, t;
    [[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &t];
    r.origin.y -=  t.size.height;
    bar.frame = r;

可以通过将位置变化包装在动画中来使其漂亮

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
//...
    [UIView commitAnimations];

【讨论】:

今天早上在翻看我的旧东西,发现这是一个更好、最全面的答案。谢谢! 这个答案在一年多之后仍然非常相关。在开发与此相关的东西时,它帮助我克服了困难。 只是警告人们现在偶然发现这个问题:UIKeyboardBoundsUserInfoKey 现在在 iPhone OS 3.2 中已弃用。还有其他类似的,例如 UIKeyboardFrameBeginUserInfoKey 提供相同的信息。 在 iOS3.2 中,UITextField 和 UITextView 上的 inputAccessoryView 属性甚至有更好的新方法。 这个答案帮助了很多,但有点过时了。您应该使用UIKeyboardFrameEndUserInfoKey 来获取键盘的最后一帧(在屏幕坐标中)。您还可以使用UIKeyboardAnimationDurationUserInfoKeyUIKeyboardAnimationCurveUserInfoKey 来获取完全匹配键盘行为所需的其余参数。【参考方案3】:

这是基于existing answer from tonklon - 我只是添加一个代码sn-p,它在键盘顶部显示一个半透明的黑色工具栏,以及右侧的“完成”按钮:

UIToolbar *toolbar = [[[UIToolbar alloc] init] autorelease];
[toolbar setBarStyle:UIBarStyleBlackTranslucent];
[toolbar sizeToFit];

UIBarButtonItem *flexButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneButton =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(resignKeyboard)];

NSArray *itemsArray = [NSArray arrayWithObjects:flexButton, doneButton, nil];

[flexButton release];
[doneButton release];
[toolbar setItems:itemsArray];

[aTextField setInputAccessoryView:toolbar];

-resignKeyboard 看起来像:

-(void)resignKeyboard 
  [aTextField resignFirstResponder];

希望对某人有所帮助。

【讨论】:

只是添加了一点关于获得下一个前一个的评论。 UISegmentedControl *segmentControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Previous", @"Next", nil]]; [segmentControl setSegmentedControlStyle:UISegmentedControlStyleBar]; [segmentControl addTarget:self action:@selector(nextPrevious:) forControlEvents:UIControlEventValueChanged]; 对@TraustiThor 评论的补充:您必须将分段控件包装在 UIBarButtonItem 中才能将其添加到工具栏。 优秀——这就是我需要的所有代码。感谢发帖:) 但是 UIWebView 呢?如何为其添加工具栏?【参考方案4】:

如果您注册键盘通知,即UIKeyboardWillShowNotificationUIKeyboardWillHideNotification等,您收到的通知将包含userInfo dict(UIKeyboardBoundsUserInfoKey)中的键盘边界。

请参阅UIWindow 类参考。

【讨论】:

【参考方案5】:

在 3.0 及以上版本中,您可以从通知的userInfo 字典中获取动画持续时间和曲线。

例如,要为视图大小设置动画以为键盘腾出空间,请注册UIKeyboardWillShowNotification 并执行以下操作:

- (void)keyboardWillShow:(NSNotification *)notification

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
    [UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];

    CGRect frame = self.view.frame;
    frame.size.height -= [[[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue].size.height;
    self.view.frame = frame;

    [UIView commitAnimations];

UIKeyboardWillHideNotification做一个类似的动画。

【讨论】:

看起来在 3.0 SDK 上执行此操作的更好方法,感谢您的发帖! 感谢您的代码。这很有帮助。但是,当我将 UITextView 设置为 viewDidLoad 中的第一响应者时,UIToolBar 不会随着 self.view 的大小调整而移动。你知道为什么吗? @RyanJM:becomingFirstResponder 和 resignFirstResponder 当视图离开屏幕时有奇怪的行为。您应该改为从 viewWillAppear 方法调用 becomeFirstResponder。【参考方案6】:

创建此方法并在 ViewWillLoad 上调用它:

        - (void) keyboardToolbarSetup

    if(self.keyboardToolbar==nil)
        
        self.keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];

        UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:self action:@selector(anyAction)];

        UIBarButtonItem *extraSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(anyOtherAction)];


        NSArray *toolbarButtons = [[NSArray alloc]initWithObjects:cancelButton,extraSpace,doneButton, nil];

        [self.keyboardToolbar setItems:toolbarButtons];

        self.myTextView.inputAccessoryView=self.keyboardToolbar;
        

【讨论】:

【参考方案7】:

没有办法 (AFAIK) 获取键盘视图的尺寸。然而,它是不变的,至少在迄今为止的每个 iPhone 版本中都是如此。

如果您将工具栏位置计算为与视图底部的偏移量,并考虑视图的大小,那么您不必担心导航栏是否存在。

例如

#define KEYBOARD_HEIGHT 240 // example - can't remember the exact size
#define TOOLBAR_HEIGHT 30

toolBarRect.origin.y = viewRect.size.height - KEYBOARD_HEIGHT - TOOLBAR_HEIGHT;

// move toolbar either directly or with an animation

您可以轻松地创建一个 keyboardHeight 函数来代替定义,该函数根据键盘是否显示返回大小,并将此工具栏定位移动到一个单独的函数中,以重新组织您的布局。

它还可能取决于您在哪里进行此定位,因为您的视图大小可能会根据您的导航栏设置在加载和显示之间发生变化。我相信最好的地方是 viewWillAppear。

【讨论】:

这很好用,谢谢!到目前为止,我一直在 UIKeyboardDidShowNotification 触发的选择器中进行此计算。我只在几个地方进行了测试,但它看起来是个不错的地方。 从 5.0 开始,键盘大小不再是静态的。

以上是关于以编程方式对齐 iPhone 键盘顶部的工具栏的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式计算 UIImagePickerController 工具栏的高度?

使用不使用硬编码的 CGRect 和最小数量的约束以编程方式将堆栈视图与屏幕顶部对齐

Swift:以编程方式在键盘上方添加 UIButton

Android 编辑文本动态时滑动到对应item底部和输入框(右边“发送”按钮下边软键盘)顶部对齐

在 PhoneGap 应用程序中以编程方式在 iPhone 上显示软键盘?

UIToolbar外观用于以编程方式添加工具栏