iphone storyboard

Change-Id: I08ffe80fc228997b8a6618248116b52506100a79
This commit is contained in:
siqi
2013-07-03 17:09:52 +02:00
parent 5d0b5f6f42
commit 5da2c45328
7 changed files with 0 additions and 660 deletions

Binary file not shown.

View File

@@ -1,64 +0,0 @@
#import <UIKit/UIKit.h>
#import "MyListController.h"
@class Book;
@class EditableTableViewCell;
// Constants representing the book's fields.
//
enum {
BookTitle,
BookLastName,
BookFirstName,
BookYear,
BookImagePath
};
// Constants representing the various sections of our grouped table view.
//
enum {
TitleSection,
AuthorSection,
YearSection,
ImageSection
};
typedef NSUInteger BookAttribute;
@interface MyDetailController : UITableViewController <UITextFieldDelegate>
{
Book *_book;
MyListController *_listController;
EditableDetailCell *_titleCell;
EditableDetailCell *_firstNameCell;
EditableDetailCell *_lastNameCell;
EditableDetailCell *_yearCell;
EditableDetailCell *_imagePathCell;
}
@property (nonatomic, retain) Book *book;
// Watch out for retain cycles (objects that retain each other can never
// be deallocated). If the list controller were to retain the detail controller,
// we should change 'retain' to 'assign' below to avoid a cycle. (Note that in
// that case, dealloc shouldn't release the list controller.)
//
@property (nonatomic, retain) MyListController *listController;
@property (nonatomic, retain) EditableDetailCell *titleCell;
@property (nonatomic, retain) EditableDetailCell *firstNameCell;
@property (nonatomic, retain) EditableDetailCell *lastNameCell;
@property (nonatomic, retain) EditableDetailCell *yearCell;
@property (nonatomic, retain) EditableDetailCell *imagePathCell;
- (BOOL)isModal;
- (EditableDetailCell *)newDetailCellWithTag:(NSInteger)tag;
// Action Methods
//
- (void)save;
- (void)cancel;
@end

View File

@@ -1,14 +0,0 @@
//
// TPKeyboardAvoidingScrollView.h
//
// Created by Michael Tyson on 11/04/2011.
// Copyright 2011 A Tasty Pixel. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface TPKeyboardAvoidingScrollView : UIScrollView
@property (assign, nonatomic) BOOL autoAdjustsContentSizeToBounds;
- (BOOL)focusNextTextField;
- (void)scrollToActiveTextField;
@end

View File

