MDC-104 iOS: Material Advanced Components (Objective-C)

1. Introduction

logo_components_color_2x_web_96dp.png

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

In codelab MDC-103, you customized the color, elevation, typography, and shape of Material Components (MDC) to style your app.

A component in the Material Design system performs a set of predefined tasks and has certain characteristics, like a button. However, a button is more than just a way for a user to perform an action, it's also a visual expression of shape, size, and color that lets the user know that it's interactive, and that something will happen upon touch or click.

The Material Design guidelines describe components from a designer's point of view. They describe a wide range of basic functions available across platforms, as well as the anatomic elements that make up each component. For instance, a backdrop contains a back layer and its content, the front layer and its content, motion rules, and display options. Each of these components can be customized for each app's needs, use cases, and content. These pieces are, for the most part, traditional views, controls, and functions from your platform's SDK.

While the Material Design guidelines name many components, not all of them are good candidates for reusable code and therefore aren't found in MDC. You can create these experiences yourself to achieve a customized style for your app, all using traditional code.

What you'll build

In this codelab, you'll add a backdrop to Shrine. It will filter the products shown in the asymmetrical grid by category. You'll be using:

  • View Controller Containment
  • Shape
  • Notifications

899cafdcfb0488d6.png fdc007dbb3355c6c.png

How would you rate your level of experience building iOS apps?

Novice Intermediate Proficient

2. Set up your development environment

Download the starter codelab app

The starter app is located within the material-components-ios-codelabs-master/MDC-104/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-104/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 the file and click "Open".

OR: At the terminal enter:
open Shrine.xcworkspace

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! You should see Shrine's main interface running in the simulator. c64189b9bf6829ff.png

3. Add the backdrop menu

A backdrop is the furthest back surface of an app, appearing behind all other content and components. It's composed of two surfaces: a back layer (which displays actions and filters) and a front layer (which displays content). You can use a backdrop to display interactive information and actions, such as navigation or content filters.

Change the root view controller to BackdropViewController

In AppDelegate.m, change the root view controller in application:didFinishLaunchingWithOptions: from HomeViewController to BackdropViewController.

  //TODO: Change the root view controller to BackdropViewController
  UIViewController *viewController =
      [storyboard instantiateViewControllerWithIdentifier:@"BackdropViewController"];

This controller has already been populated with a list of categories we will use to filter our products.

66e5609c8a6401ff.png

Well done! You've added a beautiful backdrop to Shrine's UI. Next, we'll bring the products back on top of our Backdrop..

Now we've set up our backdrop. Let's bring back the content that we concealed earlier.

4. Embed the Products View Controller into the Backdrop View Controller

Before we made any changes to Shrine in this codelab, the primary product content was located on the furthest back surface. By adding a backdrop, this content is now more emphasized because it appears in front of that backdrop.

Add a new layer

Now we'll add a front layer to hold all of the product content. Add the following to the end of viewDidLoad: in BackdropViewController.m.

//TODO: Instantiate and embed the catalog view controller in the BackdropViewController
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *viewController =
    [storyboard instantiateViewControllerWithIdentifier:@"HomeViewController"];
[self insertController:viewController];

Let's style the front layer with a notch in the upper left corner. Material Design refers to this type of customization as a shape. Material surfaces can be displayed in different shapes. Shapes add emphasis and style to surfaces and can be used to express branding. Material shapes can have curved or angled corners and edges, and any number of sides. They can be symmetrical or irregular.

Add a shape scheme to your application

In ApplicationScheme.m, modify the following lines:

// Instantiate a MDCShapeScheme object and modify it to our chosen shapes
_shapeScheme = [[MDCShapeScheme alloc] initWithDefaults:MDCShapeSchemeDefaultsMaterial201809];
_shapeScheme.largeComponentShape =
    [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyCut andSize:20];

Add a shape and apply it to the backdrop

Just above where we inserted the HomeViewController let's change the containerView to a ShapedShadowedView from a standard UIView in the viewDidLoad: method in BackdropViewController.m. Then we apply the applications shape scheme on the ShapedShadowedView, specifically the top left corner of the backdrop.

Remove

//TODO: Change the container view into a ShapedShadowedView and apply the shape.
self.containerView = [[UIView alloc] initWithFrame:CGRectZero];

and replace it with

//TODO: Change the container view into a ShapedShadowedView and apply the shape.
self.containerView = [[ShapedShadowedView alloc] initWithFrame:CGRectZero];
MDCRectangleShapeGenerator *shapeGenerator = [[MDCRectangleShapeGenerator alloc] init];
shapeGenerator.topLeftCorner =
    [ApplicationScheme sharedInstance].shapeScheme.largeComponentShape.topLeftCorner;
((ShapedShadowedView *)self.containerView).shapeGenerator = shapeGenerator;

Build and run:

5a8c37ee53dc4bbb.png

Almost there, but since both of the view controllers have an AppBar, we are seeing both of them. Let remove the AppBar from embedded HomeViewController.

Remove the following lines from viewDidLoad: in HomeViewController.m.

// AppBar Init
//TODO: Remove the following seven lines to remove the App Bar
self.appBarViewController = [[MDCAppBarViewController alloc] init];
[self addChildViewController:self.appBarViewController];
[self.view addSubview:self.appBarViewController.view];
[self.appBarViewController didMoveToParentViewController:self];

// Set the tracking scroll view.
self.appBarViewController.headerView.trackingScrollView = self.collectionView;

Build and run the simulator and you'll see the proper interface, complete with the top left corner cut out of our product interface.

87368e07c731d3ff.png

5. Add filtering

The buttons in our bottom layer are meant to be used to filter the displayed products. Let's reload our displayed products if the filter is changed.

Add a Notification observer to HomeViewController.m. Add the following to the end of viewDidLoad:

  //TODO: Register for the catalog changed notification
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(respondToCatalogNotification:)
                                               name:CatalogFilterDidChangeNotification
                                             object:nil];

Add a respondToCatalogNotification at the end of HomeViewController.m.

//TODO: Add notification Handler
- (void)respondToCatalogNotification:(NSNotification *)notification {
  [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
}

When we get a button tap on our filters, let's update our catalog. Add the following to BackdropViewController.m in the didTapCategory: function.

//TODO: Set the catalog filter based on the button pressed
[Catalog productCatalog].categoryFilter = filter;

Build and run. Press the settings button to toggle the display of the Backdrop:

658801d492949aa6.png

See the filter in action by pressing the "Clothing" button:

ca1d31c9430248fe.png

6. Recap

Over the course of these four codelabs, you've seen how to use Material Components to build unique, elegant user experiences that express a brand's personality and style.

Next steps

This codelab, MDC-104, completes this sequence of codelabs. You can explore more components and subsystems in the MDC iOS library.

I was able to complete this codelab with a reasonable amount of time and effort

Strongly agree Agree Neutral Disagree Strongly disagree

I would like to continue using Material Components in the future

Strongly agree Agree Neutral Disagree Strongly disagree