可以弹出带有自定义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];
}
    

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。