【问题标题】:iMessage Style Receding Keyboard in an iOS AppiOS 应用中的 iMessage 样式后退键盘
【发布时间】:2011-12-08 12:10:48
【问题描述】:

我一直想知道是否可以在消息应用程序中复制 Apple iOS5 键盘的行为,而无需使用任何私有 API 调用。当您向下滚动到消息应用程序中的键盘时,键盘将折叠,留下更多空间来查看消息 - 试试看。

我找不到任何指向制作这个的东西,而不必开始跳过一些严重的箍来获取键盘视图的实例。而且我很确定 Apple 不会对此感到满意。

除了下面给出的答案之外,您还可以在此处看到我的实现的完整 xcode 项目: https://github.com/orta/iMessage-Style-Receding-Keyboard

【问题讨论】:

  • 我也一直在想这个问题——如果有人提出了解决方案,那就太好了。我假设“后退”是指 iOS 5 中消息应用程序的新键盘行为?
  • 我很确定所做的只是将键盘的上下文渲染为位图,其余的就是魔术(即跟踪滚动位置、来回移动渲染图像等)。
  • 希望我能多次对此投票。这正是我一直在寻找的。谢谢!
  • 其他 iOS5 应用程序是否显示此行为?
  • 这显然是一种有偏见的观点,但如果您正在寻找一种方法来以一种适用于各种视图类型的插入方式实现此键盘功能,我会推荐 DAKeyboardControl:@ 987654322@

标签: iphone keyboard uikit ios5


【解决方案1】:

在 iOS 7 中,UIScrollView 上有一个keyboardDismissMode 属性。 因此,只需将其设置为“UIScrollViewKeyboardDismissModeInteractive”,您就会得到这种行为。适用于 UIScrollView 子类,例如 UITableView。

self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

斯威夫特 3:

tableView.keyboardDismissMode = .interactive

或者在你的 UIScrollView 子类的属性检查器中的情节提要(如果使用它)中更改它。

【讨论】:

  • 你如何跟踪当前的键盘位置?
  • @JoãoNunes 我不知道,这是一个简单的案例 - 带有滚动视图,其中有关键盘位置的所有内容都会自动发生。如果您不是询问键盘通知...
  • 当您放下键盘时。并且您想根据键盘位置调整 UI。你怎么知道那个时候的键盘框架?或者你如何获得键盘移动的通知?
  • @JoãoNunes 通常你会听 UIKeyboardNotifications。但据我所知,他们只会告诉您“将显示键盘”“将隐藏键盘”之类的内容。如果您需要根据确切的键盘框架更改您的 UI,那真的是另一个问题,超出了本文的范围。
  • 它在您的答案范围内。因为当你有交互模式时,你需要跟踪键盘在哪里,或者至少你需要跟踪一些让你知道交互百分比的东西。在 iMessage APP 中当键盘上下移动时。输入框也会上下移动!
【解决方案2】:

这是一个不完整的解决方案,但它应该为您提供一个很好的起点。

将以下 ivars 添加到您的 UIViewController:

CGRect        keyboardSuperFrame; // frame of keyboard when initially displayed
UIView      * keyboardSuperView;  // reference to keyboard view

将 inputAccessoryView 添加到您的文本控制器。我创建了一个小视图作为附件视图插入:

accView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
accView.backgroundColor = [UIColor clearColor];
textField.inputAccessoryView = accView;

我把上面的代码加到-(void)loadView

在视图加载时注册接收 UIKeyboardDidShowNotification 和 UIKeyboardDidHideNotification:

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

添加方法以指定为通知的选择器:

// method is called whenever the keyboard is about to be displayed
- (void)keyboardWillShow:(NSNotification *)notification
{
    // makes keyboard view visible incase it was hidden
    keyboardSuperView.hidden = NO;
    return;
}
// method is called whenever the keyboard is displayed
- (void) keyboardDidShow:(NSNotification *)note
{
    // save reference to keyboard so we can easily determine
    // if it is currently displayed
    keyboardSuperView  = textField.inputAccessoryView.superview;

    // save current frame of keyboard so we can reference the original position later
    keyboardSuperFrame = textField.inputAccessoryView.superview.frame;
    return;
}

