Wizard: add TPKeyboardAvoiding framework and use it to remove frame resizing code

This commit is contained in:
Gautier Pelloux-Prayer 2015-07-16 15:34:25 +02:00
parent 009bb78e7c
commit a764686db3
16 changed files with 720 additions and 176 deletions

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment defaultVersion="1072" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="WizardViewController">
@ -20,7 +20,7 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" tag="1" contentMode="scaleToFill" bounces="NO" showsHorizontalScrollIndicator="NO" id="98" userLabel="contentView">
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" tag="1" contentMode="scaleToFill" bounces="NO" showsHorizontalScrollIndicator="NO" id="98" userLabel="contentView" customClass="TPKeyboardAvoidingScrollView">
<rect key="frame" x="0.0" y="0.0" width="320" height="394"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</scrollView>
@ -97,6 +97,8 @@
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
</objects>
<resources>
@ -109,4 +111,9 @@
<image name="setup_start_default.png" width="320" height="154"/>
<image name="setup_start_over.png" width="320" height="154"/>
</resources>
</document>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="5056" systemVersion="13C1021" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment defaultVersion="1536" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="WizardViewController">
@ -21,7 +21,7 @@
<rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" tag="1" contentMode="scaleToFill" bounces="NO" showsHorizontalScrollIndicator="NO" id="98" userLabel="contentView">
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" tag="1" contentMode="scaleToFill" bounces="NO" showsHorizontalScrollIndicator="NO" id="98" userLabel="contentView" customClass="TPKeyboardAvoidingScrollView">
<rect key="frame" x="0.0" y="0.0" width="768" height="966"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</scrollView>
@ -98,12 +98,14 @@
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
<view contentMode="scaleToFill" id="118" userLabel="Landscape View">
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" tag="1" contentMode="scaleToFill" bounces="NO" showsHorizontalScrollIndicator="NO" id="119" userLabel="contentView">
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" tag="1" contentMode="scaleToFill" bounces="NO" showsHorizontalScrollIndicator="NO" id="119" userLabel="contentView" customClass="TPKeyboardAvoidingScrollView">
<rect key="frame" x="0.0" y="0.0" width="1024" height="711"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</scrollView>
@ -180,6 +182,8 @@
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
</objects>
<resources>
@ -200,4 +204,9 @@
<image name="setup_start_over.png" width="320" height="154"/>
<image name="setup_start_over_landscape.png" width="1024" height="171"/>
</resources>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="WizardViewController">
@ -22,7 +22,6 @@
<outlet property="provisionedDomain" destination="wRB-Sh-K8J" id="Ieb-x8-yL4"/>
<outlet property="provisionedPassword" destination="ClH-fT-a8N" id="h61-p1-4qG"/>
<outlet property="provisionedUsername" destination="MyR-eX-QTa" id="gmr-FI-hpH"/>
<outlet property="purchaseButton" destination="uIp-br-8Kv" id="Ov2-V4-LLx"/>
<outlet property="registerButton" destination="77" id="A9h-Es-kxv"/>
<outlet property="remoteProvisioningButton" destination="Kbn-dL-C5h" id="PPk-DJ-nEb"/>
<outlet property="transportChooser" destination="Nrv-SM-lMf" id="7iR-aG-eQf"/>
@ -244,22 +243,6 @@
<action selector="onRegisterClick:" destination="-1" eventType="touchUpInside" id="113"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" id="uIp-br-8Kv" userLabel="purchaseButton" customClass="UILinphoneButton">
<rect key="frame" x="33" y="481" width="255" height="73"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Purchase"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<state key="normal" title="Purchase" backgroundImage="button_background_default.png">
<color key="titleColor" red="0.35686274509999999" green="0.39607843139999999" blue="0.43529411759999997" alpha="1" colorSpace="deviceRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted" backgroundImage="button_background_over.png">
<color key="titleColor" red="0.72549019609999998" green="0.76862745099999996" blue="0.79607843140000001" alpha="1" colorSpace="deviceRGB"/>
</state>
<connections>
<action selector="onPurchaseAccountClick:" destination="-1" eventType="touchUpInside" id="BR1-hP-14E"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<point key="canvasLocation" x="927" y="295"/>

View file

