Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Commit

Permalink
- Pickin up firstResponder fix
Browse files Browse the repository at this point in the history
  • Loading branch information
thinktopdown committed Nov 18, 2009
1 parent f3afe71 commit d015ea5
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 3 deletions.
15 changes: 13 additions & 2 deletions src/TTGlobal.m
Expand Up @@ -38,8 +38,19 @@ BOOL TTIsEmptyString(NSObject* object) {
}

BOOL TTIsKeyboardVisible() {
UIWindow* window = [UIApplication sharedApplication].keyWindow;
return !![window performSelector:@selector(firstResponder)];
NSArray *windows = [[UIApplication sharedApplication] windows];
for( UIWindow *window in [windows reverseObjectEnumerator] )
{
for( UIView *view in [window subviews] )
{
if( !strcmp(object_getClassName(view), "UIKeyboard") )
{
return YES;
}
}
}

return NO;
}

UIDeviceOrientation TTDeviceOrientation() {
Expand Down
16 changes: 16 additions & 0 deletions src/TTLabel.m
Expand Up @@ -56,6 +56,22 @@ - (CGSize)sizeThatFits:(CGSize)size {
return [_style addToSize:CGSizeZero context:context];
}


//////////////////////////////////////////////////////////////////////////////////////////////////
// UIAccessibility

- (BOOL)isAccessibilityElement {
return YES;
}

- (NSString *)accessibilityLabel {
return _text;
}

- (UIAccessibilityTraits)accessibilityTraits {
return [super accessibilityTraits] | UIAccessibilityTraitStaticText;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// TTStyleDelegate

Expand Down
8 changes: 8 additions & 0 deletions src/Three20.xcodeproj/project.pbxproj
Expand Up @@ -139,6 +139,8 @@
BEF341970F8042520027E93C /* TTStyledTextLabel.h in Headers */ = {isa = PBXBuildFile; fileRef = BEF341960F8042520027E93C /* TTStyledTextLabel.h */; };
FE15B9BB1015A0D500B5C4E6 /* UIFontAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = FE15B9B91015A0D500B5C4E6 /* UIFontAdditions.h */; };
FE15B9BC1015A0D500B5C4E6 /* UIFontAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = FE15B9BA1015A0D500B5C4E6 /* UIFontAdditions.m */; };
FEF03C0710B39DBA00844C02 /* UIWindowAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = FEF03C0610B39DBA00844C02 /* UIWindowAdditions.m */; };
FEF03C0910B39DC900844C02 /* UIWindowAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF03C0810B39DC900844C02 /* UIWindowAdditions.h */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -275,6 +277,8 @@
BEF341960F8042520027E93C /* TTStyledTextLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTStyledTextLabel.h; path = Three20/TTStyledTextLabel.h; sourceTree = "<group>"; };
FE15B9B91015A0D500B5C4E6 /* UIFontAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UIFontAdditions.h; path = Three20/UIFontAdditions.h; sourceTree = "<group>"; };
FE15B9BA1015A0D500B5C4E6 /* UIFontAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIFontAdditions.m; sourceTree = "<group>"; };
FEF03C0610B39DBA00844C02 /* UIWindowAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIWindowAdditions.m; sourceTree = "<group>"; };
FEF03C0810B39DC900844C02 /* UIWindowAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UIWindowAdditions.h; path = Three20/UIWindowAdditions.h; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -394,6 +398,8 @@
BEAF21210F4D329600D75F3B /* UIWebViewAdditions.m */,
BEAF21390F4D32E100D75F3B /* UIToolbarAdditions.h */,
BEAF211F0F4D329600D75F3B /* UIToolbarAdditions.m */,
FEF03C0810B39DC900844C02 /* UIWindowAdditions.h */,
FEF03C0610B39DBA00844C02 /* UIWindowAdditions.m */,
);
name = Additions;
sourceTree = "<group>";
Expand Down Expand Up @@ -633,6 +639,7 @@
BEA69ECD0FAC0FEC00DA7DDC /* TTWebController.h in Headers */,
BEA762500FBA1E290091B567 /* NSDateAdditions.h in Headers */,
FE15B9BB1015A0D500B5C4E6 /* UIFontAdditions.h in Headers */,
FEF03C0910B39DC900844C02 /* UIWindowAdditions.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -741,6 +748,7 @@
BEA69ECB0FAC0FD600DA7DDC /* TTWebController.m in Sources */,
BEA7624E0FBA1E220091B567 /* NSDateAdditions.m in Sources */,
FE15B9BC1015A0D500B5C4E6 /* UIFontAdditions.m in Sources */,
FEF03C0710B39DBA00844C02 /* UIWindowAdditions.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
1 change: 1 addition & 0 deletions src/Three20/TTGlobal.h
Expand Up @@ -9,6 +9,7 @@
#import "Three20/UIImageAdditions.h"
#import "Three20/UIViewControllerAdditions.h"
#import "Three20/UIViewAdditions.h"
#import "Three20/UIWindowAdditions.h"
#import "Three20/UITableViewAdditions.h"
#import "Three20/UIWebViewAdditions.h"
#import "Three20/UIToolbarAdditions.h"
Expand Down
47 changes: 47 additions & 0 deletions src/Three20/UIViewAdditions.h
Expand Up @@ -20,6 +20,9 @@
@property(nonatomic,readonly) CGFloat screenViewY;
@property(nonatomic,readonly) CGRect screenFrame;

@property(nonatomic) CGPoint origin;
@property(nonatomic) CGSize size;

@property(nonatomic,readonly) CGFloat orientationWidth;
@property(nonatomic,readonly) CGFloat orientationHeight;

Expand All @@ -31,6 +34,17 @@

- (UIView*)findChildWithDescendant:(UIView*)descendant;

/**
* Finds the first descendant view (including this view) that is a member of a particular class.
*/
- (UIView*)descendantOrSelfWithClass:(Class)cls;

