带大家一步一步封装聊天键盘(三)新增功能不要错过哟

这几天都不忙,就来写写博客了,继上次

带大家一步一步封装聊天键盘(一)地址:http://www.cnblogs.com/bcblogs/p/4704046.html

带大家一步一步封装聊天键盘(二)地址:http://www.cnblogs.com/bcblogs/p/4707512.html

git也更新了,大家在拉一遍地址在第一篇里

今天我们来写三,主要是把MoreView的里面的发送图片啊,语音啊,视频啊什么的都实现,今天主要实现的是发送图片(因为这个最简单...)

需求:点击图片按钮,弹出actionsheet控件,选择拍摄还是从图片库选择

好吧,不啰嗦了,直接上代码

- (void)didselectImageView:(NSInteger)index
{
    switch (index) {
        case 0:
            [self createActionSheet];
            break;
        default:
            break;
    }
}
- (void)createActionSheet
{
    UIActionSheet *action=[[UIActionSheet alloc] initWithTitle:@"选取照片" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"从摄像头选取", @"从图片库选择",nil];
    [action showInView:self];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    switch (buttonIndex) {
        case 0:
            [self openCamera];
            break;
        case 1:
            [self openLibary];
            break;
        default:
            break;
    }
}
- (void)openCamera{
    //打开系统相机
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.allowsEditing = YES;
        picker.sourceType = UIImagePickerControllerSourceTypeCamera;
        [self.currentCtr presentViewController:picker animated:YES completion:nil];
    }
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    if([self.delegate respondsToSelector:@selector(returnImage:)]){
        [self.delegate returnImage:image];
    }
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
    [self.currentCtr dismissViewControllerAnimated:YES completion:nil];
    
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [self.currentCtr dismissViewControllerAnimated:YES completion:nil];
}
- (void)openLibary{
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.allowsEditing = YES;
        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        [self.currentCtr presentViewController:picker animated:YES completion:nil];
    }
}

上次封装的代理方法可以将点击了第几张图片的事件传回自定义的View,也就是BCKeyBoard,根据 - (void)didselectImageView:(NSInteger)index方法中的index来判断点击了第几个图片

这里我们用switch,因为它比较快,点击了第一个图片,就创建一个actionsheet,利用actionsheet的代理方法

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex来判断点击了第几个按钮

从而选择打开相机还是打开相册,在这里我发现个问题,因为在view里的对象是view,而不是viewcontroller所以不能使用presentViewController方法,虽然可以使用代理将点击事件传到控制器再在控制器去打开相机和相册

但是,那不是我想要的,我想把所有的逻辑都封装在自定义View里面,突然,灵光一闪,我把控制器当做一个属性传给自定义View,不就能调用外部控制器去使用presentViewController方法了(真是个天才,哈哈),还需要写个代理方法

将拍摄的照片和从相册里面选择的照片传回控制器,以便使用者使用

最后BCKeyBoard.h文件

#import <UIKit/UIKit.h>

@protocol BCKeyBoardDelegate <NSObject>

/**
 发送的文字
 */
- (void)didSendText:(NSString *)text;

/**
 回调返回高度
 */
- (void)returnHeight:(CGFloat)height;

/**
 回调返回的图片
 */
- (void)returnImage:(UIImage *)image;

@end

@interface BCKeyBoard : UIView

@property (nonatomic,weak)id <BCKeyBoardDelegate> delegate;
@property (nonatomic,strong)NSArray *imageArray; /**< 点击加号弹出的View中的图片数组 */
@property (nonatomic,strong)NSString *placeholder; /**< 占位文字 */
@property (nonatomic,strong)UIColor *placeholderColor; /**< 占位文字颜色 */
@property (nonatomic,strong)UIViewController *currentCtr;
@end

BCKeyBoard.m文件

#import "BCKeyBoard.h"
#import "BCTextView.h"

#import "DXFaceView.h"
#import "BCMoreView.h"


#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)


#define kBCTextViewHeight 36 /**< 底部textView的高度 */
#define kHorizontalPadding 8 /**< 横向间隔 */
#define kVerticalPadding 5 /**< 纵向间隔 */