@@ -1,285 +0,0 @@
//
// TPKeyboardAvoidingScrollView.m
//
// Created by Michael Tyson on 11/04/2011.
// Copyright 2011 A Tasty Pixel. All rights reserved.
//
#import "TPKeyboardAvoidingScrollView.h"
#define _UIKeyboardFrameEndUserInfoKey (&UIKeyboardFrameEndUserInfoKey != NULL ? UIKeyboardFrameEndUserInfoKey : @"UIKeyboardBoundsUserInfoKey")
@interface TPKeyboardAvoidingScrollView () <UITextFieldDelegate, UITextViewDelegate> {
UIEdgeInsets _priorInset;
BOOL _priorInsetSaved;
BOOL _keyboardVisible;
CGRect _keyboardRect;
CGSize _originalContentSize;
}
- (UIView*)findFirstResponderBeneathView:(UIView*)view;
- (UIEdgeInsets)contentInsetForKeyboard;
- (CGFloat)idealOffsetForView:(UIView *)view withSpace:(CGFloat)space;
- (CGRect)keyboardRect;
@end
@implementation TPKeyboardAvoidingScrollView
#pragma mark - Setup/Teardown
- (void)setup {
_priorInsetSaved = NO;
if ( CGSizeEqualToSize(self.contentSize, CGSizeZero) ) {
self.contentSize = self.bounds.size;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
-(id)initWithFrame:(CGRect)frame {
if ( !(self = [super initWithFrame:frame]) ) return nil;
[self setup];
return self;
}
-(void)awakeFromNib {
[self setup];
}
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
#if !__has_feature(objc_arc)
[super dealloc];
#endif
}
-(void)setFrame:(CGRect)frame {
[super setFrame:frame];
[self handleContentSize];
}
-(void)setContentSize:(CGSize)contentSize {
_originalContentSize = contentSize;
[self handleContentSize];
}
-(void)setAutoAdjustsContentSizeToBounds:(BOOL)autoAdjustsContentSizeToBounds {
_autoAdjustsContentSizeToBounds = autoAdjustsContentSizeToBounds;
[self handleContentSize];
}
#pragma mark - Responders, events
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[[self findFirstResponderBeneathView:self] resignFirstResponder];
[super touchesEnded:touches withEvent:event];
}
- (void)keyboardWillShow:(NSNotification*)notification {
_keyboardRect = [[[notification userInfo] objectForKey:_UIKeyboardFrameEndUserInfoKey] CGRectValue];
_keyboardVisible = YES;
UIView *firstResponder = [self findFirstResponderBeneathView:self];
if ( !firstResponder ) {
// No child view is the first responder - nothing to do here
return;
}
if (!_priorInsetSaved) {
_priorInset = self.contentInset;
_priorInsetSaved = YES;
}
// Shrink view's inset by the keyboard's height, and scroll to show the text field/view being edited
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]];
self.contentInset = [self contentInsetForKeyboard];
[self setContentOffset:CGPointMake(self.contentOffset.x,
[self idealOffsetForView:firstResponder withSpace:[self keyboardRect].origin.y - self.bounds.origin.y])
animated:YES];
[self setScrollIndicatorInsets:self.contentInset];
[UIView commitAnimations];
}
- (void)keyboardWillHide:(NSNotification*)notification {
_keyboardRect = CGRectZero;
_keyboardVisible = NO;
// Restore dimensions to prior size
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]];
self.contentInset = _priorInset;
[self setScrollIndicatorInsets:self.contentInset];
_priorInsetSaved = NO;
[UIView commitAnimations];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
if ( ![self focusNextTextField] ) {
[textField resignFirstResponder];
}
return YES;
}
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[self scrollToActiveTextField];
}
-(void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToActiveTextField];
}
-(void)layoutSubviews {
[super layoutSubviews];
[self initializeViewsBeneathView:self];
}
#pragma mark - Utilities
- (BOOL)focusNextTextField {
UIView *firstResponder = [self findFirstResponderBeneathView:self];
if ( !firstResponder ) {
return NO;
}
CGFloat minY = CGFLOAT_MAX;
UIView *view = nil;
[self findTextFieldAfterTextField:firstResponder beneathView:self minY:&minY foundView:&view];
if ( view ) {
[view becomeFirstResponder];
return YES;
}
return NO;
}
-(void)scrollToActiveTextField {
if ( !_keyboardVisible ) return;
CGFloat visibleSpace = self.bounds.size.height - self.contentInset.top - self.contentInset.bottom;
CGPoint idealOffset = CGPointMake(0, [self idealOffsetForView:[self findFirstResponderBeneathView:self] withSpace:visibleSpace]);
[self setContentOffset:idealOffset animated:YES];
}
#pragma mark - Helpers
-(void)handleContentSize {
CGSize contentSize = _autoAdjustsContentSizeToBounds ? self.bounds.size : _originalContentSize;
contentSize.width = MAX(contentSize.width, self.frame.size.width);
contentSize.height = MAX(contentSize.height, self.frame.size.height);
[super setContentSize:contentSize];
if ( _keyboardVisible ) {
self.contentInset = [self contentInsetForKeyboard];
}
}
- (UIView*)findFirstResponderBeneathView:(UIView*)view {
// Search recursively for first responder
for ( UIView *childView in view.subviews ) {
if ( [childView respondsToSelector:@selector(isFirstResponder)] && [childView isFirstResponder] ) return childView;
UIView *result = [self findFirstResponderBeneathView:childView];
if ( result ) return result;
}
return nil;
}
- (void)findTextFieldAfterTextField:(UIView*)priorTextField beneathView:(UIView*)view minY:(CGFloat*)minY foundView:(UIView**)foundView {
// Search recursively for text field or text view below priorTextField
CGFloat priorFieldOffset = CGRectGetMinY([self convertRect:priorTextField.frame fromView:priorTextField.superview]);
for ( UIView *childView in view.subviews ) {
if ( childView.hidden ) continue;
if ( ([childView isKindOfClass:[UITextField class]] || [childView isKindOfClass:[UITextView class]]) ) {
CGRect frame = [self convertRect:childView.frame fromView:view];
if ( childView != priorTextField && CGRectGetMinY(frame) >= priorFieldOffset && CGRectGetMinY(frame) < *minY ) {
*minY = CGRectGetMinY(frame);
*foundView = childView;
}
} else {
[self findTextFieldAfterTextField:priorTextField beneathView:childView minY:minY foundView:foundView];
}
}
}
- (void)initializeViewsBeneathView:(UIView*)view {
for ( UIView *childView in view.subviews ) {
if ( ([childView isKindOfClass:[UITextField class]] || [childView isKindOfClass:[UITextView class]]) ) {
[self initializeView:childView];
} else {
[self initializeViewsBeneathView:childView];
}
}
}
- (UIEdgeInsets)contentInsetForKeyboard {
UIEdgeInsets newInset = self.contentInset;
CGRect keyboardRect = [self keyboardRect];
newInset.bottom = keyboardRect.size.height - ((keyboardRect.origin.y+keyboardRect.size.height) - (self.bounds.origin.y+self.bounds.size.height));
return newInset;
}
-(CGFloat)idealOffsetForView:(UIView *)view withSpace:(CGFloat)space {
// Convert the rect to get the view's distance from the top of the scrollView.
CGRect rect = [view convertRect:view.bounds toView:self];
// Set starting offset to that point
CGFloat offset = rect.origin.y;
if ( self.contentSize.height - offset < space ) {
// Scroll to the bottom
offset = self.contentSize.height - space;
} else {
if ( view.bounds.size.height < space ) {
// Center vertically if there's room
offset -= floor((space-view.bounds.size.height)/2.0);
}
if ( offset + space > self.contentSize.height ) {
// Clamp to content size
offset = self.contentSize.height - space;
}
}
if (offset < 0) offset = 0;
return offset;
}
- (CGRect)keyboardRect {
CGRect keyboardRect = [self convertRect:_keyboardRect fromView:nil];
if ( keyboardRect.origin.y == 0 ) {
CGRect screenBounds = [self convertRect:[UIScreen mainScreen].bounds fromView:nil];
keyboardRect.origin = CGPointMake(0, screenBounds.size.height - keyboardRect.size.height);
}
return keyboardRect;
}
- (void)initializeView:(UIView*)view {
if ( ([view isKindOfClass:[UITextField class]] || [view isKindOfClass:[UITextView class]]) && (![(id)view delegate] || [(id)view delegate] == self) ) {
[(id)view setDelegate:self];
if ( [view isKindOfClass:[UITextField class]] ) {
UIView *otherView = nil;
CGFloat minY = CGFLOAT_MAX;
[self findTextFieldAfterTextField:view beneathView:self minY:&minY foundView:&otherView];
if ( otherView ) {
((UITextField*)view).returnKeyType = UIReturnKeyNext;
} else {
((UITextField*)view).returnKeyType = UIReturnKeyDone;
}
}
}
}
@end

