Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Added support for customizing an indicator view. Defaults to the stan… #202

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Source/Classes/SLKTextViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ NS_CLASS_AVAILABLE_IOS(7_0) @interface SLKTextViewController : UIViewController
/** The bottom toolbar containing a text view and buttons. */
@property (nonatomic, readonly) SLKTextInputbar *textInputbar;

/** The typing indicator used to display user names horizontally. */
/** The typing indicator used to display user names horizontally. If -registerClassForIndicatorView: has been called with another class, this returns nil. */
@property (nonatomic, readonly) SLKTypingIndicatorView *typingIndicatorView;

/** The indicator view. Will be a kind of SLKTypingIndicatorView by default. Override by calling -registerClassForIndicatorView: during init */
@property (nonatomic, readonly) UIView *indicatorView;

/** A single tap gesture used to dismiss the keyboard. */
@property (nonatomic, readonly) UIGestureRecognizer *singleTapGesture;

Expand Down Expand Up @@ -446,6 +449,14 @@ NS_CLASS_AVAILABLE_IOS(7_0) @interface SLKTextViewController : UIViewController
*/
- (void)registerClassForTextView:(Class)textViewClass;

/**
Registers a class for customizing the behavior and appearance of the indicator view.
You need to call this method inside of any initialization method.

@param indicatorViewClass A UIView subclass conforming to the SLKIndicatorView protocol.
*/
- (void)registerClassForIndicatorView:(Class)indicatorViewClass;


#pragma mark - Delegate Methods Requiring Super
///------------------------------------------------
Expand Down
96 changes: 57 additions & 39 deletions Source/Classes/SLKTextViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ @interface SLKTextViewController ()
// Auto-Layout height constraints used for updating their constants
@property (nonatomic, strong) NSLayoutConstraint *scrollViewHC;
@property (nonatomic, strong) NSLayoutConstraint *textInputbarHC;
@property (nonatomic, strong) NSLayoutConstraint *typingIndicatorViewHC;
@property (nonatomic, strong) NSLayoutConstraint *indicatorViewHC;
@property (nonatomic, strong) NSLayoutConstraint *autoCompletionViewHC;
@property (nonatomic, strong) NSLayoutConstraint *keyboardHC;

Expand All @@ -68,14 +68,15 @@ @interface SLKTextViewController ()

// The subclass of SLKTextView class to use
@property (nonatomic, strong) Class textViewClass;
@property (nonatomic, strong) Class indicatorViewClass;

@end

@implementation SLKTextViewController
@synthesize tableView = _tableView;
@synthesize collectionView = _collectionView;
@synthesize scrollView = _scrollView;
@synthesize typingIndicatorView = _typingIndicatorView;
@synthesize indicatorView = _indicatorView;
@synthesize textInputbar = _textInputbar;
@synthesize autoCompletionView = _autoCompletionView;
@synthesize autoCompleting = _autoCompleting;
Expand Down Expand Up @@ -173,9 +174,11 @@ - (void)viewDidLoad
{
[super viewDidLoad];

self.view.backgroundColor = [UIColor whiteColor];

[self.view addSubview:self.scrollViewProxy];
[self.view addSubview:self.autoCompletionView];
[self.view addSubview:self.typingIndicatorView];
[self.view addSubview:self.indicatorView];
[self.view addSubview:self.textInputbar];

[self slk_setupViewConstraints];
Expand Down Expand Up @@ -322,15 +325,26 @@ - (SLKTextInputbar *)textInputbar
return _textInputbar;
}


- (UIView *)indicatorView
{
if (!_indicatorView) {
Class class = self.indicatorViewClass ?: [SLKTypingIndicatorView class];
_indicatorView = [[class alloc] init];
_indicatorView.translatesAutoresizingMaskIntoConstraints = NO;
_indicatorView.hidden = YES;
[_indicatorView addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionNew context:nil];
}
return _indicatorView;
}

