可以弹出带有自定义inputAccessoryView 的keyboard的按钮设计
最近在做一个项目,我独自负责的部分类似微信的朋友圈。虽然还是菜鸟一只,但我还是想尽量做到腾讯那样的效果。
本文将分享目前为止我从这个项目中获得的一些经验。首先先介绍一下这个按钮的功能:
点击一下这个按钮,弹出键盘和键盘上的inputAccessoryView。键盘上输入的内容在inputAccessoryView中的UITextView中呈现。再次点击这个按钮,输入的内容被提交。
这里的一个问题是:这个过程中谁是first responder?一开始我尝试点击按钮之后,直接让inputAccessoryView中的UITextView成为first responder,但是失败了。这是因为只有已显示的对象才能成为first responder,而inputAccessoryView一开始是隐藏的。
以下是我自定义的评论按钮:
//.h
#import <UIKit/UIKit.h>
#import "ViewOnKeyboard.h"
//只有实现了<UIKeyInput> ,当按钮被点击成为第一响应者后,才能够弹出键盘。<UITextInputTraits> 是为了修改回车键的样式。
@interface CommentButton : UIButton<UIKeyInput, UITextInputTraits>
@property (nonatomic, copy) NSIndexPath * indexPath;
@property (nonatomic) UIReturnKeyType returnKeyType;
//继承自UIResponder的inputAccessoryView是readonly的,只有改成readwrite才能实现自定义。
@property (nonatomic, retain, readwrite) ViewOnKeyboard * inputAccessoryView;
-(NSString *)makeText;
@end
//.m
#import "CommentButton.h"
@implementation CommentButton
@synthesize indexPath, inputAccessoryView, returnKeyType;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
inputAccessoryView = [[ViewOnKeyboard alloc]initWithFrame:CGRectMake(0, 0, 320, 40)];
inputAccessoryView.backgroundColor = [UIColor blueColor];
returnKeyType = UIReturnKeySend;
//监听键盘弹出
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(changeFirstResponder)
name:UIKeyboardDidShowNotification
object:nil];
}
return self;
}
-(void)changeFirstResponder
{
[self.inputAccessoryView.textView becomeFirstResponder]; //改变第一响应者。
[self resignFirstResponder];
}
//视图控制器将调用此函数,在收到inputAccessoryView.textView里的文本后,将其置为空。
-(NSString *)makeText{
NSString *str = [NSString stringWithString:inputAccessoryView.textView.text];
inputAccessoryView.textView.text = @"";
return str;
}
//让该对象可以成为第一响应者
-(BOOL)canBecomeFirstResponder{
return YES;
}
- (void)dealloc
{
[inputAccessoryView release];
[super dealloc];
}
//由于键盘一弹出,inputAccessoryView就顶替成为了first responder,所以一下函数不会被调用,只是为了消除警告。再次顺便也介绍一下功能。
//多说一句,即使是required的方法,也可以不实现。
#pragma mark - UIKeyInput
//每当从键盘输入一个字母(即参数text),会调用这个函数。
-(void)insertText:(NSString *)text{
}
//官方文档是这么说的:A Boolean value that indicates whether the text-entry objects has any text.YES
if the backing store has textual content, NO
otherwise.
-(BOOL)hasText{
return YES;
}
//点击键盘的删除键时调用这个函数。
-(void)deleteBackward{
}
@end
以下是我评论按钮的inputAccessoryView:
//.h
#import <UIKit/UIKit.h>
@protocol ViewOnKeyboardDelegate <NSObject>
-(void)receiveText;
@end
@interface ViewOnKeyboard : UIView <UITextViewDelegate>
@property (nonatomic, assign) UITextView * textView;
@property (nonatomic, assign) id <ViewOnKeyboardDelegate>delegate; //将试图控制器设为它的代理,并在试图控制器中实现receiveText。
@end
//.m
#import "ViewOnKeyboard.h"
@implementation ViewOnKeyboard
@synthesize textView, delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
textView = [[UITextView alloc]initWithFrame:CGRectMake(10, 5, 250, 30)];
textView.font = [UIFont systemFontOfSize:23];
textView.returnKeyType = UIReturnKeySend;
textView.delegate = self;
[self addSubview:textView];
[textView release];
}
return self;
}
//输入回车就提交已在键盘中输入的内容。
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if ([text isEqualToString:@"\n"]) {
[delegate receiveText];
return NO;
}
return YES;
}
@end
我的解决方法是:让按钮的点击事件调出键盘,这样按钮的inputAccessoryView会随着键盘弹出。同时按钮监听键盘弹出事件,键盘弹出之后让inputAccessoryView中的UITextView成为first responder。
另一个重点是:弹出键盘后,tableview 要随之滚动,使相应的cell的底边与键盘顶部对齐。通过在视图控制器中监听键盘弹出事件,改变tableview的contentOffset即可。
以下是实现这一功能的主要代码:
- (void)viewDidLoad { [super viewDidLoad]; /* ...... */ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; } - (void) keyboardWillShow:(NSNotification *) notif { NSDictionary *info = [notif userInfo]; NSValue *value = [info objectForKey:UIKeyboardFrameBeginUserInfoKey]; CGFloat keyboardHeight = [value CGRectValue].size.height;//包括了inputAccessoryView的高度 UITableViewCell * cell = [_tv cellForRowAtIndexPath:activeBtn.indexPath]; CGPoint contentOffset = _tv.contentOffset; CGRect applicationFrame = [[UIScreen mainScreen]applicationFrame];//{{0, 20}, {320, 460}} CGFloat newContentOffsetY = (cell.frame.origin.y + cell.frame.size.height) - (applicationFrame.size.height - keyboardHeight);//(cell底边y值) - (屏幕的高度 - 键盘的高度)。其中cell.frame 是相对content的frame,即cell.frame.origin.y可以大于480。 CGPoint newContentOffset = CGPointMake(contentOffset.x, newContentOffsetY); [_tv setContentOffset:newContentOffset animated:YES]; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。