/**
* Finds the first ancestor view (including this view) that is a member of a particular class.
*/
- (UIView*)ancestorOrSelfWithClass:(Class)cls;


/**
* Removes all subviews.
*/
Expand All @@ -45,4 +59,37 @@

- (CGPoint)offsetFromView:(UIView*)otherView;

/**
* Calculates the offset of this view from another view in screen coordinates.
*/
- (CGPoint)offsetFromView:(UIView*)otherView;

/**
* Calculates the frame of this view with parts that intersect with the keyboard subtracted.
*
* If the keyboard is not showing, this will simply return the normal frame.
*/
- (CGRect)frameWithKeyboardSubtracted:(CGFloat)plusHeight;

/**
* Shows the view in a window at the bottom of the screen.
*
* This will send a notification pretending that a keyboard is about to appear so that
* observers who adjust their layout for the keyboard will also adjust for this view.
*/
- (void)presentAsKeyboardInView:(UIView*)containingView;

/**
* Hides a view that was showing in a window at the bottom of the screen (via presentAsKeyboard).
*
* This will send a notification pretending that a keyboard is about to disappear so that
* observers who adjust their layout for the keyboard will also adjust for this view.
*/
- (void)dismissAsKeyboard:(BOOL)animated;

/**
* The view controller whose view contains this view.
*/
- (UIViewController*)viewController;

@end
19 changes: 19 additions & 0 deletions src/Three20/UIWindowAdditions.h
@@ -0,0 +1,19 @@
//
// UIWindowAdditions.h
// Three20
//
// Created by Mike on 10/31/09.
// Copyright 2009 Prime31 Studios. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>


@interface UIWindow (TTCategory)

- (UIView*)findFirstResponder;

- (UIView*)findFirstResponderInView:(UIView*)topView;

@end
2 changes: 1 addition & 1 deletion src/UITableViewAdditions.m
Expand Up @@ -50,7 +50,7 @@ - (void)touchRowAtIndexPath:(NSIndexPath*)indexPath animated:(BOOL)animated {
}