- (SLKTypingIndicatorView *)typingIndicatorView
{
if (!_typingIndicatorView)
{
_typingIndicatorView = [SLKTypingIndicatorView new];
_typingIndicatorView.translatesAutoresizingMaskIntoConstraints = NO;
_typingIndicatorView.canResignByTouch = NO;
if ([self.indicatorView isKindOfClass:[SLKTypingIndicatorView class]]) {
return (SLKTypingIndicatorView *)self.indicatorView;
} else {
return nil;
}
return _typingIndicatorView;
}

- (BOOL)isExternalKeyboardDetected
Expand Down Expand Up @@ -401,7 +415,7 @@ - (CGFloat)slk_appropriateScrollViewHeight
height -= self.keyboardHC.constant;
height -= self.textInputbarHC.constant;
height -= self.autoCompletionViewHC.constant;
height -= self.typingIndicatorViewHC.constant;
height -= self.indicatorViewHC.constant;

if (height < 0) return 0;
else return roundf(height);
Expand Down Expand Up @@ -1042,6 +1056,15 @@ - (void)didPressArrowKey:(id)sender

#pragma mark - Notification Events

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object == _indicatorView && [keyPath isEqualToString:@"hidden"]) {
[self slk_willShowOrHideIndicatorView];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}

- (void)slk_willShowOrHideKeyboard:(NSNotification *)notification
{
// Skips if the view isn't visible.
Expand Down Expand Up @@ -1277,26 +1300,19 @@ - (void)slk_didShakeTextView:(NSNotification *)notification
}
}

- (void)slk_willShowOrHideTypeIndicatorView:(NSNotification *)notification
- (void)slk_willShowOrHideIndicatorView
{
SLKTypingIndicatorView *indicatorView = (SLKTypingIndicatorView *)notification.object;

// Skips if it's not the expected typing indicator view.
if (![indicatorView isEqual:self.typingIndicatorView]) {
return;
}

// Skips if the typing indicator should not show. Ignores the checking if it's trying to hide.
if (![self canShowTypeIndicator] && !self.typingIndicatorView.isVisible) {
if (![self canShowTypeIndicator] && self.indicatorView.isHidden) {
return;
}
self.typingIndicatorViewHC.constant = indicatorView.isVisible ? 0.0 : indicatorView.intrinsicContentSize.height;
self.scrollViewHC.constant -= self.typingIndicatorViewHC.constant;

self.indicatorViewHC.constant = self.indicatorView.isHidden ? 0.0 : [self.indicatorView systemLayoutSizeFittingSize:CGSizeZero].height;
self.scrollViewHC.constant -= self.indicatorViewHC.constant;

[self.view slk_animateLayoutIfNeededWithBounce:self.bounces
options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionLayoutSubviews|UIViewAnimationOptionBeginFromCurrentState
animations:NULL];
animations:nil];
}

- (void)slk_willTerminateApplication:(NSNotification *)notification
Expand Down Expand Up @@ -1613,6 +1629,16 @@ - (void)registerClassForTextView:(Class)textViewClass
self.textViewClass = textViewClass;
}

- (void)registerClassForIndicatorView:(Class)indicatorViewClass
{
if (indicatorViewClass == nil) {
return;
}

NSAssert([indicatorViewClass isSubclassOfClass:[UIView class]], @"The registered class is invalid, it must be a subclass for UIView.");
self.indicatorViewClass = indicatorViewClass;
}


#pragma mark - UITextViewDelegate Methods

Expand Down Expand Up @@ -1756,19 +1782,19 @@ - (void)slk_setupViewConstraints
{
NSDictionary *views = @{@"scrollView": self.scrollViewProxy,
@"autoCompletionView": self.autoCompletionView,
@"typingIndicatorView": self.typingIndicatorView,
@"indicatorView": self.indicatorView,
@"textInputbar": self.textInputbar,
};

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView(0@750)][autoCompletionView(0@750)][typingIndicatorView(0)]-0@999-[textInputbar(>=0)]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView(0@750)][autoCompletionView(0@750)][indicatorView(0)]-0@999-[textInputbar(>=0)]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[autoCompletionView]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[typingIndicatorView]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[indicatorView]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[textInputbar]|" options:0 metrics:nil views:views]];