添加跟踪触摸和更新键盘视图的方法:

// stops tracking touches to divider
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGRect newFrame;
    CGRect bounds = [[UIScreen mainScreen] bounds];

    newFrame = keyboardSuperFrame;
    newFrame.origin.y = bounds.size.height;  

    if ((keyboardSuperView.superview))
        if (keyboardSuperFrame.origin.y != keyboardSuperView.frame.origin.y)
            [UIView animateWithDuration:0.2
                    animations:^{keyboardSuperView.frame = newFrame;}
                    completion:^(BOOL finished){
                                keyboardSuperView.hidden = YES;
                                keyboardSuperView.frame = keyboardSuperFrame;
                                [textField resignFirstResponder]; }];
    return;
}


// updates divider view position based upon movement of touches
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
   UITouch  * touch;
   CGPoint    point;
   CGFloat    updateY;

   if ((touch = [touches anyObject]))
   {
      point   = [touch locationInView:self.view];
      if ((keyboardSuperView.superview))
      {
         updateY = keyboardSuperView.frame.origin.y;
         if (point.y < keyboardSuperFrame.origin.y)
            return;
         if ((point.y > updateY) || (point.y < updateY))
            updateY = point.y;
         if (keyboardSuperView.frame.origin.y != updateY)
            keyboardSuperView.frame = CGRectMake(keyboardSuperFrame.origin.x,
                                                 point.y,
                                                 keyboardSuperFrame.size.width,
                                                 keyboardSuperFrame.size.height);
      };
   };
   return;
}

免责声明:

  • 当按照第一个响应退出时,键盘会在滑出屏幕之前移回其原始位置。为了使关闭键盘更加流畅,您首先需要创建一个动画来将键盘移出屏幕,然后隐藏视图。我将把这部分作为练习留给读者。
  • 我只在 iOS 5 模拟器和装有 iOS 5 的 iPhone 上测试过这个。我没有在早期版本的 iOS 上测试过。

我为测试这个概念而创建的 SlidingKeyboard 项目可从 GitHub 的 BindleKit 示例目录中获得:

https://github.com/bindle/BindleKit

编辑:更新示例以解决第一个免责声明。

【讨论】:

  • 我认为这是一个很好的实现,而且我不必做太多的事情就可以使用键盘。
  • 使用 inputAccessoryView 获取键盘句柄的技巧在 iOS 4 中有效。
  • 小错误修复:向上拖动键盘时,如果拖得太快,键盘将不会“粘”起来,而是会退出。这可以通过将if (point.y &lt; keyboardSuperFrame.origin.y) return; 替换为if (point.y &lt; keyboardSuperFrame.origin.y) { if (keyboardSuperView.frame.origin.y != keyboardSuperFrame.origin.y) { keyboardSuperView.frame = keyboardSuperFrame; } return; } 来解决
  • 另一个问题:如果你的视图没有占据整个窗口,触摸点可能有点偏离(在我的例子中,64点:导航栏44点,状态栏20点)。我在point = [touch locationInView:self.view]; 行中用 [self.view window] 修复了这个替换 self.view
  • 看起来这显示了适用于 iOS 8 及更低版本的正确动画。在 iOS 9 上,动画消失了。键盘只会在没有动画的情况下关闭!
【解决方案3】:

Vladimir 的简单解决方案将在用户向下滚动时隐藏键盘。但是要完成有关 iMessage 的问题,为了使 TextField 始终可见并固定在键盘顶部,您需要实现以下方法:

- (UIView *) inputAccessoryView {
     // Return your textfield, buttons, etc
}

- (BOOL) canBecomeFirstResponder {
    return YES;
}

Here's a good tutorial 分解更多

【讨论】:

  • 这实际上是实现 iMessage 样式消息输入工具栏的正确方式...哇..我无法相信 Apple 让它变得如此复杂,而且在同时,它是如何一直摆在我面前的。无论如何,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 2015-02-06
相关资源
最近更新 更多