1. Introduction
Material Components (MDC) help developers implement Material Design. Created by a team of engineers and UX designers at Google, MDC features dozens of beautiful and functional UI components and is available for Android, iOS, web and Flutter.material.io/develop |
What are Material Design and Material Components for iOS?
Material Design is a system for building bold and beautiful digital products. By uniting style, branding, interaction, and motion under a consistent set of principles and components, product teams can realize their greatest design potential.
Material Components for iOS (MDC iOS) unites design and engineering with a library of components for creating consistency across apps and websites. As the Material Design system evolves, these components are updated to ensure consistent pixel-perfect implementation and adherence to Google's front-end development standards. MDC is also available for the Android, web, and Flutter.
In this codelab, you'll build a login page using several MDC iOS components.
What you'll build
This codelab is the first of 4 codelabs that will guide you through building an app called Shrine, an e-commerce website that sells clothing and home goods. It will demonstrate how you can customize components to reflect any brand or style using MDC-iOS.
In this codelab, you'll build a login page for Shrine that contains:
- Two text fields, one for entering a username and the other for a password
- Two buttons, one for "Cancel" and the other for "Next"
- The name of the app (Shrine)
- An image of Shrine's logo
MDC iOS components in this codelab
- Text field
- Button
What you'll need
- Xcode
- The sample code
- Basic knowledge of Xcode, the iOS SDK and Objective-C
How would you rate your level of experience building iOS apps?
2. Set up your development environment
Download the starter codelab app
The starter app is located within the material-components-ios-codelabs-master/MDC-101/ObjectiveC/Starter
directory. Be sure to cd
into that directory before beginning.
...or clone it from GitHub
To clone this codelab from GitHub, run the following commands:
git clone https://github.com/material-components/material-components-ios-codelabs cd material-components-ios-codelabs/MDC-101/ObjectiveC/Starter/Shrine
Run the starter app
1. In Xcode open the workspace "Shrine.xcworkspace". If you see the "Welcome to Xcode" window, click "Open another project...", navigate to the file and click open. | ||
OR: Go to File > Open... and navigate to "Shrine.xcworkspace" and click "Open". | ||
OR: At the terminal enter: | ||
2. Run the app by pressing the play button at the top of the window.Note: Screenshots are generated from building on an iPhone 6s. |
Success! The starter code for Shrine's login screen should be running in your simulator. You should see the name "Shrine" and the Shrine logo just below it.
3. Add text fields
To begin, we'll add two text fields to our login page, where a user will be able to enter their username and password. We'll use the MDC Text Field component, which displays a floating label by default.
Add the required header
In LoginViewController.m
, add the following header:
//TODO: Add MaterialTextFields #import
#import <MaterialComponents/MaterialTextFields.h>
Add for text field properties
In LoginViewController.m
, add the following properties underneath the existing @property(nonatomic) UIImageView *logoImageView in @interface:
// Text Field Properties
//TODO: Add Text Field Properties
@property(nonatomic) MDCTextField *usernameTextField;
@property(nonatomic) MDCTextField *passwordTextField;
You'll also need a Text Input Controller for each text field.
@property(nonatomic) MDCTextInputControllerOutlined *usernameTextFieldController;
@property(nonatomic) MDCTextInputControllerOutlined *passwordTextFieldController;
Initialize the text fields and add them to the view
In LoginViewController.m
, add the following code underneath the existing logoImageView initialization in the viewDidLoad:
method.
// Text Field Init
//TODO: Instantiate Text Fields
self.usernameTextField = [[MDCTextField alloc] initWithFrame:CGRectZero];
self.usernameTextField.translatesAutoresizingMaskIntoConstraints = NO;
self.usernameTextField.delegate = self;
self.usernameTextField.clearButtonMode = UITextFieldViewModeUnlessEditing;
self.usernameTextField.backgroundColor = self.scrollView.backgroundColor;
[self.scrollView addSubview:self.usernameTextField];
Now initialize and associate the Text Input Controller for Username Text Field.
self.usernameTextFieldController =
[[MDCTextInputControllerOutlined alloc] initWithTextInput:self.usernameTextField];
self.usernameTextFieldController.placeholderText = @"Username";
Repeat the process for the password text field.
self.passwordTextField = [[MDCTextField alloc] initWithFrame:CGRectZero];
self.passwordTextField.translatesAutoresizingMaskIntoConstraints = NO;
self.passwordTextField.delegate = self;
self.passwordTextField.clearButtonMode = UITextFieldViewModeUnlessEditing;
self.passwordTextField.secureTextEntry = YES;
self.passwordTextField.backgroundColor = self.scrollView.backgroundColor;
[self.scrollView addSubview:self.passwordTextField];
self.passwordTextFieldController =
[[MDCTextInputControllerOutlined alloc] initWithTextInput:self.passwordTextField];
self.passwordTextFieldController.placeholderText = @"Password";
Position the text fields in the layout
To position the Text Fields, add this code to LoginViewController.m
. underneath logoImageView's constraints:
// Text Field Constraints
//TODO: Add Text Field Constraints
NSLayoutConstraint *usernameTopConstraint =
[NSLayoutConstraint constraintWithItem:self.usernameTextField
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.titleLabel
attribute:NSLayoutAttributeBottom
multiplier:1
constant:22];
[constraints addObject:usernameTopConstraint];
NSLayoutConstraint *centerUsernameConstraint =
[NSLayoutConstraint constraintWithItem:self.usernameTextField
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView
attribute:NSLayoutAttributeCenterX
multiplier:1 constant:0];
[constraints addObject:centerUsernameConstraint];
NSArray <NSLayoutConstraint *> *horizontalUsernameConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[username]-|"
options:0
metrics:nil
views:@{ @"username" : self.usernameTextField }];
[constraints addObjectsFromArray:horizontalUsernameConstraints];
NSLayoutConstraint *passwordTopConstraint =
[NSLayoutConstraint constraintWithItem:self.passwordTextField
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.usernameTextField
attribute:NSLayoutAttributeBottom
multiplier:1
constant:8];
[constraints addObject:passwordTopConstraint];
NSLayoutConstraint *centerPasswordConstraint =
[NSLayoutConstraint constraintWithItem:self.passwordTextField
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView
attribute:NSLayoutAttributeCenterX
multiplier:1 constant:0];
[constraints addObject:centerPasswordConstraint];
NSArray <NSLayoutConstraint *> *horizontalPasswordConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[password]-|"
options:0
metrics:nil
views:@{ @"password" : self.passwordTextField }];
[constraints addObjectsFromArray:horizontalPasswordConstraints];
Check for a minimum password length
Text fields can indicate if the field input is valid or if it contains an error.
You should:
- Require the Password text field to have a minimum length of
8
.
Find the UITextFieldDelegate
and add the following implementation of textFieldShouldReturn:
//TODO: Add Text Field Validation
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
// Text Field Validation
if (textField == (UITextField *)self.passwordTextField) {
if (self.passwordTextField.text.length < 8) {
[self.passwordTextFieldController setErrorText:@"Password is too short" errorAccessibilityValue:nil];
} else {
[self.passwordTextFieldController setErrorText:nil errorAccessibilityValue:nil];
}
}
return NO;
}
Build and run
The interface should now show two text fields for Username and Password! Check out the floating label animation when you tap on a text field:
4. Add buttons
Next, we'll add two buttons to our login page: "Cancel" and "Next." We'll use the MDC Button component to finish building our interface.
Add the required header
In LoginViewController.m
, add the following header:
//TODO: Add MaterialButtons #import
#import <MaterialComponents/MaterialButtons.h>
Create properties for the buttons
In LoginViewController.m
, add the following properties to the @interface, underneath the text field properties created earlier:
// Button Properties
//TODO: Add Button Properties
@property(nonatomic) MDCButton *cancelButton;
@property(nonatomic) MDCButton *nextButton;
Initialize the buttons and add them to the view
In LoginViewController.m
, add the following code underneath the the text fields in the viewDidLoad:
method:
// Button Init
//TODO: Instantiate Buttons
self.cancelButton = [[MDCButton alloc] init];
self.cancelButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.cancelButton setTitle:@"CANCEL" forState:UIControlStateNormal];
[self.cancelButton addTarget:self
action:@selector(didTapCancel:)
forControlEvents:UIControlEventTouchUpInside];
[self.scrollView addSubview:self.cancelButton];
self.nextButton = [[MDCButton alloc] initWithFrame:CGRectZero];
self.nextButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.nextButton setTitle:@"NEXT" forState:UIControlStateNormal];
[self.nextButton addTarget:self
action:@selector(didTapNext:)
forControlEvents:UIControlEventTouchUpInside];
[self.scrollView addSubview:self.nextButton];
Add layout constraints to position the buttons
To position the Text Fields, add code to viewDidLoad:
underneath the text field constraints:
// Button Constraints
//TODO: Add Button Constraints
NSLayoutConstraint *cancelTopConstraint =
[NSLayoutConstraint constraintWithItem:self.cancelButton
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.passwordTextField
attribute:NSLayoutAttributeBottom
multiplier:1
constant:8];
[constraints addObject:cancelTopConstraint];
NSLayoutConstraint *centerCancelConstraint =
[NSLayoutConstraint constraintWithItem:self.cancelButton
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView
attribute:NSLayoutAttributeCenterX
multiplier:1 constant:0];
[constraints addObject:centerCancelConstraint];
NSLayoutConstraint *centerButtonsConstraint =
[NSLayoutConstraint constraintWithItem:self.cancelButton
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.nextButton
attribute:NSLayoutAttributeCenterY
multiplier:1 constant:0];
[constraints addObject:centerButtonsConstraint];
NSArray <NSLayoutConstraint *> *horizontalButtonConstraints =
[NSLayoutConstraint constraintsWithVisualFormat:@"H:[cancel]-[next]-|"
options:0
metrics:nil
views:@{ @"cancel" : self.cancelButton, @"next" : self.nextButton }];
[constraints addObjectsFromArray:horizontalButtonConstraints];
NSLayoutConstraint *scrollContentBottomConstraint =
[NSLayoutConstraint constraintWithItem:self.nextButton
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView.contentLayoutGuide
attribute:NSLayoutAttributeBottomMargin
multiplier:1
constant:-20];
[constraints addObject:scrollContentBottomConstraint];
Add button actions
Add the button action handlers.
#pragma mark - Action Handling
// Button Action Handlers
//TODO: Add Action Handlers
- (void)didTapNext:(id)sender {
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (void)didTapCancel:(id)sender {
[self dismissViewControllerAnimated:YES completion:NULL];
}
Build and run
You should now see a page that contains these two buttons. Try it out
5. All done
Material Components for iOS has helped you create a beautiful login page that conforms to the Material Design guidelines, which looks and behaves consistently across all devices.
Next steps
Text Field and Button are two core components in MDC iOS, but there are many more! You can explore the rest of the components in MDC iOS.
Alternatively, head over to MDC-102: Material Design Structure and Layout to learn about AppBar and Card Collection. Thanks for trying Material Components. We hope you enjoyed this codelab!