@ -44,9 +44,8 @@
- (instancetype)init {
if ((self = [super init]) != nil) {
_enabled =
(([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) && ([SKPaymentQueue canMakePayments]) &&
([[LinphoneManager instance] lpConfigBoolForKey:@"enabled" forSection:@"in_app_purchase"]));
_enabled = (([SKPaymentQueue canMakePayments]) &&
([[LinphoneManager instance] lpConfigBoolForKey:@"enabled" forSection:@"in_app_purchase"]));
_initialized = false;
_available = false;
_accountActivationInProgress = false;

View file

@ -0,0 +1,20 @@
Copyright (c) 2013 Michael Tyson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.

View file

@ -0,0 +1,14 @@
//
// TPKeyboardAvoidingCollectionView.h
//
// Created by Michael Tyson on 30/09/2013.
// Copyright 2013 A Tasty Pixel & The CocoaBots. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "UIScrollView+TPKeyboardAvoidingAdditions.h"
@interface TPKeyboardAvoidingCollectionView : UICollectionView <UITextFieldDelegate, UITextViewDelegate>
- (BOOL)focusNextTextField;
- (void)scrollToActiveTextField;
@end

View file

@ -0,0 +1,96 @@
//
// TPKeyboardAvoidingCollectionView.m
//
// Created by Michael Tyson on 30/09/2013.
// Copyright 2013 A Tasty Pixel & The CocoaBots. All rights reserved.
//
#import "TPKeyboardAvoidingCollectionView.h"
@interface TPKeyboardAvoidingCollectionView () <UITextFieldDelegate, UITextViewDelegate>
@end
@implementation TPKeyboardAvoidingCollectionView
#pragma mark - Setup/Teardown
- (void)setup {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
-(id)initWithFrame:(CGRect)frame {
if ( !(self = [super initWithFrame:frame]) ) return nil;
[self setup];
return self;
}
- (id)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout {
if ( !(self = [super initWithFrame:frame collectionViewLayout:layout]) ) 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 TPKeyboardAvoiding_updateContentInset];
}
-(void)setContentSize:(CGSize)contentSize {
if (CGSizeEqualToSize(contentSize, self.contentSize)) {
// Prevent triggering contentSize when it's already the same that
// cause weird infinte scrolling and locking bug
return;
}
[super setContentSize:contentSize];
[self TPKeyboardAvoiding_updateContentInset];
}
- (BOOL)focusNextTextField {
return [self TPKeyboardAvoiding_focusNextTextField];
}
- (void)scrollToActiveTextField {
return [self TPKeyboardAvoiding_scrollToActiveTextField];
}
#pragma mark - Responders, events
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[[self TPKeyboardAvoiding_findFirstResponderBeneathView:self] resignFirstResponder];
[super touchesEnded:touches withEvent:event];
}
-(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];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) object:self];
[self performSelector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) withObject:self afterDelay:0.1];
}
@end

View file

@ -0,0 +1,15 @@
//
// TPKeyboardAvoidingScrollView.h
//
// Created by Michael Tyson on 30/09/2013.
// Copyright 2013 A Tasty Pixel. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "UIScrollView+TPKeyboardAvoidingAdditions.h"
@interface TPKeyboardAvoidingScrollView : UIScrollView <UITextFieldDelegate, UITextViewDelegate>
- (void)contentSizeToFit;
- (BOOL)focusNextTextField;
- (void)scrollToActiveTextField;
@end

View file

@ -0,0 +1,89 @@
//
// TPKeyboardAvoidingScrollView.m
//
// Created by Michael Tyson on 30/09/2013.
// Copyright 2013 A Tasty Pixel. All rights reserved.
//
#import "TPKeyboardAvoidingScrollView.h"
@interface TPKeyboardAvoidingScrollView () <UITextFieldDelegate, UITextViewDelegate>
@end
@implementation TPKeyboardAvoidingScrollView
#pragma mark - Setup/Teardown
- (void)setup {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_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 TPKeyboardAvoiding_updateContentInset];
}
-(void)setContentSize:(CGSize)contentSize {
[super setContentSize:contentSize];
[self TPKeyboardAvoiding_updateFromContentSizeChange];
}
- (void)contentSizeToFit {
self.contentSize = [self TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames];
}
- (BOOL)focusNextTextField {
return [self TPKeyboardAvoiding_focusNextTextField];
}
- (void)scrollToActiveTextField {
return [self TPKeyboardAvoiding_scrollToActiveTextField];
}
#pragma mark - Responders, events
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[[self TPKeyboardAvoiding_findFirstResponderBeneathView:self] resignFirstResponder];
[super touchesEnded:touches withEvent:event];
}
-(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];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) object:self];
[self performSelector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) withObject:self afterDelay:0.1];
}
@end

View file

@ -0,0 +1,14 @@
//
// TPKeyboardAvoidingTableView.h
//
// Created by Michael Tyson on 30/09/2013.
// Copyright 2013 A Tasty Pixel. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "UIScrollView+TPKeyboardAvoidingAdditions.h"
@interface TPKeyboardAvoidingTableView : UITableView <UITextFieldDelegate, UITextViewDelegate>
- (BOOL)focusNextTextField;
- (void)scrollToActiveTextField;
@end

View file

