mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-02 17:57:22 +08:00
149 lines
6.2 KiB
Objective-C
149 lines
6.2 KiB
Objective-C
//
|
|
// RKKeyboardScroller.m
|
|
// RestKit
|
|
//
|
|
// Created by Blake Watters on 7/5/12.
|
|
// Copyright (c) 2012 RestKit, Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#import "RKKeyboardScroller.h"
|
|
#import "RKLog.h"
|
|
#import "UIView+FindFirstResponder.h"
|
|
|
|
// Define logging component
|
|
#undef RKLogComponent
|
|
#define RKLogComponent lcl_cRestKitUI
|
|
|
|
@interface RKKeyboardScroller ()
|
|
|
|
@property (nonatomic, retain, readwrite) UIViewController *viewController;
|
|
@property (nonatomic, retain, readwrite) UIScrollView *scrollView;
|
|
@end
|
|
|
|
@implementation RKKeyboardScroller
|
|
|
|
@synthesize viewController = _viewController;
|
|
@synthesize scrollView = _scrollView;
|
|
|
|
- (id)init
|
|
{
|
|
RKLogError(@"Failed to call designated initialized initWithViewController:");
|
|
[self doesNotRecognizeSelector:_cmd];
|
|
[self release];
|
|
return nil;
|
|
}
|
|
|
|
- (id)initWithViewController:(UIViewController *)viewController scrollView:(UIScrollView *)scrollView
|
|
{
|
|
NSAssert(viewController, @"%@ must be instantiated with a viewController.", [self class]);
|
|
NSAssert(scrollView, @"%@ must be instantiated with a scrollView.", [self class]);
|
|
|
|
self = [super init];
|
|
if (self) {
|
|
self.viewController = viewController;
|
|
self.scrollView = scrollView;
|
|
|
|
// Register for Keyboard notifications
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleKeyboardNotification:)
|
|
name:UIKeyboardWillShowNotification
|
|
object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleKeyboardNotification:)
|
|
name:UIKeyboardWillHideNotification
|
|
object:nil];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
self.viewController = nil;
|
|
self.scrollView = nil;
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)handleKeyboardNotification:(NSNotification *)notification
|
|
{
|
|
NSDictionary *userInfo = [notification userInfo];
|
|
|
|
CGRect keyboardEndFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
|
CGFloat heightForViewShift = keyboardEndFrame.size.height;
|
|
RKLogTrace(@"keyboardEndFrame.size.height=%f, heightForViewShift=%f",
|
|
keyboardEndFrame.size.height, heightForViewShift);
|
|
|
|
CGFloat bottomBarOffset = 0.0;
|
|
UINavigationController *navigationController = self.viewController.navigationController;
|
|
if (navigationController && navigationController.toolbar && !navigationController.toolbarHidden) {
|
|
bottomBarOffset += navigationController.toolbar.frame.size.height;
|
|
RKLogTrace(@"Found a visible toolbar. Reducing size of heightForViewShift by=%f", bottomBarOffset);
|
|
}
|
|
|
|
UITabBarController *tabBarController = self.viewController.tabBarController;
|
|
if (tabBarController && tabBarController.tabBar && !self.viewController.hidesBottomBarWhenPushed) {
|
|
bottomBarOffset += tabBarController.tabBar.frame.size.height;
|
|
RKLogTrace(@"Found a visible tabBar. Reducing size of heightForViewShift by=%f", bottomBarOffset);
|
|
}
|
|
|
|
if ([[notification name] isEqualToString:UIKeyboardWillShowNotification]) {
|
|
[UIView beginAnimations:nil context:nil];
|
|
[UIView setAnimationDuration:0.2];
|
|
|
|
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0, 0, (heightForViewShift - bottomBarOffset), 0);
|
|
self.scrollView.contentInset = contentInsets;
|
|
self.scrollView.scrollIndicatorInsets = contentInsets;
|
|
|
|
CGRect nonKeyboardRect = self.scrollView.frame;
|
|
nonKeyboardRect.size.height -= heightForViewShift;
|
|
RKLogTrace(@"Searching for a firstResponder not inside our nonKeyboardRect (%f, %f, %f, %f)",
|
|
nonKeyboardRect.origin.x, nonKeyboardRect.origin.y,
|
|
nonKeyboardRect.size.width, nonKeyboardRect.size.height);
|
|
|
|
UIView *firstResponder = [self.scrollView findFirstResponder];
|
|
if (firstResponder) {
|
|
CGRect firstResponderFrame = firstResponder.frame;
|
|
RKLogTrace(@"Found firstResponder=%@ at (%f, %f, %f, %f)", firstResponder,
|
|
firstResponderFrame.origin.x, firstResponderFrame.origin.y,
|
|
firstResponderFrame.size.width, firstResponderFrame.size.width);
|
|
|
|
if (![firstResponder.superview isEqual:self.scrollView]) {
|
|
firstResponderFrame = [firstResponder.superview convertRect:firstResponderFrame toView:self.scrollView];
|
|
RKLogTrace(@"firstResponder (%@) frame is not in viewToBeResized's coordinate system. Coverted to (%f, %f, %f, %f)",
|
|
firstResponder, firstResponderFrame.origin.x, firstResponderFrame.origin.y,
|
|
firstResponderFrame.size.width, firstResponderFrame.size.height);
|
|
}
|
|
|
|
if (!CGRectContainsPoint(nonKeyboardRect, firstResponderFrame.origin)) {
|
|
RKLogTrace(@"firstResponder (%@) is underneath keyboard. Beginning scroll of tableView to show", firstResponder);
|
|
[self.scrollView scrollRectToVisible:firstResponderFrame animated:YES];
|
|
}
|
|
}
|
|
[UIView commitAnimations];
|
|
|
|
} else if ([[notification name] isEqualToString:UIKeyboardWillHideNotification]) {
|
|
[UIView beginAnimations:nil context:nil];
|
|
[UIView setAnimationDuration:0.2];
|
|
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
|
|
self.scrollView.contentInset = contentInsets;
|
|
self.scrollView.scrollIndicatorInsets = contentInsets;
|
|
[UIView commitAnimations];
|
|
}
|
|
}
|
|
|
|
@end
|