@interface BCKeyBoard () <UITextViewDelegate,DXFaceDelegate,BCMoreViewDelegate,UIActionSheetDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate>
@property (nonatomic,strong)UIImageView *backgroundImageView;
@property (nonatomic,strong)UIButton *faceBtn;
@property (nonatomic,strong)UIButton *moreBtn;
@property (nonatomic,strong)BCTextView  *textView;
@property (nonatomic,strong)UIView *faceView;
@property (nonatomic,strong)UIView *moreView;
@property (nonatomic,assign)CGFloat lastHeight;
@property (nonatomic,strong)UIView *activeView;
@end

@implementation BCKeyBoard
- (instancetype)initWithFrame:(CGRect)frame
{
    if (frame.size.height < (kVerticalPadding * 2 + kBCTextViewHeight)) {
        frame.size.height = kVerticalPadding * 2 + kBCTextViewHeight;
    }
    self = [super initWithFrame:frame];
    if (self) {
        [self createUI];
    }
    return self;
}

- (void)setFrame:(CGRect)frame
{
    if (frame.size.height < (kVerticalPadding * 2 + kBCTextViewHeight)) {
        frame.size.height = kVerticalPadding * 2 + kBCTextViewHeight;
    }
    [super setFrame:frame];
}
- (void)createUI
{
    _lastHeight = 30;
    //注册键盘改变是调用
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
    
    self.backgroundImageView = [[UIImageView alloc] initWithFrame:self.bounds];
    self.backgroundImageView.userInteractionEnabled = YES;
    self.backgroundImageView.image = [[UIImage imageNamed:@"messageToolbarBg"] stretchableImageWithLeftCapWidth:0.5 topCapHeight:10];
    
    
    //表情按钮
    self.faceBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    self.faceBtn.frame = CGRectMake(kHorizontalPadding,kHorizontalPadding, 30, 30);
    [self.faceBtn addTarget:self action:@selector(willShowFaceView:) forControlEvents:UIControlEventTouchUpInside];
    [self.faceBtn setBackgroundImage:[UIImage imageNamed:@"chatBar_face"] forState:UIControlStateNormal];
    [self.faceBtn setBackgroundImage:[UIImage imageNamed:@"chatBar_keyboard"] forState:UIControlStateSelected];
    [self addSubview:self.faceBtn];
    
    //文本
    self.textView = [[BCTextView alloc] initWithFrame:CGRectMake(CGRectGetMaxX(self.faceBtn.frame)+kHorizontalPadding, kHorizontalPadding, self.bounds.size.width - 4*kHorizontalPadding - 30*2, 30)];
    self.textView.placeholderColor = self.placeholderColor;
    self.textView.returnKeyType = UIReturnKeySend;
    self.textView.scrollEnabled = NO;
    self.textView.backgroundColor = [UIColor clearColor];
    self.textView.layer.borderColor = [UIColor colorWithWhite:0.8f alpha:1.0f].CGColor;
    self.textView.layer.borderWidth = 0.65f;
    self.textView.layer.cornerRadius = 6.0f;
    self.textView.delegate = self;
    
    //更多按钮
    self.moreBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    self.moreBtn.frame = CGRectMake(CGRectGetMaxX(self.textView.frame)+kHorizontalPadding,kHorizontalPadding,30,30);
    [self.moreBtn addTarget:self action:@selector(willShowactiveView:) forControlEvents:UIControlEventTouchUpInside];
    [self.moreBtn setBackgroundImage:[UIImage imageNamed:@"chatBar_more"] forState:UIControlStateNormal];
    [self.moreBtn setBackgroundImage:[UIImage imageNamed:@"chatBar_keyboard"] forState:UIControlStateSelected];
    
    [self addSubview:self.backgroundImageView];
    [self.backgroundImageView addSubview:self.textView];
    [self.backgroundImageView addSubview:self.faceBtn];
    [self.backgroundImageView addSubview:self.moreBtn];
    
    if (!self.faceView) {
        self.faceView = [[DXFaceView alloc] initWithFrame:CGRectMake(0, (kHorizontalPadding * 2 + 30), self.frame.size.width, 200)];
        [(DXFaceView *)self.faceView setDelegate:self];
        self.faceView.backgroundColor = [UIColor whiteColor];
        self.faceView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
    }
    
    if (!self.moreView) {
        self.moreView = [[BCMoreView alloc] initWithFrame:CGRectMake(0, (kHorizontalPadding * 2 + 30), self.frame.size.width, 200)];
        self.moreView.backgroundColor = [UIColor whiteColor];
        [(BCMoreView *)self.moreView setDelegate:self];
        self.moreView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
    }
}
- (void)changeFrame:(CGFloat)height{
    
    if (height == _lastHeight)
    {
        return;
    }
    else{
        CGFloat changeHeight = height - _lastHeight;
        
        CGRect rect = self.frame;
        rect.size.height += changeHeight;
        rect.origin.y -= changeHeight;
        self.frame = rect;
        
        rect = self.backgroundImageView.frame;
        rect.size.height += changeHeight;
        self.backgroundImageView.frame = rect;
        
        
        [self.textView setContentOffset:CGPointMake(0.0f, (self.textView.contentSize.height - self.textView.frame.size.height) / 2) animated:YES];
        
        CGRect frame = self.textView.frame;
        frame.size.height = height;
        self.textView.frame = frame;
        
        _lastHeight = height;
        
        if (self.delegate && [self.delegate respondsToSelector:@selector(returnHeight:)]) {
            [self.delegate returnHeight:height];
        }
    }

}
- (void)setPlaceholder:(NSString *)placeholder
{
    self.textView.placeholder = placeholder;
}
- (void)setPlaceholderColor:(UIColor *)placeholderColor
{
    self.textView.placeholderColor = placeholderColor;
}
- (void)keyboardWillChangeFrame:(NSNotification *)notification{
    NSDictionary *userInfo = notification.userInfo;
    CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
    void(^animations)() = ^{
        CGRect frame = self.frame;
        frame.origin.y = endFrame.origin.y - self.bounds.size.height;
        self.frame = frame;
    };
    void(^completion)(BOOL) = ^(BOOL finished){
    };
    [UIView animateWithDuration:duration delay:0.0f options:(curve << 16 | UIViewAnimationOptionBeginFromCurrentState) animations:animations completion:completion];
}
#pragma mark 表情View
- (void)willShowFaceView:(UIButton *)btn
{
    btn.selected = !btn.selected;
    if(btn.selected == YES){
        [self willShowBottomView:self.faceView];
        [self.textView resignFirstResponder];
    }else{
        [self willShowBottomView:nil];
        [self.textView becomeFirstResponder];
    }
}