@ -0,0 +1,91 @@
//
// TPKeyboardAvoidingTableView.m
//
// Created by Michael Tyson on 30/09/2013.
// Copyright 2013 A Tasty Pixel. All rights reserved.
//
#import "TPKeyboardAvoidingTableView.h"
@interface TPKeyboardAvoidingTableView () <UITextFieldDelegate, UITextViewDelegate>
@end
@implementation TPKeyboardAvoidingTableView
#pragma mark - Setup/Teardown
- (void)setup {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_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];
[self TPKeyboardAvoiding_updateContentInset];
}
-(void)setContentSize:(CGSize)contentSize {
[super setContentSize:contentSize];
[self TPKeyboardAvoiding_updateContentInset];
}
- (BOOL)focusNextTextField {
return [self TPKeyboardAvoiding_focusNextTextField];
}
- (void)scrollToActiveTextField {
return [self TPKeyboardAvoiding_scrollToActiveTextField];
}
#pragma mark - Responders, events
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[[self TPKeyboardAvoiding_findFirstResponderBeneathView:self] resignFirstResponder];
[super touchesEnded:touches withEvent:event];
}
-(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];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) object:self];
[self performSelector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) withObject:self afterDelay:0.1];
}
@end

View file

@ -0,0 +1,22 @@
//
// UIScrollView+TPKeyboardAvoidingAdditions.h
// TPKeyboardAvoidingSample
//
// Created by Michael Tyson on 30/09/2013.
// Copyright 2013 A Tasty Pixel. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface UIScrollView (TPKeyboardAvoidingAdditions)
- (BOOL)TPKeyboardAvoiding_focusNextTextField;
- (void)TPKeyboardAvoiding_scrollToActiveTextField;
- (void)TPKeyboardAvoiding_keyboardWillShow:(NSNotification*)notification;
- (void)TPKeyboardAvoiding_keyboardWillHide:(NSNotification*)notification;
- (void)TPKeyboardAvoiding_updateContentInset;
- (void)TPKeyboardAvoiding_updateFromContentSizeChange;
- (void)TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:(UIView*)view;
- (UIView*)TPKeyboardAvoiding_findFirstResponderBeneathView:(UIView*)view;
-(CGSize)TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames;
@end

View file