View File

@@ -1,13 +0,0 @@
//
// TPKeyboardAvoidingTableView.h
//
// Created by Michael Tyson on 11/04/2011.
// Copyright 2011 A Tasty Pixel. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface TPKeyboardAvoidingTableView : UITableView
- (BOOL)focusNextTextField;
- (void)scrollToActiveTextField;
@end

View File

@@ -1,284 +0,0 @@
//
// TPKeyboardAvoidingTableView.m
//
// Created by Michael Tyson on 11/04/2011.
// Copyright 2011 A Tasty Pixel. All rights reserved.
//
#import "TPKeyboardAvoidingTableView.h"
#define _UIKeyboardFrameEndUserInfoKey (&UIKeyboardFrameEndUserInfoKey != NULL ? UIKeyboardFrameEndUserInfoKey : @"UIKeyboardBoundsUserInfoKey")
@interface TPKeyboardAvoidingTableView () <UITextFieldDelegate, UITextViewDelegate> {
UIEdgeInsets _priorInset;
BOOL _priorInsetSaved;
BOOL _keyboardVisible;
CGRect _keyboardRect;
CGSize _originalContentSize;
}
- (UIView*)findFirstResponderBeneathView:(UIView*)view;
- (UIEdgeInsets)contentInsetForKeyboard;
- (CGFloat)idealOffsetForView:(UIView *)view withSpace:(CGFloat)space;
- (CGRect)keyboardRect;
@end
@implementation TPKeyboardAvoidingTableView
#pragma mark - Setup/Teardown
- (void)setup {
_priorInsetSaved = NO;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
-(id)initWithFrame:(CGRect)frame {
if ( !(self = [super initWithFrame:frame]) ) return nil;
[self setup];
return self;
}
-(id)initWithFrame:(CGRect)frame style:(UITableViewStyle)withStyle {
if ( !(self = [super initWithFrame:frame style:withStyle]) ) return nil;
[self setup];
return self;
}
-(void)awakeFromNib {
[self setup];
}
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
#if !__has_feature(objc_arc)
[super dealloc];
#endif
}
-(void)setFrame:(CGRect)frame {
[super setFrame:frame];
CGSize contentSize = _originalContentSize;
contentSize.width = MAX(contentSize.width, self.frame.size.width);
contentSize.height = MAX(contentSize.height, self.frame.size.height);
[super setContentSize:contentSize];
if ( _keyboardVisible ) {
self.contentInset = [self contentInsetForKeyboard];
}
}
-(void)setContentSize:(CGSize)contentSize {
_originalContentSize = contentSize;
contentSize.width = MAX(contentSize.width, self.frame.size.width);
contentSize.height = MAX(contentSize.height, self.frame.size.height);
[super setContentSize:contentSize];
if ( _keyboardVisible ) {
self.contentInset = [self contentInsetForKeyboard];
}
}
#pragma mark - Responders, events
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[[self findFirstResponderBeneathView:self] resignFirstResponder];
[super touchesEnded:touches withEvent:event];
}
- (void)keyboardWillShow:(NSNotification*)notification {
_keyboardRect = [[[notification userInfo] objectForKey:_UIKeyboardFrameEndUserInfoKey] CGRectValue];
_keyboardVisible = YES;
UIView *firstResponder = [self findFirstResponderBeneathView:self];
if ( !firstResponder ) {
// No child view is the first responder - nothing to do here
return;
}
if (!_priorInsetSaved) {
_priorInset = self.contentInset;
_priorInsetSaved = YES;
}
// Shrink view's inset by the keyboard's height, and scroll to show the text field/view being edited
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]];
self.contentInset = [self contentInsetForKeyboard];
[self setContentOffset:CGPointMake(self.contentOffset.x,
[self idealOffsetForView:firstResponder withSpace:[self keyboardRect].origin.y - self.bounds.origin.y])
animated:YES];
[self setScrollIndicatorInsets:self.contentInset];
[UIView commitAnimations];
}
- (void)keyboardWillHide:(NSNotification*)notification {
_keyboardRect = CGRectZero;
_keyboardVisible = NO;
// Restore dimensions to prior size
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]];
self.contentInset = _priorInset;
[self setScrollIndicatorInsets:self.contentInset];
_priorInsetSaved = NO;
[UIView commitAnimations];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
if ( ![self focusNextTextField] ) {
[textField resignFirstResponder];
}
return YES;
}
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[self scrollToActiveTextField];
}
-(void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToActiveTextField];
}
-(void)layoutSubviews {
[super layoutSubviews];
[self initializeViewsBeneathView:self];
}
#pragma mark - Utilities
- (BOOL)focusNextTextField {
UIView *firstResponder = [self findFirstResponderBeneathView:self];
if ( !firstResponder ) {
return NO;
}
CGFloat minY = CGFLOAT_MAX;
UIView *view = nil;
[self findTextFieldAfterTextField:firstResponder beneathView:self minY:&minY foundView:&view];
if ( view ) {
[view becomeFirstResponder];
return YES;
}
return NO;
}
-(void)scrollToActiveTextField {
if ( !_keyboardVisible ) return;
CGFloat visibleSpace = self.bounds.size.height - self.contentInset.top - self.contentInset.bottom;
CGPoint idealOffset = CGPointMake(0, [self idealOffsetForView:[self findFirstResponderBeneathView:self] withSpace:visibleSpace]);
[self setContentOffset:idealOffset animated:YES];
}
#pragma mark - Helpers
- (UIView*)findFirstResponderBeneathView:(UIView*)view {
// Search recursively for first responder
for ( UIView *childView in view.subviews ) {
if ( [childView respondsToSelector:@selector(isFirstResponder)] && [childView isFirstResponder] ) return childView;
UIView *result = [self findFirstResponderBeneathView:childView];
if ( result ) return result;
}
return nil;
}
- (void)findTextFieldAfterTextField:(UIView*)priorTextField beneathView:(UIView*)view minY:(CGFloat*)minY foundView:(UIView**)foundView {
// Search recursively for text field or text view below priorTextField
CGFloat priorFieldOffset = CGRectGetMinY([self convertRect:priorTextField.frame fromView:priorTextField.superview]);
for ( UIView *childView in view.subviews ) {
if ( childView.hidden ) continue;
if ( ([childView isKindOfClass:[UITextField class]] || [childView isKindOfClass:[UITextView class]]) ) {
CGRect frame = [self convertRect:childView.frame fromView:view];
if ( childView != priorTextField && CGRectGetMinY(frame) >= priorFieldOffset && CGRectGetMinY(frame) < *minY ) {
*minY = CGRectGetMinY(frame);
*foundView = childView;
}
} else {
[self findTextFieldAfterTextField:priorTextField beneathView:childView minY:minY foundView:foundView];
}
}
}
- (void)initializeViewsBeneathView:(UIView*)view {
for ( UIView *childView in view.subviews ) {
if ( ([childView isKindOfClass:[UITextField class]] || [childView isKindOfClass:[UITextView class]]) ) {
[self initializeView:childView];
} else {
[self initializeViewsBeneathView:childView];
}
}
}
- (UIEdgeInsets)contentInsetForKeyboard {
UIEdgeInsets newInset = self.contentInset;
CGRect keyboardRect = [self keyboardRect];
newInset.bottom = keyboardRect.size.height - ((keyboardRect.origin.y+keyboardRect.size.height) - (self.bounds.origin.y+self.bounds.size.height));
return newInset;
}
-(CGFloat)idealOffsetForView:(UIView *)view withSpace:(CGFloat)space {
// Convert the rect to get the view's distance from the top of the scrollView.
CGRect rect = [view convertRect:view.bounds toView:self];
// Set starting offset to that point
CGFloat offset = rect.origin.y;
if ( self.contentSize.height - offset < space ) {
// Scroll to the bottom
offset = self.contentSize.height - space;
} else {
if ( view.bounds.size.height < space ) {
// Center vertically if there's room
offset -= floor((space-view.bounds.size.height)/2.0);
}
if ( offset + space > self.contentSize.height ) {
// Clamp to content size
offset = self.contentSize.height - space;
}
}
if (offset < 0) offset = 0;
return offset;
}
- (CGRect)keyboardRect {
CGRect keyboardRect = [self convertRect:_keyboardRect fromView:nil];
if ( keyboardRect.origin.y == 0 ) {
CGRect screenBounds = [self convertRect:[UIScreen mainScreen].bounds fromView:nil];
keyboardRect.origin = CGPointMake(0, screenBounds.size.height - keyboardRect.size.height);
}
return keyboardRect;
}
- (void)initializeView:(UIView*)view {
if ( ([view isKindOfClass:[UITextField class]] || [view isKindOfClass:[UITextView class]]) && (![(id)view delegate] || [(id)view delegate] == self) ) {
[(id)view setDelegate:self];
if ( [view isKindOfClass:[UITextField class]] ) {
UIView *otherView = nil;
CGFloat minY = CGFLOAT_MAX;
[self findTextFieldAfterTextField:view beneathView:self minY:&minY foundView:&otherView];
if ( otherView ) {
((UITextField*)view).returnKeyType = UIReturnKeyNext;
} else {
((UITextField*)view).returnKeyType = UIReturnKeyDone;
}
}
}
}
@end