#pragma mark 表更多View
- (void)willShowactiveView:(UIButton *)btn
{
    btn.selected = !btn.selected;
    if(btn.selected == YES){
        [self willShowBottomView:self.moreView];
        [self.textView resignFirstResponder];
        [(BCMoreView *)self.moreView setImageArray:self.imageArray];
    }else{
        [self willShowBottomView:nil];
        [self.textView becomeFirstResponder];
    }
}

- (void)willShowBottomHeight:(CGFloat)bottomHeight
{
    CGRect fromFrame = self.frame;
    CGFloat toHeight = self.backgroundImageView.frame.size.height + bottomHeight;
    CGRect toFrame = CGRectMake(fromFrame.origin.x, fromFrame.origin.y + (fromFrame.size.height - toHeight), fromFrame.size.width, toHeight);
    self.frame = toFrame;
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(returnHeight:)]) {
        [self.delegate returnHeight:toHeight];
    }
}
- (CGFloat)getTextViewContentH:(UITextView *)textView
{
    return ceilf([textView sizeThatFits:textView.frame.size].height);
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
    [self willShowBottomView:nil];
    self.faceBtn.selected = NO;
    self.moreBtn.selected = NO;
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    
    if ([text isEqualToString:@"
"]) {
        if ([self.delegate respondsToSelector:@selector(didSendText:)]) {
            [self.delegate didSendText:textView.text];
            self.textView.text = @"";
            [self changeFrame:ceilf([textView sizeThatFits:textView.frame.size].height)];
        }
        return NO;
    }
    return YES;
}
- (void)willShowBottomView:(UIView *)bottomView
{
    if (![self.activeView isEqual:bottomView]) {
        CGFloat bottomHeight = bottomView ? bottomView.frame.size.height : 0;
        [self willShowBottomHeight:bottomHeight];
        
        if (bottomView) {
            CGRect rect = bottomView.frame;
            rect.origin.y = CGRectGetMaxY(self.backgroundImageView.frame);
            bottomView.frame = rect;
            [self addSubview:bottomView];
        }
        if (self.activeView) {
            [self.activeView removeFromSuperview];
        }
        self.activeView = bottomView;
    }
}
- (void)textViewDidChange:(UITextView *)textView
{
    [self changeFrame:ceilf([textView sizeThatFits:textView.frame.size].height)];
}
- (void)selectedFacialView:(NSString *)str isDelete:(BOOL)isDelete
{
    NSString *chatText = self.textView.text;
    
    if (!isDelete && str.length > 0) {
        self.textView.text = [NSString stringWithFormat:@"%@%@",chatText,str];
    }
    else {
        if (chatText.length >= 2)
        {
            NSString *subStr = [chatText substringFromIndex:chatText.length-2];
            if ([(DXFaceView *)self.faceView stringIsFace:subStr]) {
                self.textView.text = [chatText substringToIndex:chatText.length-2];
                [self textViewDidChange:self.textView];
                return;
            }
        }
        if (chatText.length > 0) {
            self.textView.text = [chatText substringToIndex:chatText.length-1];
        }
    }
    [self textViewDidChange:self.textView];
}
- (void)sendFace
{
    NSString *chatText = self.textView.text;
    if (chatText.length > 0) {
        if ([self.delegate respondsToSelector:@selector(didSendText:)]) {
            [self.delegate didSendText:chatText];
            self.textView.text = @"";
            [self changeFrame:ceilf([self.textView sizeThatFits:self.textView.frame.size].height)];
        }
    }
}
- (void)didselectImageView:(NSInteger)index
{
    switch (index) {
        case 0:
            [self createActionSheet];
            break;
        default:
            break;
    }
}
- (void)createActionSheet
{
    UIActionSheet *action=[[UIActionSheet alloc] initWithTitle:@"选取照片" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"从摄像头选取", @"从图片库选择",nil];
    [action showInView:self];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    switch (buttonIndex) {
        case 0:
            [self openCamera];
            break;
        case 1:
            [self openLibary];
            break;
        default:
            break;
    }
}
- (void)openCamera{
    //打开系统相机
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.allowsEditing = YES;
        picker.sourceType = UIImagePickerControllerSourceTypeCamera;
        [self.currentCtr presentViewController:picker animated:YES completion:nil];
    }
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    if([self.delegate respondsToSelector:@selector(returnImage:)]){
        [self.delegate returnImage:image];
    }
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
    [self.currentCtr dismissViewControllerAnimated:YES completion:nil];
    
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [self.currentCtr dismissViewControllerAnimated:YES completion:nil];
}
- (void)openLibary{
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.allowsEditing = YES;
        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        [self.currentCtr presentViewController:picker animated:YES completion:nil];
    }
}
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil];
}
@end