@ -0,0 +1,285 @@
//
// UIScrollView+TPKeyboardAvoidingAdditions.m
// TPKeyboardAvoidingSample
//
// Created by Michael Tyson on 30/09/2013.
// Copyright 2013 A Tasty Pixel. All rights reserved.
//
#import "UIScrollView+TPKeyboardAvoidingAdditions.h"
#import "TPKeyboardAvoidingScrollView.h"
#import <objc/runtime.h>
static const CGFloat kCalculatedContentPadding = 10;
static const CGFloat kMinimumScrollOffsetPadding = 20;
static const int kStateKey;
#define _UIKeyboardFrameEndUserInfoKey (&UIKeyboardFrameEndUserInfoKey != NULL ? UIKeyboardFrameEndUserInfoKey : @"UIKeyboardBoundsUserInfoKey")
@interface TPKeyboardAvoidingState : NSObject
@property (nonatomic, assign) UIEdgeInsets priorInset;
@property (nonatomic, assign) UIEdgeInsets priorScrollIndicatorInsets;
@property (nonatomic, assign) BOOL keyboardVisible;
@property (nonatomic, assign) CGRect keyboardRect;
@property (nonatomic, assign) CGSize priorContentSize;
@end
@implementation UIScrollView (TPKeyboardAvoidingAdditions)
- (TPKeyboardAvoidingState*)keyboardAvoidingState {
TPKeyboardAvoidingState *state = objc_getAssociatedObject(self, &kStateKey);
if ( !state ) {
state = [[TPKeyboardAvoidingState alloc] init];
objc_setAssociatedObject(self, &kStateKey, state, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
#if !__has_feature(objc_arc)
[state release];
#endif
}
return state;
}
- (void)TPKeyboardAvoiding_keyboardWillShow:(NSNotification*)notification {
TPKeyboardAvoidingState *state = self.keyboardAvoidingState;
if ( state.keyboardVisible ) {
return;
}
UIView *firstResponder = [self TPKeyboardAvoiding_findFirstResponderBeneathView:self];
state.keyboardRect = [self convertRect:[[[notification userInfo] objectForKey:_UIKeyboardFrameEndUserInfoKey] CGRectValue] fromView:nil];
state.keyboardVisible = YES;
state.priorInset = self.contentInset;
state.priorScrollIndicatorInsets = self.scrollIndicatorInsets;
if ( [self isKindOfClass:[TPKeyboardAvoidingScrollView class]] ) {
state.priorContentSize = self.contentSize;
if ( CGSizeEqualToSize(self.contentSize, CGSizeZero) ) {
// Set the content size, if it's not set. Do not set content size explicitly if auto-layout
// is being used to manage subviews
self.contentSize = [self TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames];
}
}
// 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 TPKeyboardAvoiding_contentInsetForKeyboard];
if ( firstResponder ) {
CGFloat viewableHeight = self.bounds.size.height - self.contentInset.top - self.contentInset.bottom;
[self setContentOffset:CGPointMake(self.contentOffset.x,
[self TPKeyboardAvoiding_idealOffsetForView:firstResponder
withViewingAreaHeight:viewableHeight])
animated:NO];
}
self.scrollIndicatorInsets = self.contentInset;
[UIView commitAnimations];
}
- (void)TPKeyboardAvoiding_keyboardWillHide:(NSNotification*)notification {
TPKeyboardAvoidingState *state = self.keyboardAvoidingState;
if ( !state.keyboardVisible ) {
return;
}
state.keyboardRect = CGRectZero;
state.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]];
if ( [self isKindOfClass:[TPKeyboardAvoidingScrollView class]] ) {
self.contentSize = state.priorContentSize;
}
self.contentInset = state.priorInset;
self.scrollIndicatorInsets = state.priorScrollIndicatorInsets;
[UIView commitAnimations];
}
- (void)TPKeyboardAvoiding_updateContentInset {
TPKeyboardAvoidingState *state = self.keyboardAvoidingState;
if ( state.keyboardVisible ) {
self.contentInset = [self TPKeyboardAvoiding_contentInsetForKeyboard];
}
}
- (void)TPKeyboardAvoiding_updateFromContentSizeChange {
TPKeyboardAvoidingState *state = self.keyboardAvoidingState;
if ( state.keyboardVisible ) {
state.priorContentSize = self.contentSize;
self.contentInset = [self TPKeyboardAvoiding_contentInsetForKeyboard];
}
}
#pragma mark - Utilities
- (BOOL)TPKeyboardAvoiding_focusNextTextField {
UIView *firstResponder = [self TPKeyboardAvoiding_findFirstResponderBeneathView:self];
if ( !firstResponder ) {
return NO;
}
CGFloat minY = CGFLOAT_MAX;
UIView *view = nil;
[self TPKeyboardAvoiding_findTextFieldAfterTextField:firstResponder beneathView:self minY:&minY foundView:&view];
if ( view ) {
[view performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
return YES;
}
return NO;
}
-(void)TPKeyboardAvoiding_scrollToActiveTextField {
TPKeyboardAvoidingState *state = self.keyboardAvoidingState;
if ( !state.keyboardVisible ) return;
CGFloat visibleSpace = self.bounds.size.height - self.contentInset.top - self.contentInset.bottom;
CGPoint idealOffset = CGPointMake(0, [self TPKeyboardAvoiding_idealOffsetForView:[self TPKeyboardAvoiding_findFirstResponderBeneathView:self]
withViewingAreaHeight:visibleSpace]);
// Ordinarily we'd use -setContentOffset:animated:YES here, but it does not appear to
// scroll to the desired content offset. So we wrap in our own animation block.
[UIView animateWithDuration:0.25 animations:^{
[self setContentOffset:idealOffset animated:NO];
}];
}
#pragma mark - Helpers
- (UIView*)TPKeyboardAvoiding_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 TPKeyboardAvoiding_findFirstResponderBeneathView:childView];
if ( result ) return result;
}
return nil;
}
- (void)TPKeyboardAvoiding_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]]) && childView.isUserInteractionEnabled) {
CGRect frame = [self convertRect:childView.frame fromView:view];
if ( childView != priorTextField
&& CGRectGetMinY(frame) >= priorFieldOffset
&& CGRectGetMinY(frame) < *minY &&
!(frame.origin.y == priorTextField.frame.origin.y
&& frame.origin.x < priorTextField.frame.origin.x) ) {
*minY = CGRectGetMinY(frame);
*foundView = childView;
}
} else {
[self TPKeyboardAvoiding_findTextFieldAfterTextField:priorTextField beneathView:childView minY:minY foundView:foundView];
}
}
}
- (void)TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:(UIView*)view {
for ( UIView *childView in view.subviews ) {
if ( ([childView isKindOfClass:[UITextField class]] || [childView isKindOfClass:[UITextView class]]) ) {
[self TPKeyboardAvoiding_initializeView:childView];
} else {
[self TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:childView];
}
}
}
-(CGSize)TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames {
BOOL wasShowingVerticalScrollIndicator = self.showsVerticalScrollIndicator;
BOOL wasShowingHorizontalScrollIndicator = self.showsHorizontalScrollIndicator;
self.showsVerticalScrollIndicator = NO;
self.showsHorizontalScrollIndicator = NO;
CGRect rect = CGRectZero;
for ( UIView *view in self.subviews ) {
rect = CGRectUnion(rect, view.frame);
}
rect.size.height += kCalculatedContentPadding;
self.showsVerticalScrollIndicator = wasShowingVerticalScrollIndicator;
self.showsHorizontalScrollIndicator = wasShowingHorizontalScrollIndicator;
return rect.size;
}
- (UIEdgeInsets)TPKeyboardAvoiding_contentInsetForKeyboard {
TPKeyboardAvoidingState *state = self.keyboardAvoidingState;
UIEdgeInsets newInset = self.contentInset;
CGRect keyboardRect = state.keyboardRect;
newInset.bottom = keyboardRect.size.height - (CGRectGetMaxY(keyboardRect) - CGRectGetMaxY(self.bounds));
return newInset;
}
-(CGFloat)TPKeyboardAvoiding_idealOffsetForView:(UIView *)view withViewingAreaHeight:(CGFloat)viewAreaHeight {
CGSize contentSize = self.contentSize;
CGFloat offset = 0.0;
CGRect subviewRect = [view convertRect:view.bounds toView:self];
// Attempt to center the subview in the visible space, but if that means there will be less than kMinimumScrollOffsetPadding
// pixels above the view, then substitute kMinimumScrollOffsetPadding
CGFloat padding = (viewAreaHeight - subviewRect.size.height) / 2;
if ( padding < kMinimumScrollOffsetPadding ) {
padding = kMinimumScrollOffsetPadding;
}
// Ideal offset places the subview rectangle origin "padding" points from the top of the scrollview.
// If there is a top contentInset, also compensate for this so that subviewRect will not be placed under
// things like navigation bars.
offset = subviewRect.origin.y - padding - self.contentInset.top;
// Constrain the new contentOffset so we can't scroll past the bottom. Note that we don't take the bottom
// inset into account, as this is manipulated to make space for the keyboard.
if ( offset > (contentSize.height - viewAreaHeight) ) {
offset = contentSize.height - viewAreaHeight;
}
// Constrain the new contentOffset so we can't scroll past the top, taking contentInsets into account
if ( offset < -self.contentInset.top ) {
offset = -self.contentInset.top;
}
return offset;
}
- (void)TPKeyboardAvoiding_initializeView:(UIView*)view {
if ( [view isKindOfClass:[UITextField class]] && ((UITextField*)view).returnKeyType == UIReturnKeyDefault && (![(id)view delegate] || [(UIScrollView*)view delegate] == (id<UIScrollViewDelegate>)self) ) {
[(UIScrollView*)view setDelegate:(id<UIScrollViewDelegate>)self];
UIView *otherView = nil;
CGFloat minY = CGFLOAT_MAX;
[self TPKeyboardAvoiding_findTextFieldAfterTextField:view beneathView:self minY:&minY foundView:&otherView];
if ( otherView ) {
((UITextField*)view).returnKeyType = UIReturnKeyNext;
} else {
((UITextField*)view).returnKeyType = UIReturnKeyDone;
}
}
}
@end
@implementation TPKeyboardAvoidingState
@end