- (void)scrollFirstResponderIntoView {
UIView* responder = [self.window performSelector:@selector(firstResponder)];
UIView* responder = [self.window findFirstResponder];
UITableViewCell* cell = (UITableViewCell*)[responder firstParentOfClass:[UITableViewCell class]];
if (cell) {
NSIndexPath* indexPath = [self indexPathForCell:cell];
Expand Down
135 changes: 135 additions & 0 deletions src/UIViewAdditions.m
Expand Up @@ -216,6 +216,26 @@ - (CGRect)screenFrame {
return CGRectMake(self.screenViewX, self.screenViewY, self.width, self.height);
}

- (CGPoint)origin {
return self.frame.origin;
}

- (void)setOrigin:(CGPoint)origin {
CGRect frame = self.frame;
frame.origin = origin;
self.frame = frame;
}

- (CGSize)size {
return self.frame.size;
}

- (void)setSize:(CGSize)size {
CGRect frame = self.frame;
frame.size = size;
self.frame = frame;
}

- (CGPoint)offsetFromView:(UIView*)otherView {
CGFloat x = 0, y = 0;
for (UIView* view = self; view && view != otherView; view = view.superview) {
Expand Down Expand Up @@ -281,6 +301,29 @@ - (UIView*)findChildWithDescendant:(UIView*)descendant {
return nil;
}

- (UIView*)descendantOrSelfWithClass:(Class)cls {
if ([self isKindOfClass:cls])
return self;

for (UIView* child in self.subviews) {
UIView* it = [child descendantOrSelfWithClass:cls];
if (it)
return it;
}

return nil;
}

- (UIView*)ancestorOrSelfWithClass:(Class)cls {
if ([self isKindOfClass:cls]) {
return self;
} else if (self.superview) {
return [self.superview ancestorOrSelfWithClass:cls];
} else {
return nil;
}
}

- (void)removeSubviews {
while (self.subviews.count) {
UIView* child = self.subviews.lastObject;
Expand All @@ -302,4 +345,96 @@ - (void)simulateTapAtPoint:(CGPoint)location {
}
#endif

- (CGRect)frameWithKeyboardSubtracted:(CGFloat)plusHeight {
CGRect frame = self.frame;
if( TTIsKeyboardVisible() )
{
CGRect screenFrame = TTScreenBounds();
CGFloat keyboardTop = (screenFrame.size.height - (TTKeyboardHeight() + plusHeight));
CGFloat screenBottom = self.screenY + frame.size.height;
CGFloat diff = screenBottom - keyboardTop;
if (diff > 0) {
frame.size.height -= diff;
}
}
return frame;
}

- (void)presentAsKeyboardAnimationDidStop {
CGRect screenFrame = TTScreenBounds();
CGRect bounds = CGRectMake(0, 0, screenFrame.size.width, self.height);
CGPoint centerBegin = CGPointMake(floor(screenFrame.size.width/2 - self.width/2),
screenFrame.size.height + floor(self.height/2));
CGPoint centerEnd = CGPointMake(floor(screenFrame.size.width/2 - self.width/2),
screenFrame.size.height - floor(self.height/2));

NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
[NSValue valueWithCGRect:bounds], UIKeyboardBoundsUserInfoKey,
[NSValue valueWithCGPoint:centerBegin], UIKeyboardCenterBeginUserInfoKey,
[NSValue valueWithCGPoint:centerEnd], UIKeyboardCenterEndUserInfoKey,
nil];

[[NSNotificationCenter defaultCenter] postNotificationName:@"UIKeyboardWillShowNotification"
object:self userInfo:userInfo];
}

- (void)dismissAsKeyboardAnimationDidStop {
[self removeFromSuperview];
}

- (void)presentAsKeyboardInView:(UIView*)containingView {
self.top = containingView.height;
[containingView addSubview:self];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:TT_TRANSITION_DURATION];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(presentAsKeyboardAnimationDidStop)];
self.top -= self.height;
[UIView commitAnimations];
}

- (void)dismissAsKeyboard:(BOOL)animated {
CGRect screenFrame = TTScreenBounds();
CGRect bounds = CGRectMake(0, 0, screenFrame.size.width, self.height);
CGPoint centerBegin = CGPointMake(floor(screenFrame.size.width/2 - self.width/2),
screenFrame.size.height - floor(self.height/2));
CGPoint centerEnd = CGPointMake(floor(screenFrame.size.width/2 - self.width/2),
screenFrame.size.height + floor(self.height/2));

NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
[NSValue valueWithCGRect:bounds], UIKeyboardBoundsUserInfoKey,
[NSValue valueWithCGPoint:centerBegin], UIKeyboardCenterBeginUserInfoKey,
[NSValue valueWithCGPoint:centerEnd], UIKeyboardCenterEndUserInfoKey,
nil];

[[NSNotificationCenter defaultCenter] postNotificationName:@"UIKeyboardWillHideNotification"
object:self userInfo:userInfo];

if (animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:TT_TRANSITION_DURATION];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(dismissAsKeyboardAnimationDidStop)];
}

self.top += self.height;

if (animated) {
[UIView commitAnimations];
} else {
[self dismissAsKeyboardAnimationDidStop];
}
}

- (UIViewController*)viewController {
for (UIView* next = [self superview]; next; next = next.superview) {
UIResponder* nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController*)nextResponder;
}
}
return nil;
}

@end
37 changes: 37 additions & 0 deletions src/UIWindowAdditions.m
@@ -0,0 +1,37 @@
//
// UIWindowAdditions.m
// Three20
//
// Created by Mike on 10/31/09.
// Copyright 2009 Prime31 Studios. All rights reserved.
//

#import "UIWindowAdditions.h"


@implementation UIWindow (TTCategory)

- (UIView*)findFirstResponder
{
return [self findFirstResponderInView:self];
}


- (UIView*)findFirstResponderInView:(UIView*)topView
{
if( [topView isFirstResponder] )
return topView;

for( UIView *subView in topView.subviews )
{
if( [subView isFirstResponder] )
return subView;

UIView *firstResponderCheck = [self findFirstResponderInView:subView];
if( firstResponderCheck != nil )
return firstResponderCheck;
}
return nil;
}

@end

0 comments on commit d015ea5

Please sign in to comment.