完美主义:实现iOS输入框自动移动

iOS“信息”中输入框交互式弹回。

在设计以输入框(接受并显示文本输入)为主的App用户界面时,常见的模式是输入框自动移动(一直显示在屏幕上),输入框位于键盘的顶部并随着键盘的移动而移动。

Apple的“消息”是一个很好的例子,它的UI就属于上述模式。从iOS 7起,它还可以通过滚动消息内容交互式弹回键盘。

这种模式很常见(尤其是聊天类App),但很少有App运用地像Apple的“消息”这么好。众所周知效仿的例子有Facebook MessengerWhatsApp

这并不是什么了不得的事,但也并不简单

能够把键盘交互式弹回并不是什么了不得的事,这可能是大多数用户都不会注意到的小细节。但是,它的确增强了App的手感。

然而不幸的是,解决方案并不明朗。开发人员已经尝试了很多方案并取得了不同程度的成功。有几个相关的开源项目,相关的博文和相关的StackOverflow提问,提供了从简单到复杂的解决方案。

简而言之,实现输入框自动移动很简单。但交互式弹回键盘就复杂了。以下是一些流行聊天App的尝试:

Google Hangouts:交互式弹回,输入框移动,键盘覆盖在上面随之移动。缺陷:弹回时,键盘和输入框之间的有空隙。

Slack for iPad:不支持交互式弹回,不过它在iPhone上是支持的。

Telegram、Line、微信:不支持交互式弹回。

收集资料

在寻找解决方案时,我发现了一些博客详细介绍了一些非常有用的技术,这完成了我们的解决方案的大半:赋给UIViewController根视图的inputAccessoryView一个非空的值,并让它在加载时立即响应(first responder)。详情见此:https://robots.thoughtbot.com/input-accessorizing-uiviewcontrollerhttp://derpturkey.com/uitextfield-docked-like-ios-messenger/

不管怎样,这至少说明了两点:

  • 输入框是键盘的窗口的子视图。我们并不想这样,尤其是对聊天App。
  • 输入框的宽度扩大了键盘的宽度。除了iPad上的拆分键盘。

酝酿解决方案

我们已经知道,赋给inputAccessoryView一个非空的值能达到我们想要的效果,但会出现一些警告。

那么,如果:

  • 我们赋给inputAccessoryView一个不可见视图
  • 同时为了得知键盘frame的变化(作为交互式弹回的结果),我们使用KVO(键值观察)观察不可见视图的父视图(即键盘)的bounds/center属性

汇总

解决方案设计

基于前面描述的想法,上图展示了解决方案的各关键部分。这里我们把不可见的视图称为“Pseudo Input Accessory View”。

  • 该解决方案的核心是键盘跟踪器。它通过两个来源跟踪并存储键盘状态:键盘通知(UIKit keyboard notifications)和Pseudo Input Accessory View父视图边界/中心变化的回调。
  • Pseudo Input Accessory View Coordinator管理Pseudo Input Accessory View的单例,同时提供了改变其高度的方法(为了满足输入框变宽的需要)。
  • Pseudo Input Accessory View由其Coordinator创建和管理。它使用KVO跟踪父视图的bounds/center属性并向Coordinator报告。

在这基础上,App在任何时候可以通过键盘跟踪器的实例查询当前键盘的状态。并且通过跟踪器的委托回调实时更新键盘。

根据键盘当前的frame调整输入框的布局,这就是随着键盘“自动移动”。在跟踪器的委托回调里,我们只需要在必要时重新调整布局。

管用吗?

是的,我认为我们已经搞定它了!

实现自动移动输入框的 Pie for iPad

以上是一个Pie for iPad的demo,并实现了自动伸缩输入框。

开源解决方案

在Pie中,我们努力打造最好的工作交流体验。但除此之外,我们也爱回馈社区。因此,我们打包了上述的解决方案包括一个demo作为一个小的开源库。

我们希望这对其他有类似要求的开发人员是有用的。如果你感兴趣,请参阅https://github.com/meiwin/NgKeyboardTracker

1 2 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部