View file

@ -22,6 +22,7 @@
#import "UICompositeViewController.h"
#import "UILinphoneTextField.h"
#import "LinphoneUI/UILinphoneButton.h"
#import "TPKeyboardAvoidingScrollView.h"
@interface WizardViewController : TPMultiLayoutViewController
<UITextFieldDelegate,
@ -37,7 +38,7 @@
NSMutableArray *historyViews;
}
@property (nonatomic, strong) IBOutlet UIScrollView *contentView;
@property(nonatomic, strong) IBOutlet TPKeyboardAvoidingScrollView *contentView;
@property (nonatomic, strong) IBOutlet UIView *welcomeView;
@property (nonatomic, strong) IBOutlet UIView *choiceView;
@ -56,7 +57,6 @@
@property (nonatomic, strong) IBOutlet UIButton *externalAccountButton;
@property (strong, nonatomic) IBOutlet UIButton *remoteProvisioningButton;
@property (strong, nonatomic) IBOutlet UILinphoneButton *registerButton;
@property (strong, nonatomic) IBOutlet UILinphoneButton *purchaseButton;
@property (strong, nonatomic) IBOutlet UILinphoneTextField *createAccountUsername;
@property (strong, nonatomic) IBOutlet UILinphoneTextField *connectAccountUsername;
@ -83,7 +83,6 @@
- (IBAction)onExternalAccountClick:(id)sender;
- (IBAction)onCheckValidationClick:(id)sender;
- (IBAction)onRemoteProvisioningClick:(id)sender;
- (IBAction)onPurchaseAccountClick:(id)sender;
- (IBAction)onSignInClick:(id)sender;
- (IBAction)onSignInExternalClick:(id)sender;

View file

