Skip to content

Commit

Permalink
[TextFields] Add some important protocols (material-components#8493)
Browse files Browse the repository at this point in the history
This PR adds the MDCContainedInputView protocol and the MDCContainedInputViewStyle protocol. MDCContainedInputView is the protocol that all the contained input views conform to. It has properties for all of the things that contained input views should have in common. This includes a style property, which is an object conforming to MDCContainedInputViewStyle. The main job of the style object is to apply various visual decorations on the textfield, like filled backgrounds for filled textfields or outlines for outlined textfields. The style objects also vend the vertical positioning reference objects, which are the things that determine the vertical distances between the textfield's subviews. This makes sense when you consider that the differences in those distances depend on the style of the textfield, i.e. whether it's filled or outlined.

Related to #6942.
  • Loading branch information
andrewoverton authored Sep 26, 2019
1 parent 55a857f commit 85bd705
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 6 deletions.
18 changes: 16 additions & 2 deletions components/TextFields/src/ContainedInputView/MDCBaseTextField.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
#import "private/MDCContainedInputViewColorViewModel.h"
#import "private/MDCContainedInputViewLabelAnimation.h"
#import "private/MDCContainedInputViewLabelState.h"
#import "private/MDCContainedInputViewStyleBase.h"
#import "private/MDCContainedInputViewVerticalPositioningGuideBase.h"

@interface MDCBaseTextField ()
@interface MDCBaseTextField () <MDCContainedInputView>

@property(strong, nonatomic) UILabel *label;
@property(strong, nonatomic) MDCBaseTextFieldLayout *layout;
Expand All @@ -43,6 +44,7 @@ @interface MDCBaseTextField ()
@end

@implementation MDCBaseTextField
@synthesize containerStyle = _containerStyle;

#pragma mark Object Lifecycle

Expand Down Expand Up @@ -74,6 +76,7 @@ - (void)initializeProperties {
self.labelBehavior = MDCTextControlLabelBehaviorFloats;
self.layoutDirection = self.mdf_effectiveUserInterfaceLayoutDirection;
self.labelState = [self determineCurrentLabelState];
self.containerStyle = [[MDCContainedInputViewStyleBase alloc] init];
self.colorViewModels = [[NSMutableDictionary alloc] init];
}

Expand Down Expand Up @@ -195,7 +198,7 @@ - (MDCBaseTextFieldLayout *)calculateLayoutWithTextFieldSize:(CGSize)textFieldSi
}

- (id<MDCContainerStyleVerticalPositioningReference>)createPositioningReference {
return [[MDCContainedInputViewVerticalPositioningGuideBase alloc] init];
return [self.containerStyle positioningReference];
}