self.scrollViewHC = [self.view slk_constraintForAttribute:NSLayoutAttributeHeight firstItem:self.scrollViewProxy secondItem:nil];
self.autoCompletionViewHC = [self.view slk_constraintForAttribute:NSLayoutAttributeHeight firstItem:self.autoCompletionView secondItem:nil];
self.typingIndicatorViewHC = [self.view slk_constraintForAttribute:NSLayoutAttributeHeight firstItem:self.typingIndicatorView secondItem:nil];
self.indicatorViewHC = [self.view slk_constraintForAttribute:NSLayoutAttributeHeight firstItem:self.indicatorView secondItem:nil];
self.textInputbarHC = [self.view slk_constraintForAttribute:NSLayoutAttributeHeight firstItem:self.textInputbar secondItem:nil];
self.keyboardHC = [self.view slk_constraintForAttribute:NSLayoutAttributeBottom firstItem:self.view secondItem:self.textInputbar];

Expand Down Expand Up @@ -1830,14 +1856,9 @@ - (void)slk_registerNotifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slk_didChangeTextViewContentSize:) name:SLKTextViewContentSizeDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slk_didChangeTextViewSelectedRange:) name:SLKTextViewSelectedRangeDidChangeNotification object:nil];


[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slk_didChangeTextViewPasteboard:) name:SLKTextViewDidPasteItemNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slk_didShakeTextView:) name:SLKTextViewDidShakeNotification object:nil];

// TypeIndicator notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slk_willShowOrHideTypeIndicatorView:) name:SLKTypingIndicatorViewWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slk_willShowOrHideTypeIndicatorView:) name:SLKTypingIndicatorViewWillHideNotification object:nil];

// Application notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slk_willTerminateApplication:) name:UIApplicationWillTerminateNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slk_willTerminateApplication:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
Expand Down Expand Up @@ -1871,10 +1892,6 @@ - (void)slk_unregisterNotifications
[[NSNotificationCenter defaultCenter] removeObserver:self name:SLKTextViewDidPasteItemNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:SLKTextViewDidShakeNotification object:nil];

// TypeIndicator notifications
[[NSNotificationCenter defaultCenter] removeObserver:self name:SLKTypingIndicatorViewWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:SLKTypingIndicatorViewWillHideNotification object:nil];

// Application notifications
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
Expand Down Expand Up @@ -1934,7 +1951,8 @@ - (void)dealloc

_textInputbar.textView.delegate = nil;
_textInputbar = nil;
_typingIndicatorView = nil;
[_indicatorView removeObserver:self forKeyPath:@"hidden"];
_indicatorView = nil;

_registeredPrefixes = nil;
_keyboardCommands = nil;
Expand All @@ -1946,7 +1964,7 @@ - (void)dealloc
_scrollViewHC = nil;
_textInputbarHC = nil;
_textInputbarHC = nil;
_typingIndicatorViewHC = nil;
_indicatorViewHC = nil;
_autoCompletionViewHC = nil;
_keyboardHC = nil;

Expand Down
15 changes: 3 additions & 12 deletions Source/Classes/SLKTypingIndicatorView.m
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ - (UILabel *)textLabel
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
_textLabel.backgroundColor = [UIColor clearColor];
_textLabel.userInteractionEnabled = NO;
_textLabel.hidden = YES;
}
return _textLabel;
}
Expand Down Expand Up @@ -175,18 +174,10 @@ - (void)setVisible:(BOOL)visible

NSString *notificationName = visible ? SLKTypingIndicatorViewWillShowNotification : SLKTypingIndicatorViewWillHideNotification;
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:self];

if (visible) {
self.textLabel.hidden = NO;
}
else {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.textLabel.hidden = YES;
});
}


_visible = visible;

self.hidden = !visible;

if (!visible) {
[self slk_cleanAll];
}
Expand Down