JSQMessagesViewController/JSMessagesViewController/Classes/JSMessageInputView.m
2014-01-21 20:28:42 -08:00

239 lines
9.1 KiB
Objective-C

//
// Created by Jesse Squires
// http://www.hexedbits.com
//
//
// Documentation
// http://cocoadocs.org/docsets/JSMessagesViewController
//
//
// The MIT License
// Copyright (c) 2013 Jesse Squires
// http://opensource.org/licenses/MIT
//
#import "JSMessageInputView.h"
#import <QuartzCore/QuartzCore.h>
#import "JSBubbleView.h"
#import "NSString+JSMessagesView.h"
#import "UIColor+JSMessagesView.h"
@interface JSMessageInputView ()
- (void)setup;
- (void)configureInputBarWithStyle:(JSMessageInputViewStyle)style;
- (void)configureSendButtonWithStyle:(JSMessageInputViewStyle)style;
@end
@implementation JSMessageInputView
#pragma mark - Initialization
- (void)setup
{
self.backgroundColor = [UIColor whiteColor];
self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin);
self.opaque = YES;
self.userInteractionEnabled = YES;
}
- (void)configureInputBarWithStyle:(JSMessageInputViewStyle)style
{
CGFloat sendButtonWidth = (style == JSMessageInputViewStyleClassic) ? 78.0f : 64.0f;
CGFloat width = self.frame.size.width - sendButtonWidth;
CGFloat height = [JSMessageInputView textViewLineHeight];
JSMessageTextView *textView = [[JSMessageTextView alloc] initWithFrame:CGRectZero];
[self addSubview:textView];
_textView = textView;
if (style == JSMessageInputViewStyleClassic) {
_textView.frame = CGRectMake(6.0f, 3.0f, width, height);
_textView.backgroundColor = [UIColor whiteColor];
self.image = [[UIImage imageNamed:@"input-bar-background"] resizableImageWithCapInsets:UIEdgeInsetsMake(19.0f, 3.0f, 19.0f, 3.0f)
resizingMode:UIImageResizingModeStretch];
UIImageView *inputFieldBack = [[UIImageView alloc] initWithFrame:CGRectMake(_textView.frame.origin.x - 1.0f,
0.0f,
_textView.frame.size.width + 2.0f,
self.frame.size.height)];
inputFieldBack.image = [[UIImage imageNamed:@"input-field-cover"] resizableImageWithCapInsets:UIEdgeInsetsMake(20.0f, 12.0f, 18.0f, 18.0f)];
inputFieldBack.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
inputFieldBack.backgroundColor = [UIColor clearColor];
[self addSubview:inputFieldBack];
}
else {
_textView.frame = CGRectMake(4.0f, 4.5f, width, height);
_textView.backgroundColor = [UIColor clearColor];
_textView.layer.borderColor = [UIColor colorWithWhite:0.8f alpha:1.0f].CGColor;
_textView.layer.borderWidth = 0.65f;
_textView.layer.cornerRadius = 6.0f;
self.image = [[UIImage imageNamed:@"input-bar-flat"] resizableImageWithCapInsets:UIEdgeInsetsMake(2.0f, 0.0f, 0.0f, 0.0f)
resizingMode:UIImageResizingModeStretch];
}
}
- (void)configureSendButtonWithStyle:(JSMessageInputViewStyle)style
{
UIButton *sendButton;
if (style == JSMessageInputViewStyleClassic) {
sendButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIEdgeInsets insets = UIEdgeInsetsMake(0.0f, 13.0f, 0.0f, 13.0f);
UIImage *sendBack = [[UIImage imageNamed:@"send-button"] resizableImageWithCapInsets:insets];
UIImage *sendBackHighLighted = [[UIImage imageNamed:@"send-button-pressed"] resizableImageWithCapInsets:insets];
[sendButton setBackgroundImage:sendBack forState:UIControlStateNormal];
[sendButton setBackgroundImage:sendBack forState:UIControlStateDisabled];
[sendButton setBackgroundImage:sendBackHighLighted forState:UIControlStateHighlighted];
UIColor *titleShadow = [UIColor colorWithRed:0.325f green:0.463f blue:0.675f alpha:1.0f];
[sendButton setTitleShadowColor:titleShadow forState:UIControlStateNormal];
[sendButton setTitleShadowColor:titleShadow forState:UIControlStateHighlighted];
sendButton.titleLabel.shadowOffset = CGSizeMake(0.0f, -1.0f);
[sendButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[sendButton setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
[sendButton setTitleColor:[UIColor colorWithWhite:1.0f alpha:0.5f] forState:UIControlStateDisabled];
sendButton.titleLabel.font = [UIFont boldSystemFontOfSize:16.0f];
}
else {
sendButton = [UIButton buttonWithType:UIButtonTypeCustom];
sendButton.backgroundColor = [UIColor clearColor];
[sendButton setTitleColor:[UIColor js_bubbleBlueColor] forState:UIControlStateNormal];
[sendButton setTitleColor:[UIColor js_bubbleBlueColor] forState:UIControlStateHighlighted];
[sendButton setTitleColor:[UIColor js_bubbleLightGrayColor] forState:UIControlStateDisabled];
sendButton.titleLabel.font = [UIFont boldSystemFontOfSize:18.0f];
}
NSString *title = NSLocalizedString(@"Send", nil);
[sendButton setTitle:title forState:UIControlStateNormal];
[sendButton setTitle:title forState:UIControlStateHighlighted];
[sendButton setTitle:title forState:UIControlStateDisabled];
sendButton.autoresizingMask = (UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin);
[self setSendButton:sendButton];
}
- (instancetype)initWithFrame:(CGRect)frame
style:(JSMessageInputViewStyle)style
delegate:(id<UITextViewDelegate, JSDismissiveTextViewDelegate>)delegate
panGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer
{
self = [super initWithFrame:frame];
if (self) {
_style = style;
[self setup];
[self configureInputBarWithStyle:style];
[self configureSendButtonWithStyle:style];
_textView.delegate = delegate;
_textView.keyboardDelegate = delegate;
_textView.dismissivePanGestureRecognizer = panGestureRecognizer;
}
return self;
}
- (void)dealloc
{
_textView = nil;
_sendButton = nil;
}
#pragma mark - UIView
- (BOOL)resignFirstResponder
{
[self.textView resignFirstResponder];
return [super resignFirstResponder];
}
#pragma mark - Setters
- (void)setSendButton:(UIButton *)btn
{
if (_sendButton)
[_sendButton removeFromSuperview];
if (self.style == JSMessageInputViewStyleClassic) {
btn.frame = CGRectMake(self.frame.size.width - 65.0f, 8.0f, 59.0f, 26.0f);
}
else {
CGFloat padding = 8.0f;
btn.frame = CGRectMake(self.textView.frame.origin.x + self.textView.frame.size.width,
padding,
60.0f,
self.textView.frame.size.height - padding);
}
[self addSubview:btn];
_sendButton = btn;
}
#pragma mark - Message input view
- (void)adjustTextViewHeightBy:(CGFloat)changeInHeight
{
CGRect prevFrame = self.textView.frame;
NSUInteger numLines = MAX([self.textView numberOfLinesOfText],
[self.textView.text js_numberOfLines]);
// below iOS 7, if you set the text view frame programmatically, the KVO will continue notifying
// to avoid that, we are removing the observer before setting the frame and add the observer after setting frame here.
[self.textView removeObserver:_textView.keyboardDelegate
forKeyPath:@"contentSize"];
self.textView.frame = CGRectMake(prevFrame.origin.x,
prevFrame.origin.y,
prevFrame.size.width,
prevFrame.size.height + changeInHeight);
[self.textView addObserver:_textView.keyboardDelegate
forKeyPath:@"contentSize"
options:NSKeyValueObservingOptionNew
context:nil];
self.textView.contentInset = UIEdgeInsetsMake((numLines >= 6 ? 4.0f : 0.0f),
0.0f,
(numLines >= 6 ? 4.0f : 0.0f),
0.0f);
// from iOS 7, the content size will be accurate only if the scrolling is enabled.
self.textView.scrollEnabled = YES;
if (numLines >= 6) {
CGPoint bottomOffset = CGPointMake(0.0f, self.textView.contentSize.height - self.textView.bounds.size.height);
[self.textView setContentOffset:bottomOffset animated:YES];
[self.textView scrollRangeToVisible:NSMakeRange(self.textView.text.length - 2, 1)];
}
}
+ (CGFloat)textViewLineHeight
{
return 36.0f; // for fontSize 16.0f
}
+ (CGFloat)maxLines
{
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) ? 4.0f : 8.0f;
}
+ (CGFloat)maxHeight
{
return ([JSMessageInputView maxLines] + 1.0f) * [JSMessageInputView textViewLineHeight];
}
@end