viewController里面的使用方法

#import "ViewController.h"
#import "BCKeyBoard.h"
@interface ViewController () <BCKeyBoardDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *array = @[@"chatBar_colorMore_photoSelected",@"chatBar_colorMore_audioCall",@"chatBar_colorMore_location",@"chatBar_colorMore_video.png",@"chatBar_colorMore_video.png",@"chatBar_colorMore_video.png"];
    BCKeyBoard *bc = [[BCKeyBoard alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height - 46, [UIScreen mainScreen].bounds.size.width,46)];
    bc.delegate = self;
    bc.imageArray = array;
    bc.placeholder = @"我来说几句";
    bc.currentCtr = self;
    bc.placeholderColor = [UIColor colorWithRed:133/255 green:133/255 blue:133/255 alpha:0.5];
    bc.backgroundColor = [UIColor clearColor];
    [self.view addSubview:bc];
}
- (void)didSendText:(NSString *)text
{
    NSLog(@"%@",text);
}
- (void)returnHeight:(CGFloat)height
{
    NSLog(@"%f",height);
}
- (void)returnImage:(UIImage *)image{
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    imageView.image = image;
    [self.view addSubview:imageView];
}
@end

运行效果

好啦,今天就到这里,大家看过了多评论啊,有什么问题和需要添加的功能也在评论里面写哦,顺便git上面点个star啊,谢谢啦。

原文地址:https://www.cnblogs.com/bcblogs/p/4709942.html