blob: 12298351d45b949166f59e5df54ed1dd4e77954c [file] [log] [blame] [edit]
// Copyright 2016-present the Material Components for iOS authors. 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 "MaterialTextFields.h"
@interface TextFieldManualLayoutLegacyExample : UIViewController <UITextFieldDelegate>
@property(nonatomic) MDCTextInputControllerLegacyDefault *nameController;
@property(nonatomic) MDCTextInputControllerLegacyDefault *phoneController;
@end
@implementation TextFieldManualLayoutLegacyExample
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
MDCTextField *textFieldName = [[MDCTextField alloc] init];
[self.view addSubview:textFieldName];
textFieldName.delegate = self;
textFieldName.clearButtonMode = UITextFieldViewModeUnlessEditing;
self.nameController =
[[MDCTextInputControllerLegacyDefault alloc] initWithTextInput:textFieldName];
textFieldName.frame = CGRectMake(10, 40, CGRectGetWidth(self.view.bounds) - 20, 0);
self.nameController.placeholderText = @"Full Name";
MDCTextField *textFieldPhone = [[MDCTextField alloc] init];
[self.view addSubview:textFieldPhone];
textFieldPhone.delegate = self;
textFieldPhone.clearButtonMode = UITextFieldViewModeUnlessEditing;
self.phoneController =
[[MDCTextInputControllerLegacyDefault alloc] initWithTextInput:textFieldPhone];
textFieldPhone.frame = CGRectMake(10, CGRectGetMaxY(self.nameController.textInput.frame) + 20,
CGRectGetWidth(self.view.bounds) - 20, 0);
self.phoneController.placeholderText = @"Phone Number";
self.phoneController.helperText = @"XXX-XXX-XXXX";
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.nameController.textInput sizeToFit];
[self.phoneController.textInput sizeToFit];
self.phoneController.textInput.frame = CGRectMake(
10, CGRectGetMaxY(self.nameController.textInput.frame) + 20,
CGRectGetWidth(self.view.bounds) - 20, CGRectGetHeight(self.phoneController.textInput.frame));
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
if (textField == (UITextField *)self.phoneController.textInput &&
![self isValidPhoneNumber:textField.text partially:NO]) {
[self.phoneController setErrorText:@"Invalid Phone Number" errorAccessibilityValue:nil];
}
return NO;
}
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
NSString *finishedString = [textField.text stringByReplacingCharactersInRange:range
withString:string];
if (textField == (UITextField *)self.nameController.textInput) {
if ([finishedString rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].length &&
![self.nameController.errorText isEqualToString:@"You cannot enter numbers"]) {
// The entered text contains numbers and we have not set an error
[self.nameController setErrorText:@"You cannot enter numbers" errorAccessibilityValue:nil];
// Since we are doing manual layout, we need to react to the expansion of the input that will
// come from setting an error.
[self.view setNeedsLayout];
} else if (self.nameController.errorText != nil) {
// There should be no error but error text is being shown.
[self.nameController setErrorText:nil errorAccessibilityValue:nil];
// Since we are doing manual layout, we need to react to the contraction of the input that
// will come from setting an error.
[self.view setNeedsLayout];
}
}
if (textField == (UITextField *)self.phoneController.textInput) {
if (![self isValidPhoneNumber:finishedString partially:YES] &&
![self.phoneController.errorText isEqualToString:@"Invalid phone number"]) {
// The entered text is not valid and we have not set an error
[self.phoneController setErrorText:@"Invalid phone number" errorAccessibilityValue:nil];
// The text field has helper text that already expanded the frame so we don't need to call
// setNeedsLayout.
} else if (self.phoneController.errorText != nil) {
[self.phoneController setErrorText:nil errorAccessibilityValue:nil];
// The text field has helper text and cannot contract the frame so we don't need to call
// setNeedsLayout.
}
}
return YES;
}
#pragma mark - Phone Number Validation
- (BOOL)isValidPhoneNumber:(NSString *)inputString partially:(BOOL)isPartialCheck {
// In real life there would be much more robust validation that takes locale into account, checks
// against invalid phone numbers (like those that begin with 0), and perhaps even auto-inserts the
// hyphens so the user doesn't have to.
if (inputString.length == 0) {
return YES;
}
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789-"];
characterSet = [characterSet invertedSet];
BOOL isValid = ![inputString rangeOfCharacterFromSet:characterSet].length;
if (!isPartialCheck) {
isValid = isValid && inputString.length == 12;
} else {
isValid = isValid && inputString.length <= 12;
}
return isValid;
}
@end
@implementation TextFieldManualLayoutLegacyExample (CatalogByConvention)
+ (NSDictionary *)catalogMetadata {
return @{
@"breadcrumbs" : @[ @"Text Field", @"[Legacy] Manual Layout" ],
@"primaryDemo" : @NO,
@"presentable" : @NO,
};
}
@end