@ -109,7 +109,6 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(registrationUpdateEvent:)
name:kLinphoneRegistrationUpdate
@ -118,39 +117,11 @@ static UICompositeViewDescription *compositeDescription = nil;
selector:@selector(configuringUpdate:)
name:kLinphoneConfiguringStateUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(inAppPurchaseNotification:)
name:kIAPPurchaseSucceeded
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(inAppPurchaseNotification:)
name:kIAPPurchaseTrying
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(inAppPurchaseNotification:)
name:kIAPPurchaseFailed
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneRegistrationUpdate object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneConfiguringStateUpdate object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kIAPPurchaseFailed object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kIAPPurchaseTrying object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kIAPPurchaseSucceeded object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)viewDidLoad {
@ -183,12 +154,6 @@ static UICompositeViewDescription *compositeDescription = nil;
text.placeholder = NSLocalizedString(@"Username", nil);
}
}
BOOL mustPurchaseNewAccount =
([[[LinphoneManager instance] iapManager] enabled] &&
[[LinphoneManager instance] lpConfigStringForKey:@"paid_account_id" forSection:@"in_app_purchase"] != nil);
_registerButton.hidden = mustPurchaseNewAccount;
_purchaseButton.hidden = !mustPurchaseNewAccount;
}
#pragma mark -
@ -882,46 +847,6 @@ static UICompositeViewDescription *compositeDescription = nil;
}
}
- (void)inAppPurchaseNotification:(NSNotification *)notification {
BOOL wasWaitingForInApp = (currentView == createAccountView);
NSString *paidAccountID =
[[LinphoneManager instance] lpConfigStringForKey:@"paid_account_id" forSection:@"in_app_purchase"];
if (wasWaitingForInApp && [paidAccountID isEqualToString:[notification.userInfo objectForKey:@"product_id"]]) {
if ([notification.name isEqual:kIAPPurchaseTrying]) {
[waitView setHidden:false];
} else if ([notification.name isEqual:kIAPPurchaseFailed]) {
[waitView setHidden:true];
} else if ([notification.name isEqual:kIAPPurchaseSucceeded]) {
[waitView setHidden:true];
// now that the purchase is made, let's create the account.
[self onPurchaseAccountClick:self];
}
}
}
- (IBAction)onPurchaseAccountClick:(id)sender {
UITextField *username_tf = [WizardViewController findTextField:ViewElement_Username view:contentView];
NSString *username = username_tf.text;
NSString *password = [WizardViewController findTextField:ViewElement_Password view:contentView].text;
NSString *password2 = [WizardViewController findTextField:ViewElement_Password2 view:contentView].text;
NSString *email = [WizardViewController findTextField:ViewElement_Email view:contentView].text;
if ([self verificationRegisterWithUsername:username password:password password2:password2 email:email]) {
InAppProductsManager *iapm = [[LinphoneManager instance] iapManager];
// if has already purchased, continue
if ([iapm isPurchasedWithID:[[LinphoneManager instance] lpConfigStringForKey:@"paid_account_id"
forSection:@"in_app_purchase"]]) {
username = [username lowercaseString];
[username_tf setText:username];
NSString *identity = [self identityFromUsername:username];
[self checkUserExist:identity];
} else {
[iapm purchaseAccount:username withPassword:password andEmail:email monthly:FALSE];
// inAppPurchaseNotification will take care of bringing us to the next view now
}
}
}
- (IBAction)onProvisionedLoginClick:(id)sender {
NSString *username = provisionedUsername.text;
NSString *password = provisionedPassword.text;
@ -946,6 +871,10 @@ static UICompositeViewDescription *compositeDescription = nil;
}
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[contentView contentSizeToFit];
}
- (IBAction)onViewTap:(id)sender {
[LinphoneUtils findAndResignFirstResponder:currentView];
}
@ -1009,71 +938,6 @@ static UICompositeViewDescription *compositeDescription = nil;
[self registrationUpdate:[[notif.userInfo objectForKey:@"state"] intValue] message:message];
}
#pragma mark - Keyboard Event Functions
- (void)keyboardWillHide:(NSNotification *)notif {
// CGRect beginFrame = [[[notif userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
// CGRect endFrame = [[[notif userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
UIViewAnimationCurve curve = [[[notif userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
NSTimeInterval duration = [[[notif userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView beginAnimations:@"resize" context:nil];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:TRUE];
// Move view
UIEdgeInsets inset = {0, 0, 0, 0};
[contentView setContentInset:inset];
[contentView setScrollIndicatorInsets:inset];
[contentView setShowsVerticalScrollIndicator:FALSE];
[UIView commitAnimations];
}
- (void)keyboardWillShow:(NSNotification *)notif {
// CGRect beginFrame = [[[notif userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect endFrame = [[[notif userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
UIViewAnimationCurve curve = [[[notif userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
NSTimeInterval duration = [[[notif userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView beginAnimations:@"resize" context:nil];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:TRUE];
if (([[UIDevice currentDevice].systemVersion floatValue] < 8) &&
UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
int width = endFrame.size.height;
endFrame.size.height = endFrame.size.width;
endFrame.size.width = width;
}
// Change inset
{
UIEdgeInsets inset = {0, 0, 0, 0};
CGRect frame = [contentView frame];
CGRect rect = [PhoneMainView instance].view.bounds;
CGPoint pos = {frame.size.width, frame.size.height};
CGPoint gPos =
[contentView convertPoint:pos
toView:[UIApplication sharedApplication].keyWindow.rootViewController.view]; // Bypass
// IOS bug
// on
// landscape
// mode
inset.bottom = -(rect.size.height - gPos.y - endFrame.size.height);
if (inset.bottom < 0)
inset.bottom = 0;
[contentView setContentInset:inset];
[contentView setScrollIndicatorInsets:inset];
CGRect fieldFrame = activeTextField.frame;
fieldFrame.origin.y += fieldFrame.size.height;
[contentView scrollRectToVisible:fieldFrame animated:TRUE];
[contentView setShowsVerticalScrollIndicator:TRUE];
}
[UIView commitAnimations];
}
#pragma mark - XMLRPCConnectionDelegate Functions
- (void)request:(XMLRPCRequest *)request didReceiveResponse:(XMLRPCResponse *)response {

View file

@ -163,6 +163,11 @@
639CEB061A1DF4F1004DE38F /* UIChatRoomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB081A1DF4F1004DE38F /* UIChatRoomCell.xib */; };
639CEB091A1DF4FA004DE38F /* UIChatCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB0B1A1DF4FA004DE38F /* UIChatCell.xib */; };
63A4280A1B26F576000DAB93 /* libSKP_SILK_SDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 226183AA1472527D0037138E /* libSKP_SILK_SDK.a */; };
63B81A0C1B57DA33009604A6 /* LICENSE.txt in Resources */ = {isa = PBXBuildFile; fileRef = 63B81A031B57DA33009604A6 /* LICENSE.txt */; };
63B81A0D1B57DA33009604A6 /* TPKeyboardAvoidingCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B81A051B57DA33009604A6 /* TPKeyboardAvoidingCollectionView.m */; };
63B81A0E1B57DA33009604A6 /* TPKeyboardAvoidingScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B81A071B57DA33009604A6 /* TPKeyboardAvoidingScrollView.m */; };
63B81A0F1B57DA33009604A6 /* TPKeyboardAvoidingTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B81A091B57DA33009604A6 /* TPKeyboardAvoidingTableView.m */; };
63B81A101B57DA33009604A6 /* UIScrollView+TPKeyboardAvoidingAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B81A0B1B57DA33009604A6 /* UIScrollView+TPKeyboardAvoidingAdditions.m */; };
63C458261B5680AC009F2D7E /* ring.wav in Resources */ = {isa = PBXBuildFile; fileRef = 2237D4081084D7A9001383EE /* ring.wav */; };
63CD4B4F1A5AAC8C00B84282 /* DTAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63CD4B4E1A5AAC8C00B84282 /* DTAlertView.m */; };
63D2680F1B174A5E00A2CC11 /* numpad_one_voicemail_default.png in Resources */ = {isa = PBXBuildFile; fileRef = 63D2680D1B174A5E00A2CC11 /* numpad_one_voicemail_default.png */; };
@ -1094,6 +1099,15 @@
639CEB0A1A1DF4FA004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UIChatCell.xib; sourceTree = "<group>"; };
639CEB0C1A1DF528004DE38F /* fr */ = {isa = PBXFileReference; fileEncoding = 2483028224; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/UICallCell.strings; sourceTree = "<group>"; };
639CEB0D1A1DF52C004DE38F /* ru */ = {isa = PBXFileReference; fileEncoding = 2483028224; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/UICallCell.strings; sourceTree = "<group>"; };
63B81A031B57DA33009604A6 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = "<group>"; };
63B81A041B57DA33009604A6 /* TPKeyboardAvoidingCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPKeyboardAvoidingCollectionView.h; sourceTree = "<group>"; };
63B81A051B57DA33009604A6 /* TPKeyboardAvoidingCollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPKeyboardAvoidingCollectionView.m; sourceTree = "<group>"; };
63B81A061B57DA33009604A6 /* TPKeyboardAvoidingScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPKeyboardAvoidingScrollView.h; sourceTree = "<group>"; };
63B81A071B57DA33009604A6 /* TPKeyboardAvoidingScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPKeyboardAvoidingScrollView.m; sourceTree = "<group>"; };
63B81A081B57DA33009604A6 /* TPKeyboardAvoidingTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPKeyboardAvoidingTableView.h; sourceTree = "<group>"; };
63B81A091B57DA33009604A6 /* TPKeyboardAvoidingTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPKeyboardAvoidingTableView.m; sourceTree = "<group>"; };
63B81A0A1B57DA33009604A6 /* UIScrollView+TPKeyboardAvoidingAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+TPKeyboardAvoidingAdditions.h"; sourceTree = "<group>"; };
63B81A0B1B57DA33009604A6 /* UIScrollView+TPKeyboardAvoidingAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+TPKeyboardAvoidingAdditions.m"; sourceTree = "<group>"; };
63CD4B4D1A5AAC8C00B84282 /* DTAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTAlertView.h; sourceTree = "<group>"; };
63CD4B4E1A5AAC8C00B84282 /* DTAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTAlertView.m; sourceTree = "<group>"; };
63D2680D1B174A5E00A2CC11 /* numpad_one_voicemail_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = numpad_one_voicemail_default.png; path = Resources/numpad_one_voicemail_default.png; sourceTree = "<group>"; };
@ -2405,6 +2419,23 @@
path = TestsLiblinphone;
sourceTree = "<group>";
};
63B81A021B57DA33009604A6 /* TPKeyboardAvoiding */ = {
isa = PBXGroup;
children = (
63B81A031B57DA33009604A6 /* LICENSE.txt */,
63B81A041B57DA33009604A6 /* TPKeyboardAvoidingCollectionView.h */,
63B81A051B57DA33009604A6 /* TPKeyboardAvoidingCollectionView.m */,
63B81A061B57DA33009604A6 /* TPKeyboardAvoidingScrollView.h */,
63B81A071B57DA33009604A6 /* TPKeyboardAvoidingScrollView.m */,
63B81A081B57DA33009604A6 /* TPKeyboardAvoidingTableView.h */,
63B81A091B57DA33009604A6 /* TPKeyboardAvoidingTableView.m */,
63B81A0A1B57DA33009604A6 /* UIScrollView+TPKeyboardAvoidingAdditions.h */,
63B81A0B1B57DA33009604A6 /* UIScrollView+TPKeyboardAvoidingAdditions.m */,
);
name = TPKeyboardAvoiding;
path = Utils/TPKeyboardAvoiding;
sourceTree = "<group>";
};
D326483415887D4400930C67 /* Utils */ = {
isa = PBXGroup;
children = (
@ -2417,6 +2448,7 @@
D32B9DFB15A2F131000B6DEC /* FastAddressBook.m */,
6371579F1B283FE200C91677 /* FileTransferDelegate.h */,
637157A01B283FE200C91677 /* FileTransferDelegate.m */,
63B81A021B57DA33009604A6 /* TPKeyboardAvoiding */,
D3ED40141602172200BF332B /* GrowingTextView */,
D3807FC715C2894A005BE9BC /* InAppSettingsKit */,
D3B90E1115C2CB5700F64F8C /* NinePatch.xcodeproj */,
@ -3735,6 +3767,7 @@
D339890215C6DD1600CAF1E4 /* video_on_over_landscape~ipad.png in Resources */,
D339890615C6E16F00CAF1E4 /* dialer_alt_back_default_landscape~ipad.png in Resources */,
D339890815C6E16F00CAF1E4 /* dialer_alt_back_over_landscape~ipad.png in Resources */,
63B81A0C1B57DA33009604A6 /* LICENSE.txt in Resources */,
D30BBD1815D402A7000F93DD /* contact_ok_disabled.png in Resources */,
D3804E6015D92A57008072A5 /* msg.caf in Resources */,
D3804E6215D92A57008072A5 /* msg.wav in Resources */,
@ -3948,6 +3981,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
63B81A0F1B57DA33009604A6 /* TPKeyboardAvoidingTableView.m in Sources */,
1D60589B0D05DD56006BFB54 /* main.m in Sources */,
1D3623260D0F684500981E51 /* LinphoneAppDelegate.m in Sources */,
22F2508E107141E100AC9B3F /* DialerViewController.m in Sources */,
@ -3984,10 +4018,13 @@
D35E7581159328EB0066B1C1 /* UIAddressTextField.m in Sources */,
D35E7597159460580066B1C1 /* ChatViewController.m in Sources */,
D35E759F159460B70066B1C1 /* SettingsViewController.m in Sources */,
63B81A101B57DA33009604A6 /* UIScrollView+TPKeyboardAvoidingAdditions.m in Sources */,
F03CA84318C72F1A0008889D /* UITextViewNoDefine.m in Sources */,
63B81A0D1B57DA33009604A6 /* TPKeyboardAvoidingCollectionView.m in Sources */,
D37DC6C11594AE1800B2A5EB /* LinphoneCoreSettingsStore.m in Sources */,
63CD4B4F1A5AAC8C00B84282 /* DTAlertView.m in Sources */,
D3EA53FD159850E80037DC6B /* LinphoneManager.m in Sources */,
63B81A0E1B57DA33009604A6 /* TPKeyboardAvoidingScrollView.m in Sources */,
D3EA540D1598528B0037DC6B /* ChatTableViewController.m in Sources */,
D3EA5411159853750037DC6B /* UIChatCell.m in Sources */,
D3F26BF115986B73005F9CAB /* IncomingCallViewController.m in Sources */,