ios 如何添加一个inputAccessoryView?
ios How to add an inputAccessoryView?
我正在尝试复制 Facebook Messenger 应用程序,其中有一个 UITextView
附加到键盘顶部。
由于此应用程序的性质,我需要附加 view
,而不是在出现键盘时手动上下滚动 ScrollView
。
这可以通过使用 inputAccessoryView
.
来实现
我阅读了它的文档 here。
文档非常简短并说:
“这 属性 通常用于将附件视图附加到为 UITextField 和 UITextView 对象提供的系统提供的键盘。
此只读 属性 的值为 nil。如果您想将自定义控件附加到系统提供的输入视图(例如系统键盘)或自定义输入视图(您在 inputView 属性 中提供的视图),请将此 属性 重新声明为已读-写在 UIResponder 子类中。
然后您可以使用此 属性 来管理自定义附件视图。当接收者成为第一响应者时,响应者基础结构在显示之前将附件视图附加到适当的输入视图。"
我试过声明 属性
@interface CommentViewController ()
@property (nonatomic, readwrite, retain) UIView *inputAccessoryView;
@end
然后设置它:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 20, 320, 100)];
[view setBackgroundColor:[UIColor greenColor]];
self.inputAccessoryView = view;
}
然后我尝试调用这两个:
[self.tableView becomeFirstResponder];
[view becomeFirstResponder];
没有任何反应。我做错了什么?
*注意 - 额外信息:我正在使用 UITableViewController
,我想将 UIView
作为 inputAccessoryView
附加。一旦我的视图开始工作,我将添加一个 UITextView
等等,但这主要是一个示例。
非常感谢任何帮助!
将输入附件添加到您的 textField 或 textView 而不是纯 UIView。
self.mytextField.inputAccessoryView = view;
inputAccessoryView
是 UIResponder
class 的 属性。它允许您定义自定义输入附件视图,以在接收者成为第一响应者时显示。通常应将 UIToolBar
的实例设置为附属视图。
工具栏示例:
MYInputAccessoryToolbar.h
typedef void (^MYInputAccessoryToolbarDidDoneTap)(id activeItem);
@interface MYInputAccessoryToolbar : UIToolbar
@property (nonatomic, copy) MYInputAccessoryToolbarDidDoneTap didDoneTapBlock;
+ (instancetype)toolbarWithInputItems:(NSArray *)items;
- (instancetype)initWithInputItems:(NSArray *)items;
- (void)addInputItem:(id)item;
- (void)goToNextItem;
- (void)goToPrevItem;
@end
MYInputAccessoryToolbar.m
@interface MYInputAccessoryToolbar ()
@property (strong, nonatomic) UIBarButtonItem *nextButton;
@property (strong, nonatomic) UIBarButtonItem *prevButton;
@property (strong, nonatomic) UIBarButtonItem *doneButton;
@property (nonatomic, copy) NSMutableArray *inputItems;
@property (nonatomic) NSInteger activeItemIndex;
@property (nonatomic) id activeItem;
@end
@implementation MYInputAccessoryToolbar
+ (instancetype)toolbarWithInputItems:(NSArray *)items {
return [[self alloc] initWithInputItems:items];
}
#pragma mark - Initializations
- (instancetype)init {
self = [super init];
if (self) {
_inputItems = [NSMutableArray new];
_prevButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:101 target:self action:@selector(prevButtonTaped)];
_nextButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:102 target:self action:@selector(nextButtonTaped)];
_doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleBordered target:self action:@selector(doneButtonTaped)];
[_doneButton setTitleTextAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:17]} forState:UIControlStateNormal];
UIBarButtonItem *fixedSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
fixedSpace.width = 20.0f;
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
NSArray<UIBarButtonItem *> *barButtons = @[_prevButton, fixedSpace, _nextButton, flexSpace, _doneButton];
[self sizeToFit];
self.items = barButtons;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(itemDidBeginEditing:)
name:UITextFieldTextDidBeginEditingNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(itemDidBeginEditing:)
name:UITextViewTextDidBeginEditingNotification
object:nil];
}
return self;
}
- (instancetype) initWithInputItems:(NSArray *)items {
self = [self init];
for (id item in items) {
[self addInputItem:item];
}
return self;
}
#pragma mark - Accessors
- (void)addInputItem:(id)item {
if ([item respondsToSelector:@selector(setInputAccessoryView:)]) {
[item setInputAccessoryView:self];
}
[_inputItems addObject:item];
}
#pragma mark - Actions
- (void)itemDidBeginEditing:(NSNotification *)noticifation {
NSInteger itemIndex = [_inputItems indexOfObject:noticifation.object];
if (itemIndex != NSNotFound && _activeItem != noticifation.object) {
_activeItemIndex = itemIndex;
_activeItem = noticifation.object;
[self activeItemChanged];
}
}
- (void)activeItemChanged {
_prevButton.enabled = _activeItemIndex != 0;
_nextButton.enabled = _activeItemIndex != _inputItems.count - 1;
}
- (void)prevButtonTaped {
[self goToPrevItem];
}
- (void)nextButtonTaped {
[self goToNextItem];
}
- (void)goToNextItem {
[_inputItems[_activeItemIndex + 1] becomeFirstResponder];
}
- (void)goToPrevItem {
[_inputItems[_activeItemIndex - 1] becomeFirstResponder];
}
- (void)doneButtonTaped {
if (_didDoneTapBlock) {
_didDoneTapBlock(_activeItem);
}
[_activeItem resignFirstResponder];
}
#pragma mark - Dealloc
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidBeginEditingNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextViewTextDidBeginEditingNotification object:nil];
}
@end
现在假设我们有一组文本字段和文本视图,我们可以使用它们来初始化工具栏的实例。
MYInputAccessoryToolbar *accessoryToolbar = [MYInputAccessoryToolbar toolbarWithInputItems:@[_passwordCurrentField, _passwordNewField, _passwordVerifyField]];
然后每个字段都会有一个自定义的附件视图,例如 this。
我发布这个答案是为了向其他人展示我的确切代码以及它实际上有多简单,但是所有功劳都归功于 MadNik。
在你想要键盘的视图控制器 class 中,在实现中添加以下内容:
@implementation CommentViewController {
UIView *toolbar;
UITextView *commentTextView;
UIButton *postComment;
}
toolbar
是停靠在键盘上的实际视图,其余对象位于视图之上。
下一步就是启动 toolbar
并设置其框架:
toolbar = [[UIView alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height-50, self.view.frame.size.width, 50)];
[toolbar setBackgroundColor:[UIColor whiteColor]];
我让工具栏的框架最初位于视图控制器的底部。
接下来我只是启动工具栏上我想要的其余对象,例如 UITextField
和 UIButton
。随心所欲地布置它们:
commentTextView = [[UITextView alloc]initWithFrame:CGRectMake(8, 8, self.view.frame.size.width - 16 - 75, 34)];
[commentTextView setBackgroundColor:[UIColor colorWithWhite:0.97 alpha:1]];
commentTextView.layer.cornerRadius = 5;
[commentTextView setFont:[UIFont fontWithName:@"Avenir Next" size:20]];
[commentTextView setTextColor:[UIColor colorWithWhite:0.35 alpha:1]];
postComment = [[UIButton alloc]initWithFrame:CGRectMake(self.view.frame.size.width-75, 0, 75, 50)];
[postComment setTitle:@"Post" forState:UIControlStateNormal];
[postComment.titleLabel setFont:[UIFont fontWithName:@"Avenir Next" size:20]];
[postComment setTitleColor:[UIColor colorWithRed:(255/255.0) green:(40/255.0) blue:(80/255.0) alpha:1.0] forState:UIControlStateNormal];
接下来将您的对象添加到工具栏:
[toolbar addSubview:commentTextView];
[toolbar addSubview:postComment];
现在这就是奇迹发生的地方:您只需将 UITextView
的 inputAccessoryView 设置为 您想要停靠到键盘的任何视图。
在这种情况下它是 toolbar
,因为 toolbar
充当容纳其他所有东西的码头。
现在您需要做的就是将 toolbar
添加到视图控制器,当您点击 UITextView
时,因为它的 inputAccessoryView 是 toolbar
,所以 toolbar
将停靠在键盘上!
由于我使用的是 UITableViewController
,因此我不得不将我的 toolbar
添加到 window:
[[[UIApplication sharedApplication]delegate].window addSubview:toolbar];
就这么简单!不需要额外的 classes 或任何东西!
删除 self.inputAccessoryView = view;
,然后在 -(void)viewDidLoad { ... }
之后的任意位置添加下面的代码,其中 view
是您的 UIView:
-(void) viewDidLoad {
....
}
- (UIView *)inputAccessoryView
{
return self.view;
}
我正在尝试复制 Facebook Messenger 应用程序,其中有一个 UITextView
附加到键盘顶部。
由于此应用程序的性质,我需要附加 view
,而不是在出现键盘时手动上下滚动 ScrollView
。
这可以通过使用 inputAccessoryView
.
我阅读了它的文档 here。
文档非常简短并说:
“这 属性 通常用于将附件视图附加到为 UITextField 和 UITextView 对象提供的系统提供的键盘。
此只读 属性 的值为 nil。如果您想将自定义控件附加到系统提供的输入视图(例如系统键盘)或自定义输入视图(您在 inputView 属性 中提供的视图),请将此 属性 重新声明为已读-写在 UIResponder 子类中。
然后您可以使用此 属性 来管理自定义附件视图。当接收者成为第一响应者时,响应者基础结构在显示之前将附件视图附加到适当的输入视图。"
我试过声明 属性
@interface CommentViewController ()
@property (nonatomic, readwrite, retain) UIView *inputAccessoryView;
@end
然后设置它:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 20, 320, 100)];
[view setBackgroundColor:[UIColor greenColor]];
self.inputAccessoryView = view;
}
然后我尝试调用这两个:
[self.tableView becomeFirstResponder];
[view becomeFirstResponder];
没有任何反应。我做错了什么?
*注意 - 额外信息:我正在使用 UITableViewController
,我想将 UIView
作为 inputAccessoryView
附加。一旦我的视图开始工作,我将添加一个 UITextView
等等,但这主要是一个示例。
非常感谢任何帮助!
将输入附件添加到您的 textField 或 textView 而不是纯 UIView。
self.mytextField.inputAccessoryView = view;
inputAccessoryView
是 UIResponder
class 的 属性。它允许您定义自定义输入附件视图,以在接收者成为第一响应者时显示。通常应将 UIToolBar
的实例设置为附属视图。
工具栏示例:
MYInputAccessoryToolbar.h
typedef void (^MYInputAccessoryToolbarDidDoneTap)(id activeItem);
@interface MYInputAccessoryToolbar : UIToolbar
@property (nonatomic, copy) MYInputAccessoryToolbarDidDoneTap didDoneTapBlock;
+ (instancetype)toolbarWithInputItems:(NSArray *)items;
- (instancetype)initWithInputItems:(NSArray *)items;
- (void)addInputItem:(id)item;
- (void)goToNextItem;
- (void)goToPrevItem;
@end
MYInputAccessoryToolbar.m
@interface MYInputAccessoryToolbar ()
@property (strong, nonatomic) UIBarButtonItem *nextButton;
@property (strong, nonatomic) UIBarButtonItem *prevButton;
@property (strong, nonatomic) UIBarButtonItem *doneButton;
@property (nonatomic, copy) NSMutableArray *inputItems;
@property (nonatomic) NSInteger activeItemIndex;
@property (nonatomic) id activeItem;
@end
@implementation MYInputAccessoryToolbar
+ (instancetype)toolbarWithInputItems:(NSArray *)items {
return [[self alloc] initWithInputItems:items];
}
#pragma mark - Initializations
- (instancetype)init {
self = [super init];
if (self) {
_inputItems = [NSMutableArray new];
_prevButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:101 target:self action:@selector(prevButtonTaped)];
_nextButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:102 target:self action:@selector(nextButtonTaped)];
_doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleBordered target:self action:@selector(doneButtonTaped)];
[_doneButton setTitleTextAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:17]} forState:UIControlStateNormal];
UIBarButtonItem *fixedSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
fixedSpace.width = 20.0f;
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
NSArray<UIBarButtonItem *> *barButtons = @[_prevButton, fixedSpace, _nextButton, flexSpace, _doneButton];
[self sizeToFit];
self.items = barButtons;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(itemDidBeginEditing:)
name:UITextFieldTextDidBeginEditingNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(itemDidBeginEditing:)
name:UITextViewTextDidBeginEditingNotification
object:nil];
}
return self;
}
- (instancetype) initWithInputItems:(NSArray *)items {
self = [self init];
for (id item in items) {
[self addInputItem:item];
}
return self;
}
#pragma mark - Accessors
- (void)addInputItem:(id)item {
if ([item respondsToSelector:@selector(setInputAccessoryView:)]) {
[item setInputAccessoryView:self];
}
[_inputItems addObject:item];
}
#pragma mark - Actions
- (void)itemDidBeginEditing:(NSNotification *)noticifation {
NSInteger itemIndex = [_inputItems indexOfObject:noticifation.object];
if (itemIndex != NSNotFound && _activeItem != noticifation.object) {
_activeItemIndex = itemIndex;
_activeItem = noticifation.object;
[self activeItemChanged];
}
}
- (void)activeItemChanged {
_prevButton.enabled = _activeItemIndex != 0;
_nextButton.enabled = _activeItemIndex != _inputItems.count - 1;
}
- (void)prevButtonTaped {
[self goToPrevItem];
}
- (void)nextButtonTaped {
[self goToNextItem];
}
- (void)goToNextItem {
[_inputItems[_activeItemIndex + 1] becomeFirstResponder];
}
- (void)goToPrevItem {
[_inputItems[_activeItemIndex - 1] becomeFirstResponder];
}
- (void)doneButtonTaped {
if (_didDoneTapBlock) {
_didDoneTapBlock(_activeItem);
}
[_activeItem resignFirstResponder];
}
#pragma mark - Dealloc
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidBeginEditingNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextViewTextDidBeginEditingNotification object:nil];
}
@end
现在假设我们有一组文本字段和文本视图,我们可以使用它们来初始化工具栏的实例。
MYInputAccessoryToolbar *accessoryToolbar = [MYInputAccessoryToolbar toolbarWithInputItems:@[_passwordCurrentField, _passwordNewField, _passwordVerifyField]];
然后每个字段都会有一个自定义的附件视图,例如 this。
我发布这个答案是为了向其他人展示我的确切代码以及它实际上有多简单,但是所有功劳都归功于 MadNik。
在你想要键盘的视图控制器 class 中,在实现中添加以下内容:
@implementation CommentViewController {
UIView *toolbar;
UITextView *commentTextView;
UIButton *postComment;
}
toolbar
是停靠在键盘上的实际视图,其余对象位于视图之上。
下一步就是启动 toolbar
并设置其框架:
toolbar = [[UIView alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height-50, self.view.frame.size.width, 50)];
[toolbar setBackgroundColor:[UIColor whiteColor]];
我让工具栏的框架最初位于视图控制器的底部。
接下来我只是启动工具栏上我想要的其余对象,例如 UITextField
和 UIButton
。随心所欲地布置它们:
commentTextView = [[UITextView alloc]initWithFrame:CGRectMake(8, 8, self.view.frame.size.width - 16 - 75, 34)];
[commentTextView setBackgroundColor:[UIColor colorWithWhite:0.97 alpha:1]];
commentTextView.layer.cornerRadius = 5;
[commentTextView setFont:[UIFont fontWithName:@"Avenir Next" size:20]];
[commentTextView setTextColor:[UIColor colorWithWhite:0.35 alpha:1]];
postComment = [[UIButton alloc]initWithFrame:CGRectMake(self.view.frame.size.width-75, 0, 75, 50)];
[postComment setTitle:@"Post" forState:UIControlStateNormal];
[postComment.titleLabel setFont:[UIFont fontWithName:@"Avenir Next" size:20]];
[postComment setTitleColor:[UIColor colorWithRed:(255/255.0) green:(40/255.0) blue:(80/255.0) alpha:1.0] forState:UIControlStateNormal];
接下来将您的对象添加到工具栏:
[toolbar addSubview:commentTextView];
[toolbar addSubview:postComment];
现在这就是奇迹发生的地方:您只需将 UITextView
的 inputAccessoryView 设置为 您想要停靠到键盘的任何视图。
在这种情况下它是 toolbar
,因为 toolbar
充当容纳其他所有东西的码头。
现在您需要做的就是将 toolbar
添加到视图控制器,当您点击 UITextView
时,因为它的 inputAccessoryView 是 toolbar
,所以 toolbar
将停靠在键盘上!
由于我使用的是 UITableViewController
,因此我不得不将我的 toolbar
添加到 window:
[[[UIApplication sharedApplication]delegate].window addSubview:toolbar];
就这么简单!不需要额外的 classes 或任何东西!
删除 self.inputAccessoryView = view;
,然后在 -(void)viewDidLoad { ... }
之后的任意位置添加下面的代码,其中 view
是您的 UIView:
-(void) viewDidLoad {
....
}
- (UIView *)inputAccessoryView
{
return self.view;
}