我正在努力实现与Apple的消息应用程序中底部文本输入栏类似的定位行为。
我尝试了很多方法,搜索得很高,也有很多类似的问题,但都没有令人满意。
指定:
UIToolbar
建议的解决方案:
此解决方案不符合第二个要求的特殊情况(当键盘出现并消失时,工具栏将跟随键盘):
UIScrollViewKeyboardDismissMode
。它启用了用于解除键盘的交互式手势。当用户翻过键盘的顶部边缘时,键盘框架逐渐跟随。此解决方案无法容纳此行为,只是将工具栏搁置在其动画位置。此外,此解决方案也无法满足第三个要求的特殊情况(当键盘可见时,工具栏应保持在键盘顶部):
此解决方案的另一个问题是:
下一个提议的解决方案:
UIResponder
的{{1}} 这个解决方案似乎是Apple打算支持这种行为的方式,因为它解决了手动设置工具栏动画的所有缺点。但是这个解决方案完全忽略了第四个要求(当键盘被隐藏时,工具栏保持(“停靠”)在视图的底部)。
似乎解决方案是使用inputAccessoryView
的{{1}},但不知何故使UIResponder
不会移动到视图下方。我正在寻找干净的代码来实现这一目标。在其他地方有精心制作的,几乎是高贵的尝试,但如上所述,它们不符合要求。
在我的特定情况下,我希望使用inputAccessoryView
的工具栏,这会带来其他问题,因为这不是inputAccessoryView
的预期行为。无论如何,我愿意介绍一些hacky修复来实现这一目标。
答案 0 :(得分:56)
Jason Foreman(@threeve)刚刚展示了“解决方案”。在视图控制器上(是的,查看控制器)添加inputAccessoryView:
并返回要在底部停靠的视图并使用键盘移动。它只是有效。视图实际上不需要在视图层次结构中,它将由视图控制器自动插入。
编辑:同时实现canBecomeFirstResponder并返回YES(如Max Seelemann所述)。 reloadInputViews也很方便。
答案 1 :(得分:31)
Jonathan Badeen提到的solution为我工作。这是来自Arik的代码,展示了如何实现它(这应该放在适当的视图控制器中):
- (BOOL)canBecomeFirstResponder{
return YES;
}
- (UIView *)inputAccessoryView{
return self.inputAccessoryToolbar;
// where inputAccessoryToolbar is your keyboard accessory view
}
答案 2 :(得分:9)
对于那些寻找Swift版本的人:
将您的工具栏(在我的情况下' myToolBar
')连接到您的视图控制器。然后覆盖canBecomeFirstResponder
方法并覆盖getter inputAccessoryView
变量。另外,请不要忘记添加self.myToolBar.removeFromSuperview()
,否则xcode会抱怨。
class ViewController: UIViewController {
@IBOutlet var myToolBar: UIToolbar!
override func canBecomeFirstResponder() -> Bool {
return true
}
override var inputAccessoryView:UIView{
get{
return self.myToolBar
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.myToolBar.removeFromSuperview()
}
}
答案 3 :(得分:6)
Slack的优秀人员提供了一个优秀,易于实施的开源解决方案: SlackTextViewController 。
以下是如何通过四个步骤实现带有停靠工具栏的视图:
创建一个继承自MessageViewController
的{{1}},无需再编写任何代码:
SLKTextViewController
向Slack团队提供道具,以提取这样一个有用的吊舱。
答案 4 :(得分:2)
所以我知道这是一个老帖子,我不确定你是否解决了这个问题,但我找到了一种方法来实现这个目标。我相信inputAccessoryView中存在一个错误,但我创建了一个hacky解决方案来表现消息应用的方式。我想我提供了所有必要的代码来实现这个工作。我将尝试在不久的将来某个时间创建一个更合适的博客文章,并对我的发现进行更深入的描述。有任何问题,请告诉我。
@property(nonatomic,assign)BOOL isFirstKeyboard; //workaround for keyboard bug
@property(nonatomic,assign)BOOL isViewAppear;
@property(nonatomic,strong)ChatBarView *chatView; //custom chat bar view
@property(nonatomic,strong)UIView *footerPadView; //just to add some nice padding
////////////////////////////////////////////////////////////////////////////////////////////////////
//in the view did load
- (void)viewDidLoad
{
//more app specific code...
self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
self.chatView.textView.inputAccessoryView = self.chatView;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
-(void)done
{
self.isFirstKeyboard = YES;
[self.chatView.textView becomeFirstResponder];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
- (void) moveTextViewForKeyboard:(NSNotification*)aNotification up:(BOOL)up
{
if(!self.isViewAppear)
return;
//NSLog(@"keyboard is: %@", up ? @"UP" : @"Down");
if(!up && !self.isFirstKeyboard)
[self performSelector:@selector(done) withObject:nil afterDelay:0.01];
else if(!up & self.isFirstKeyboard)
{
self.isFirstKeyboard = NO;
[self.view addSubview:self.chatView];
CGRect frame = self.chatView.frame;
frame.origin.y = self.view.frame.size.height - self.chatView.frame.size.height;
self.chatView.frame = frame;
}
else
{
NSDictionary* userInfo = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
// Animate up or down
[UIView beginAnimations:nil context:nil];
if(up)
[UIView setAnimationDuration:0.2];
else
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:animationCurve];
CGRect frame = self.footerPadView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
if (up)
frame.size.height = keyboardFrame.size.height - self.chatView.frame.size.height;
else
frame.size.height = 0;
self.footerPadView.frame = frame;
self.tableView.tableFooterView = self.footerPadView;
[UIView commitAnimations];
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)keyboardWillShow:(NSNotification *)aNotification {
[self moveTextViewForKeyboard:aNotification up:YES];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)keyboardWillHide:(NSNotification *)aNotification
{
[self moveTextViewForKeyboard:aNotification up:NO];
}
////////////////////////////////////////////////////////////////////////////////////////////////////