- (CGFloat)clearButtonSideLengthWithTextFieldSize:(CGSize)textFieldSize {
Expand Down Expand Up @@ -339,6 +342,17 @@ - (void)setLayoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection {
[self setNeedsLayout];
}

#pragma mark MDCContainedInputView accessors

- (void)setContainerStyle:(id<MDCContainedInputViewStyle>)containerStyle {
id<MDCContainedInputViewStyle> oldStyle = _containerStyle;
if (oldStyle) {
[oldStyle removeStyleFrom:self];
}
_containerStyle = containerStyle;
[_containerStyle applyStyleToContainedInputView:self];
}

#pragma mark UITextField Layout Overrides

// The implementations for this method and the method below deserve some context! Unfortunately,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright 2019-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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#import "MDCContainedInputViewColorViewModel.h"
#import "MDCContainedInputViewLabelAnimation.h"
#import "MDCContainedInputViewLabelState.h"
#import "MDCContainerStyleVerticalPositioningReference.h"
#import "MDCTextControlLabelBehavior.h"
#import "MDCTextControlState.h"

static const CGFloat kMDCContainedInputViewDefaultAnimationDuration = (CGFloat)0.15;

@protocol MDCContainedInputViewStyle;

@protocol MDCContainedInputView <NSObject>

/**
This object represents the style of the text control, i.e. the thing that makes it filled or
outlined. See the documentation for MDCContainedInputViewStyle for more information on its
responsibilities.
*/
@property(nonatomic, strong, nonnull) id<MDCContainedInputViewStyle> containerStyle;

/**
Describes the current @c MDCtextControlState of the view. This value is affected by things like
UIControlState, as well as whether or not it's editing.
*/
@property(nonatomic, assign, readonly) MDCTextControlState textControlState;

/**
Describes the current MDCContainedInputViewLabelState of the contained input view. This
value is affected by things like the view's @c textControlState, its @c labelBehavior, and the
text of the floating label.
*/
@property(nonatomic, assign, readonly) MDCContainedInputViewLabelState labelState;

/**
Describes the behavior of the label when the view begins editing.
*/
@property(nonatomic, assign, readonly) MDCTextControlLabelBehavior labelBehavior;

/**
The @c label is a label that occupies the text area in a resting state with no text and that either
floats above the text or disappears in an editing state. It is distinct from a placeholder.
*/
@property(strong, nonatomic, readonly, nonnull) UILabel *label;

/**
The @c normalFont is the contained input view's primary font. The text has this font. The label
also has this font when it isn't floating.
*/
@property(strong, nonatomic, readonly, nonnull) UIFont *normalFont;

/**
The @c floatingFont is the font of the label when it's floating.
*/
@property(strong, nonatomic, readonly, nonnull) UIFont *floatingFont;

/**
This method returns a MDCContainedInputViewColorViewModel for a given MDCTextControlState.
*/
- (nonnull MDCContainedInputViewColorViewModel *)containedInputViewColorViewModelForState:
(MDCTextControlState)textControlState;

/**
This method sets a MDCContainedInputViewColorViewModel for a given MDCTextControlState.
*/
- (void)setContainedInputViewColorViewModel:
(nonnull MDCContainedInputViewColorViewModel *)containedInputViewColorViewModel
forState:(MDCTextControlState)textFieldState;

@end

@protocol MDCContainedInputViewStyle <NSObject>

/**
This method allows objects conforming to MDCContainedInputViewStyle to apply themselves to objects
conforming to MDCContainedInputView.
*/
- (void)applyStyleToContainedInputView:(nonnull id<MDCContainedInputView>)containedInputView;
/**
This method allows objects conforming to MDCContainedInputViewStyle to remove the styling
previously applied to objects conforming to MDCContainedInputView.
*/
- (void)removeStyleFrom:(nonnull id<MDCContainedInputView>)containedInputView;

/**
The method returns a UIFont for the floating label based on the @c normalFont of the
view.
*/
- (UIFont *_Nonnull)floatingFontWithNormalFont:(nonnull UIFont *)font;

/**
This method returns an object that tells the view where to position it's views
vertically.
*/
- (nonnull id<MDCContainerStyleVerticalPositioningReference>)positioningReference;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@

#import "MDCContainedInputViewLabelAnimation.h"

#import "MDCContainedInputView.h"
#import "MaterialAnimationTiming.h"

static const CGFloat kDefaultAnimationDuration = (CGFloat)0.15;

@implementation MDCContainedInputViewLabelAnimation

+ (void)layOutLabel:(nonnull UILabel *)label
Expand Down Expand Up @@ -47,7 +46,7 @@ + (void)layOutLabel:(nonnull UILabel *)label
CAMediaTimingFunction *timingFunction =
[CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionStandard];
[UIView mdc_animateWithTimingFunction:timingFunction
duration:kDefaultAnimationDuration
duration:kMDCContainedInputViewDefaultAnimationDuration
delay:0
options:0
animations:^{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2019-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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#import "MDCContainedInputView.h"

/**
A base implementation of MDCContainedInputViewStyle. This is only used for base text controls, i.e.
ones that are not filled or outlined.
*/
@interface MDCContainedInputViewStyleBase : NSObject <MDCContainedInputViewStyle>
@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2019-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 "MDCContainedInputViewStyleBase.h"

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

#import "MDCContainedInputView.h"
#import "MDCContainedInputViewVerticalPositioningGuideBase.h"

static const CGFloat kBaseFloatingLabelScaleFactor = 0.75;

@implementation MDCContainedInputViewStyleBase

- (UIFont *)floatingFontWithNormalFont:(UIFont *)font {
CGFloat scaleFactor = kBaseFloatingLabelScaleFactor;
CGFloat floatingFontSize = font.pointSize * scaleFactor;
return [font fontWithSize:floatingFontSize];
}

- (void)applyStyleToContainedInputView:(id<MDCContainedInputView>)inputView {
}

- (void)removeStyleFrom:(id<MDCContainedInputView>)containedInputView {
}

- (id<MDCContainerStyleVerticalPositioningReference>)positioningReference {
return [[MDCContainedInputViewVerticalPositioningGuideBase alloc] init];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@

@interface MDCBaseTextFieldTestsSnapshotTests : MDCSnapshotTestCase
@property(strong, nonatomic) MDCBaseTextField *textField;
@property(nonatomic, assign) BOOL areAnimationsEnabled;
@end

@implementation MDCBaseTextFieldTestsSnapshotTests

- (void)setUp {
[super setUp];

self.areAnimationsEnabled = UIView.areAnimationsEnabled;
[UIView setAnimationsEnabled:NO];
self.textField = [self createBaseTextFieldInKeyWindow];
// Uncomment below to recreate all the goldens (or add the following line to the specific
// test you wish to recreate the golden for).
Expand All @@ -40,6 +43,7 @@ - (void)tearDown {
[super tearDown];
[self.textField removeFromSuperview];
self.textField = nil;
[UIView setAnimationsEnabled:self.areAnimationsEnabled];
}

- (MDCBaseTextField *)createBaseTextFieldInKeyWindow {
Expand All @@ -53,7 +57,6 @@ - (MDCBaseTextField *)createBaseTextFieldInKeyWindow {
- (void)validateTextField:(MDCBaseTextField *)textField {
XCTestExpectation *expectation =
[[XCTestExpectation alloc] initWithDescription:@"textfield_validation_expectation"];

dispatch_after(
dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(kTextFieldValidationEstimatedAnimationDuration * NSEC_PER_SEC)),
Expand Down

0 comments on commit 85bd705

Please sign in to comment.