Merge branch 'release-candidate' into stable
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6fb9424..1b2240b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,82 @@
+# 66.0.0
+
+Shapes updated it's interface.
+ActionSheet improvements.
+List added a typography themer.
+
+## Breaking changes
+
+Shapes updated its API. See [#5247](https://github.com/material-components/material-components-ios/pull/5247) for details.
+
+## API changes
+
+### List+TypographyThemer
+
+**New extension.**
+
+## Component changes
+
+### ActionSheet
+
+* [Fix ink color for themer (#5287)](https://github.com/material-components/material-components-ios/commit/a411e7143dcc85157983b5a97b3385f607ad3832) (Cody Weaver)
+* [Match spec (#5291)](https://github.com/material-components/material-components-ios/commit/7ad817606a824335c09f553c85066312f5cb29b9) (Cody Weaver)
+* [Update MDCActionSheetHelperTest (#5248)](https://github.com/material-components/material-components-ios/commit/31a2aadeb62b704bb16c40b93708be51a07bbe16) (Cody Weaver)
+
+### BottomNavigation
+
+* [Fix example (#5242)](https://github.com/material-components/material-components-ios/commit/e0fef69db32a21ad88206e1614564653d6391e8d) (Cody Weaver)
+
+### BottomSheet
+
+* [[Shape]! Terminology updates to the Shape Scheme (#5247)](https://github.com/material-components/material-components-ios/commit/bfc674a631a0214a5b7182a629ab40121b6a25a0) (Yarden Eitan)
+
+### Buttons
+
+* [[Shape]! Terminology updates to the Shape Scheme (#5247)](https://github.com/material-components/material-components-ios/commit/bfc674a631a0214a5b7182a629ab40121b6a25a0) (Yarden Eitan)
+
+### Cards
+
+* [[Shape]! Terminology updates to the Shape Scheme (#5247)](https://github.com/material-components/material-components-ios/commit/bfc674a631a0214a5b7182a629ab40121b6a25a0) (Yarden Eitan)
+
+### Chips
+
+* [[Shape]! Terminology updates to the Shape Scheme (#5247)](https://github.com/material-components/material-components-ios/commit/bfc674a631a0214a5b7182a629ab40121b6a25a0) (Yarden Eitan)
+
+### Dialogs
+
+* [Add shadow elevation (#5296)](https://github.com/material-components/material-components-ios/commit/cba82b4d060f7dccef13d7513628ad22c0bf4afe) (Cody Weaver)
+* [Customize alert title icon (#5167)](https://github.com/material-components/material-components-ios/commit/dc184ba549a5eeaac727723189c147c24d4b74ca) (Galia Kaufman)
+* [Customize tint color of alert title icon (#5159)](https://github.com/material-components/material-components-ios/commit/d065e4536f4f19660149875ec3f014dd2947d31d) (Galia Kaufman)
+* [Customizing scrim color in presentation controller (#5283)](https://github.com/material-components/material-components-ios/commit/1137a62d92b8a983a7c9feea57a3f4a884134749) (Galia Kaufman)
+
+### FlexibleHeader
+
+* [Update MDCFlexibleHeaderView.m (#5259)](https://github.com/material-components/material-components-ios/commit/a1f6658af968f12d354a10aed19f7848abe30579) (Ali Rabbani)
+
+### List
+
+* [Add TypographyThemer to MDCSelfSizingStereoCell (#5298)](https://github.com/material-components/material-components-ios/commit/0fb7ec971299f8a8f0814a9186c16ddfee5edd2a) (Andrew Overton)
+
+### NavigationDrawer
+
+* [Fix iOS 9 bottom drawer dismissals (#5202)](https://github.com/material-components/material-components-ios/commit/d56a82e0e568a464c070fc36766d3a24f8d7840f) (Andrew Overton)
+* [Use CGRect accessor methods (#5244)](https://github.com/material-components/material-components-ios/commit/07981be315fb404a53abf81603dcdca324851e0b) (Andrew Overton)
+
+### Tabs
+
+* [[MDCTabBar] Remove dependence on a UIWindow for rendering/layout of MDCTabBa (#5285)](https://github.com/material-components/material-components-ios/commit/696e3768cdfaebeebc69378e8028d453867b2954) (Sam Duke)
+
+### TextFields
+
+* [Override System Initiated VoiceOver Message When Leaving Error State (#5251)](https://github.com/material-components/material-components-ios/commit/7672bcf7a61d48af4da9947efdbbe2d34d241b09) (Andrew Overton)
+
+### schemes/Shape
+
+* [[Shape]! Terminology updates to the Shape Scheme (#5247)](https://github.com/material-components/material-components-ios/commit/bfc674a631a0214a5b7182a629ab40121b6a25a0) (Yarden Eitan)
+* [[Shapes] Addition of a shape theming example to our dragons (#5239)](https://github.com/material-components/material-components-ios/commit/956761ed4d567ef1aaf29370bc2b5be11215128a) (Yarden Eitan)
+
+---
+
# 65.0.0
Bottom App Bar got a `floatingButtonVerticalOffset` property.
diff --git a/MaterialComponents.podspec b/MaterialComponents.podspec
index 7400b51..969acb1 100644
--- a/MaterialComponents.podspec
+++ b/MaterialComponents.podspec
@@ -2,7 +2,7 @@
Pod::Spec.new do |mdc|
mdc.name = "MaterialComponents"
- mdc.version = "65.0.0"
+ mdc.version = "66.0.0"
mdc.authors = "The Material Components authors."
mdc.summary = "A collection of stand-alone production-ready UI libraries focused on design details."
mdc.homepage = "https://github.com/material-components/material-components-ios"
@@ -755,6 +755,15 @@
end
end
+ mdc.subspec "List+TypographyThemer" do |extension|
+ extension.ios.deployment_target = '8.0'
+ extension.public_header_files = "components/#{extension.base_name.split('+')[0]}/src/#{extension.base_name.split('+')[1]}/*.h"
+ extension.source_files = "components/#{extension.base_name.split('+')[0]}/src/#{extension.base_name.split('+')[1]}/*.{h,m}"
+
+ extension.dependency "MaterialComponents/#{extension.base_name.split('+')[0]}"
+ extension.dependency "MaterialComponents/schemes/Typography"
+ end
+
# MaskedTransition
mdc.subspec "MaskedTransition" do |component|
diff --git a/MaterialComponentsAlpha.podspec b/MaterialComponentsAlpha.podspec
index d1748ad..fae808a 100644
--- a/MaterialComponentsAlpha.podspec
+++ b/MaterialComponentsAlpha.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |mdc|
mdc.name = "MaterialComponentsAlpha"
- mdc.version = "65.0.0"
+ mdc.version = "66.0.0"
mdc.authors = "The Material Components authors."
mdc.summary = "A collection of stand-alone alpha UI libraries that are not yet guaranteed to be ready for general production use. Use with caution."
mdc.homepage = "https://github.com/material-components/material-components-ios"
diff --git a/MaterialComponentsEarlGreyTests.podspec b/MaterialComponentsEarlGreyTests.podspec
index 093775e..abe384e 100644
--- a/MaterialComponentsEarlGreyTests.podspec
+++ b/MaterialComponentsEarlGreyTests.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "MaterialComponentsEarlGreyTests"
- s.version = "65.0.0"
+ s.version = "66.0.0"
s.authors = "The Material Components authors."
s.summary = "This spec is an aggregate of all the Material Components EarlGrey tests."
s.description = "This spec is made for use in the MDC Catalog."
diff --git a/MaterialComponentsExamples.podspec b/MaterialComponentsExamples.podspec
index cf0fca7..2ee2cab 100644
--- a/MaterialComponentsExamples.podspec
+++ b/MaterialComponentsExamples.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "MaterialComponentsExamples"
- s.version = "65.0.0"
+ s.version = "66.0.0"
s.authors = "The Material Components authors."
s.summary = "This spec is an aggregate of all the Material Components examples."
s.description = "This spec is made for use in the MDC Catalog. Used in conjunction with CatalogByConvention we create our Material Catalog."
diff --git a/VERSION b/VERSION
index 4acff0a..c0b1fa7 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-65.0.0
+66.0.0
diff --git a/catalog/MDCCatalog/Info.plist b/catalog/MDCCatalog/Info.plist
index 1210d07..f7ec207 100644
--- a/catalog/MDCCatalog/Info.plist
+++ b/catalog/MDCCatalog/Info.plist
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>65.0.0</string>
+ <string>66.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
diff --git a/catalog/MaterialCatalog/MaterialCatalog.podspec b/catalog/MaterialCatalog/MaterialCatalog.podspec
index 10ca897..f9ddb55 100644
--- a/catalog/MaterialCatalog/MaterialCatalog.podspec
+++ b/catalog/MaterialCatalog/MaterialCatalog.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "MaterialCatalog"
- s.version = "65.0.0"
+ s.version = "66.0.0"
s.summary = "Helper Objective-C classes for the MDC catalog."
s.description = "This spec is made for use in the MDC Catalog."
s.homepage = "https://github.com/material-components/material-components-ios"
diff --git a/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.m b/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.m
index 7cfe6e1..f9d2dae 100644
--- a/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.m
+++ b/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.m
@@ -16,7 +16,7 @@
static const CGFloat kHighAlpha = 0.87f;
static const CGFloat kMediumAlpha = 0.6f;
-static const CGFloat kInkAlpha = 16.f;
+static const CGFloat kInkAlpha = 0.16f;
@implementation MDCActionSheetColorThemer
diff --git a/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.m b/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.m
index 43a8677..9abc747 100644
--- a/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.m
+++ b/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.m
@@ -20,7 +20,7 @@
toActionSheetController:(MDCActionSheetController *)actionSheetController {
actionSheetController.titleFont = typographyScheme.subtitle1;
actionSheetController.messageFont = typographyScheme.body2;
- actionSheetController.actionFont = typographyScheme.body1;
+ actionSheetController.actionFont = typographyScheme.subtitle1;
}
@end
diff --git a/components/ActionSheet/tests/unit/MDCActionSheetThemeTest.m b/components/ActionSheet/tests/unit/MDCActionSheetThemeTest.m
index 487a5c6..460e069 100644
--- a/components/ActionSheet/tests/unit/MDCActionSheetThemeTest.m
+++ b/components/ActionSheet/tests/unit/MDCActionSheetThemeTest.m
@@ -22,7 +22,7 @@
static const CGFloat kHighAlpha = 0.87f;
static const CGFloat kMediumAlpha = 0.6f;
-static const CGFloat kInkAlpha = 16.f;
+static const CGFloat kInkAlpha = 0.16f;
@interface MDCActionSheetHeaderView (Testing)
@property(nonatomic, strong) UILabel *titleLabel;
@@ -54,10 +54,8 @@
self.colorScheme.onPrimaryColor = onSurface;
self.typographyScheme = [[MDCTypographyScheme alloc] init];
UIFont *subtitle = [UIFont systemFontOfSize:12.0 weight:UIFontWeightBold];
- UIFont *body1 = [UIFont systemFontOfSize:8.0 weight:UIFontWeightThin];
UIFont *body2 = [UIFont systemFontOfSize:10.0 weight:UIFontWeightLight];
self.typographyScheme.subtitle1 = subtitle;
- self.typographyScheme.body1 = body1;
self.typographyScheme.body2 = body2;
}
@@ -140,7 +138,7 @@
XCTAssertEqualObjects(self.actionSheet.header.messageLabel.font, self.typographyScheme.body2);
XCTAssertNotEqual(cells.count, 0U);
for (MDCActionSheetItemTableViewCell *cell in cells) {
- XCTAssertEqualObjects(cell.actionLabel.font, self.typographyScheme.body1);
+ XCTAssertEqualObjects(cell.actionLabel.font, self.typographyScheme.subtitle1);
}
}
diff --git a/components/Banner/.vars b/components/Banner/.vars
new file mode 100644
index 0000000..ed7f59c
--- /dev/null
+++ b/components/Banner/.vars
@@ -0,0 +1,3 @@
+component=Banner
+component_name=Banner
+short_description=Banner
diff --git a/components/Banner/README.md b/components/Banner/README.md
index c7c9073..d01dfcb 100644
--- a/components/Banner/README.md
+++ b/components/Banner/README.md
@@ -1,4 +1,8 @@
+<!-- This file was auto-generated using ./scripts/generate_readme Banner -->
+
# Banner
-The [Banner component](https://material.io/go/design-banner) is yet to be completed, please follow the [tracking issue](https://www.pivotaltracker.com/epic/show/3949126) for more information.
+[](https://github.com/material-components/material-components-ios/issues?q=is%3Aopen+is%3Aissue+label%3Atype%3ABug+label%3A%5BBanner%5D)
+A banner displays a prominent message and related optional actions.
+Note: this component is currently being actively developed and is not yet ready for general use.
diff --git a/components/Banner/docs/README.md b/components/Banner/docs/README.md
new file mode 100644
index 0000000..4b58744
--- /dev/null
+++ b/components/Banner/docs/README.md
@@ -0,0 +1,6 @@
+# Banner
+
+<!-- badges -->
+
+A banner displays a prominent message and related optional actions.
+Note: this component is currently being actively developed and is not yet ready for general use.
diff --git a/components/Banner/examples/BannerTypicalUseExampleViewController.h b/components/Banner/examples/BannerTypicalUseExampleViewController.h
new file mode 100644
index 0000000..6f97b12
--- /dev/null
+++ b/components/Banner/examples/BannerTypicalUseExampleViewController.h
@@ -0,0 +1,19 @@
+// Copyright 2018-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 <UIKit/UIKit.h>
+
+@interface BannerTypicalUseExampleViewController : UIViewController
+
+@end
diff --git a/components/Banner/examples/BannerTypicalUseExampleViewController.m b/components/Banner/examples/BannerTypicalUseExampleViewController.m
new file mode 100644
index 0000000..d8d1f4c
--- /dev/null
+++ b/components/Banner/examples/BannerTypicalUseExampleViewController.m
@@ -0,0 +1,36 @@
+// Copyright 2018-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 "BannerTypicalUseExampleViewController.h"
+
+@interface BannerTypicalUseExampleViewController ()
+
+@end
+
+@implementation BannerTypicalUseExampleViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+}
+
++ (NSDictionary *)catalogMetadata {
+ return @{
+ @"breadcrumbs" : @[ @"Banner", @"Typical use" ],
+ @"primaryDemo" : @YES,
+ @"presentable" : @NO,
+ };
+}
+
+@end
diff --git a/components/BottomNavigation/examples/BottomNavigationTypicalUseExample.swift b/components/BottomNavigation/examples/BottomNavigationTypicalUseExample.swift
index 03981da..9ee7a1e 100644
--- a/components/BottomNavigation/examples/BottomNavigationTypicalUseExample.swift
+++ b/components/BottomNavigation/examples/BottomNavigationTypicalUseExample.swift
@@ -25,6 +25,7 @@
init() {
super.init(nibName: nil, bundle: nil)
+ commonBottomNavigationTypicalUseSwiftExampleInit()
}
@available(*, unavailable)
@@ -56,10 +57,14 @@
func layoutBottomNavBar() {
let size = bottomNavBar.sizeThatFits(view.bounds.size)
- let bottomNavBarFrame = CGRect(x: 0,
+ var bottomNavBarFrame = CGRect(x: 0,
y: view.bounds.height - size.height,
width: size.width,
height: size.height)
+ if #available(iOS 11.0, *) {
+ bottomNavBarFrame.size.height += view.safeAreaInsets.bottom
+ bottomNavBarFrame.origin.y -= view.safeAreaInsets.bottom
+ }
bottomNavBar.frame = bottomNavBarFrame
}
@@ -68,14 +73,6 @@
layoutBottomNavBar()
}
- #if swift(>=3.2)
- @available(iOS 11, *)
- override func viewSafeAreaInsetsDidChange() {
- super.viewSafeAreaInsetsDidChange()
- layoutBottomNavBar()
- }
- #endif
-
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: animated)
diff --git a/components/BottomSheet/src/ShapeThemer/MDCBottomSheetControllerShapeThemer.m b/components/BottomSheet/src/ShapeThemer/MDCBottomSheetControllerShapeThemer.m
index b2b7429..f404b28 100644
--- a/components/BottomSheet/src/ShapeThemer/MDCBottomSheetControllerShapeThemer.m
+++ b/components/BottomSheet/src/ShapeThemer/MDCBottomSheetControllerShapeThemer.m
@@ -23,8 +23,8 @@
// Shape Generator for the Extended state of the Bottom Sheet.
MDCRectangleShapeGenerator *rectangleShapeExtended = [[MDCRectangleShapeGenerator alloc] init];
// For a Bottom Sheet the corner values that can be set are the top corners.
- rectangleShapeExtended.topLeftCorner = shapeScheme.largeSurfaceShape.topLeftCorner;
- rectangleShapeExtended.topRightCorner = shapeScheme.largeSurfaceShape.topRightCorner;
+ rectangleShapeExtended.topLeftCorner = shapeScheme.largeComponentShape.topLeftCorner;
+ rectangleShapeExtended.topRightCorner = shapeScheme.largeComponentShape.topRightCorner;
[bottomSheetController setShapeGenerator:rectangleShapeExtended forState:MDCSheetStateExtended];
// Shape Generator for the Preferred state of the Bottom Sheet.
diff --git a/components/BottomSheet/tests/unit/BottomSheetShapeThemerTests.swift b/components/BottomSheet/tests/unit/BottomSheetShapeThemerTests.swift
index 2afd880..69694b8 100644
--- a/components/BottomSheet/tests/unit/BottomSheetShapeThemerTests.swift
+++ b/components/BottomSheet/tests/unit/BottomSheetShapeThemerTests.swift
@@ -23,8 +23,8 @@
// Given
let shapeScheme = MDCShapeScheme()
let bottomSheet = MDCBottomSheetController(contentViewController: UIViewController())
- shapeScheme.largeSurfaceShape = MDCShapeCategory(cornersWith: .angled, andSize: 10)
- shapeScheme.largeSurfaceShape.topRightCorner = MDCCornerTreatment.corner(withRadius: 3)
+ shapeScheme.largeComponentShape = MDCShapeCategory(cornersWith: .cut, andSize: 10)
+ shapeScheme.largeComponentShape.topRightCorner = MDCCornerTreatment.corner(withRadius: 3)
bottomSheet.setShapeGenerator(MDCRectangleShapeGenerator(), for: .extended)
// When
@@ -35,9 +35,9 @@
XCTAssert(extendedShapeGenerator is MDCRectangleShapeGenerator)
if let rectangleGenerator = extendedShapeGenerator as? MDCRectangleShapeGenerator {
XCTAssertEqual(rectangleGenerator.topLeftCorner,
- shapeScheme.largeSurfaceShape.topLeftCorner)
+ shapeScheme.largeComponentShape.topLeftCorner)
XCTAssertEqual(rectangleGenerator.topRightCorner,
- shapeScheme.largeSurfaceShape.topRightCorner)
+ shapeScheme.largeComponentShape.topRightCorner)
XCTAssertEqual(rectangleGenerator.bottomLeftCorner, MDCCornerTreatment())
XCTAssertEqual(rectangleGenerator.bottomRightCorner, MDCCornerTreatment())
}
@@ -50,7 +50,7 @@
let shapeScheme = MDCShapeScheme()
let bottomSheet = MDCBottomSheetController(contentViewController: UIViewController())
let generatedCorner = MDCCornerTreatment.corner(withRadius: collapsedBaselineShapeValue)
- shapeScheme.largeSurfaceShape = MDCShapeCategory(cornersWith: .angled, andSize: 10)
+ shapeScheme.largeComponentShape = MDCShapeCategory(cornersWith: .cut, andSize: 10)
bottomSheet.setShapeGenerator(MDCRectangleShapeGenerator(), for: .preferred)
// When
diff --git a/components/Buttons/src/ShapeThemer/MDCButtonShapeThemer.m b/components/Buttons/src/ShapeThemer/MDCButtonShapeThemer.m
index d78f237..ca9d0ae 100644
--- a/components/Buttons/src/ShapeThemer/MDCButtonShapeThemer.m
+++ b/components/Buttons/src/ShapeThemer/MDCButtonShapeThemer.m
@@ -19,10 +19,10 @@
+ (void)applyShapeScheme:(nonnull id<MDCShapeScheming>)shapeScheme
toButton:(nonnull MDCButton *)button {
MDCRectangleShapeGenerator *rectangleShape = [[MDCRectangleShapeGenerator alloc] init];
- rectangleShape.topLeftCorner = shapeScheme.smallSurfaceShape.topLeftCorner;
- rectangleShape.topRightCorner = shapeScheme.smallSurfaceShape.topRightCorner;
- rectangleShape.bottomLeftCorner = shapeScheme.smallSurfaceShape.bottomLeftCorner;
- rectangleShape.bottomRightCorner = shapeScheme.smallSurfaceShape.bottomRightCorner;
+ rectangleShape.topLeftCorner = shapeScheme.smallComponentShape.topLeftCorner;
+ rectangleShape.topRightCorner = shapeScheme.smallComponentShape.topRightCorner;
+ rectangleShape.bottomLeftCorner = shapeScheme.smallComponentShape.bottomLeftCorner;
+ rectangleShape.bottomRightCorner = shapeScheme.smallComponentShape.bottomRightCorner;
button.shapeGenerator = rectangleShape;
}
diff --git a/components/Buttons/tests/unit/ButtonsShapeThemerTests.m b/components/Buttons/tests/unit/ButtonsShapeThemerTests.m
index 8331059..c0a222b 100644
--- a/components/Buttons/tests/unit/ButtonsShapeThemerTests.m
+++ b/components/Buttons/tests/unit/ButtonsShapeThemerTests.m
@@ -39,9 +39,9 @@
- (void)testMDCButtonShapeThemer {
// Given
- self.shapeScheme.smallSurfaceShape =
- [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyAngled andSize:10];
- self.shapeScheme.smallSurfaceShape.topRightCorner = [MDCCornerTreatment cornerWithRadius:3.f];
+ self.shapeScheme.smallComponentShape =
+ [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyCut andSize:10];
+ self.shapeScheme.smallComponentShape.topRightCorner = [MDCCornerTreatment cornerWithRadius:3.f];
self.button.shapeGenerator = [[MDCRectangleShapeGenerator alloc] init];
// When
@@ -49,19 +49,20 @@
// Then
MDCRectangleShapeGenerator *rect = (MDCRectangleShapeGenerator *)self.button.shapeGenerator;
- XCTAssertEqualObjects(rect.topLeftCorner, self.shapeScheme.smallSurfaceShape.topLeftCorner);
- XCTAssertEqualObjects(rect.topRightCorner, self.shapeScheme.smallSurfaceShape.topRightCorner);
- XCTAssertEqualObjects(rect.bottomLeftCorner, self.shapeScheme.smallSurfaceShape.bottomLeftCorner);
+ XCTAssertEqualObjects(rect.topLeftCorner, self.shapeScheme.smallComponentShape.topLeftCorner);
+ XCTAssertEqualObjects(rect.topRightCorner, self.shapeScheme.smallComponentShape.topRightCorner);
+ XCTAssertEqualObjects(rect.bottomLeftCorner,
+ self.shapeScheme.smallComponentShape.bottomLeftCorner);
XCTAssertEqualObjects(rect.bottomRightCorner,
- self.shapeScheme.smallSurfaceShape.bottomRightCorner);
+ self.shapeScheme.smallComponentShape.bottomRightCorner);
}
- (void)testMDCFloatingButtonShapeThemer {
// Given
MDCFloatingButton *FAB = [[MDCFloatingButton alloc] initWithFrame:CGRectZero
shape:MDCFloatingButtonShapeDefault];
- self.shapeScheme.smallSurfaceShape =
- [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyAngled andSize:10];
+ self.shapeScheme.smallComponentShape =
+ [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyCut andSize:10];
FAB.shapeGenerator = [[MDCRectangleShapeGenerator alloc] init];
// When
diff --git a/components/Cards/src/ShapeThemer/MDCCardsShapeThemer.m b/components/Cards/src/ShapeThemer/MDCCardsShapeThemer.m
index 42be465..0dcf7f5 100644
--- a/components/Cards/src/ShapeThemer/MDCCardsShapeThemer.m
+++ b/components/Cards/src/ShapeThemer/MDCCardsShapeThemer.m
@@ -27,10 +27,10 @@
+ (id<MDCShapeGenerating>)cardShapeGeneratorFromScheme:(id<MDCShapeScheming>)shapeScheme {
MDCRectangleShapeGenerator *rectangleShape = [[MDCRectangleShapeGenerator alloc] init];
- rectangleShape.topLeftCorner = shapeScheme.mediumSurfaceShape.topLeftCorner;
- rectangleShape.topRightCorner = shapeScheme.mediumSurfaceShape.topRightCorner;
- rectangleShape.bottomLeftCorner = shapeScheme.mediumSurfaceShape.bottomLeftCorner;
- rectangleShape.bottomRightCorner = shapeScheme.mediumSurfaceShape.bottomRightCorner;
+ rectangleShape.topLeftCorner = shapeScheme.mediumComponentShape.topLeftCorner;
+ rectangleShape.topRightCorner = shapeScheme.mediumComponentShape.topRightCorner;
+ rectangleShape.bottomLeftCorner = shapeScheme.mediumComponentShape.bottomLeftCorner;
+ rectangleShape.bottomRightCorner = shapeScheme.mediumComponentShape.bottomRightCorner;
return rectangleShape;
}
diff --git a/components/Cards/tests/unit/MDCCardShapeThemerTests.swift b/components/Cards/tests/unit/MDCCardShapeThemerTests.swift
index 8862669..587710c 100644
--- a/components/Cards/tests/unit/MDCCardShapeThemerTests.swift
+++ b/components/Cards/tests/unit/MDCCardShapeThemerTests.swift
@@ -23,8 +23,8 @@
// Given
let shapeScheme = MDCShapeScheme()
let card = MDCCard()
- shapeScheme.mediumSurfaceShape = MDCShapeCategory(cornersWith: .angled, andSize: 10)
- shapeScheme.mediumSurfaceShape.topRightCorner = MDCCornerTreatment.corner(withRadius: 3)
+ shapeScheme.mediumComponentShape = MDCShapeCategory(cornersWith: .cut, andSize: 10)
+ shapeScheme.mediumComponentShape.topRightCorner = MDCCornerTreatment.corner(withRadius: 3)
card.shapeGenerator = MDCRectangleShapeGenerator()
// When
@@ -33,20 +33,20 @@
// Then
XCTAssert(card.shapeGenerator is MDCRectangleShapeGenerator);
XCTAssertEqual((card.shapeGenerator as! MDCRectangleShapeGenerator).topLeftCorner,
- shapeScheme.mediumSurfaceShape.topLeftCorner)
+ shapeScheme.mediumComponentShape.topLeftCorner)
XCTAssertEqual((card.shapeGenerator as! MDCRectangleShapeGenerator).topRightCorner,
- shapeScheme.mediumSurfaceShape.topRightCorner)
+ shapeScheme.mediumComponentShape.topRightCorner)
XCTAssertEqual((card.shapeGenerator as! MDCRectangleShapeGenerator).bottomLeftCorner,
- shapeScheme.mediumSurfaceShape.bottomLeftCorner)
+ shapeScheme.mediumComponentShape.bottomLeftCorner)
XCTAssertEqual((card.shapeGenerator as! MDCRectangleShapeGenerator).bottomRightCorner,
- shapeScheme.mediumSurfaceShape.bottomRightCorner)
+ shapeScheme.mediumComponentShape.bottomRightCorner)
}
func testCardCollectionCellShapeThemer() {
// Given
let shapeScheme = MDCShapeScheme()
let cardCell = MDCCardCollectionCell()
- shapeScheme.mediumSurfaceShape = MDCShapeCategory(cornersWith: .angled, andSize: 10)
+ shapeScheme.mediumComponentShape = MDCShapeCategory(cornersWith: .cut, andSize: 10)
cardCell.shapeGenerator = MDCRectangleShapeGenerator()
// When
@@ -55,12 +55,12 @@
// Then
XCTAssert(cardCell.shapeGenerator is MDCRectangleShapeGenerator);
XCTAssertEqual((cardCell.shapeGenerator as! MDCRectangleShapeGenerator).topLeftCorner,
- shapeScheme.mediumSurfaceShape.topLeftCorner)
+ shapeScheme.mediumComponentShape.topLeftCorner)
XCTAssertEqual((cardCell.shapeGenerator as! MDCRectangleShapeGenerator).topRightCorner,
- shapeScheme.mediumSurfaceShape.topRightCorner)
+ shapeScheme.mediumComponentShape.topRightCorner)
XCTAssertEqual((cardCell.shapeGenerator as! MDCRectangleShapeGenerator).bottomLeftCorner,
- shapeScheme.mediumSurfaceShape.bottomLeftCorner)
+ shapeScheme.mediumComponentShape.bottomLeftCorner)
XCTAssertEqual((cardCell.shapeGenerator as! MDCRectangleShapeGenerator).bottomRightCorner,
- shapeScheme.mediumSurfaceShape.bottomRightCorner)
+ shapeScheme.mediumComponentShape.bottomRightCorner)
}
}
diff --git a/components/Chips/tests/unit/ChipViewShapeThemerTests.m b/components/Chips/tests/unit/ChipViewShapeThemerTests.m
index afda9fc..a18fc56 100644
--- a/components/Chips/tests/unit/ChipViewShapeThemerTests.m
+++ b/components/Chips/tests/unit/ChipViewShapeThemerTests.m
@@ -39,8 +39,8 @@
- (void)testChipViewShapeThemer {
// Given
- self.shapeScheme.smallSurfaceShape =
- [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyAngled andSize:10];
+ self.shapeScheme.smallComponentShape =
+ [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyCut andSize:10];
self.chip.shapeGenerator = [[MDCRectangleShapeGenerator alloc] init];
// When
diff --git a/components/Dialogs/examples/DialogsAlertCustomizationViewController.swift b/components/Dialogs/examples/DialogsAlertCustomizationViewController.swift
index 13931cc..d8245dd 100644
--- a/components/Dialogs/examples/DialogsAlertCustomizationViewController.swift
+++ b/components/Dialogs/examples/DialogsAlertCustomizationViewController.swift
@@ -75,7 +75,14 @@
view.backgroundColor = UIColor.white
- loadCollectionView(menu: ["Dialog with Centered Title"])
+ loadCollectionView(menu: [
+ "Centered Title",
+ "Centered Title With a Title Icon",
+ "Naturally Aligned Title with an Icon",
+ "Right Aligned Title with a Large Icon",
+ "Tinted Title Icon, No Title",
+ "Darker Scrim",
+ ])
}
func loadCollectionView(menu: [String]) {
@@ -84,22 +91,86 @@
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
- switch indexPath.row {
- case 0:
- didTapCenteredTitle()
- default:
- print("No row is selected")
- }
- }
-
- func didTapCenteredTitle() {
- let alert = createMDCAlertController(title: "Dialog Title")
- alert.titleAlignment = .center // todo: theme with themer when available
- MDCAlertControllerThemer.applyScheme(alertScheme, to: alert)
+ guard let alert = performActionFor(row: indexPath.row) else { return }
self.present(alert, animated: true, completion: nil)
}
- private func createMDCAlertController(title: String) -> MDCAlertController {
+ private func performActionFor(row: Int) -> MDCAlertController? {
+ switch row {
+ case 0:
+ return performCenteredTitle()
+ case 1:
+ return performCenteredTitleWithIcon()
+ case 2:
+ return performNaturalTitleWithIcon()
+ case 3:
+ return performRightTitleWithResizedIcon()
+ case 4:
+ return performTintedTitleIconNoTitle()
+ case 5:
+ return performScrimColor()
+ default:
+ print("No row is selected")
+ return nil
+ }
+ }
+
+ func sampleIcon(isStandardSize: Bool = true) -> UIImage? {
+ let bundle = Bundle(for: DialogsAlertCustomizationViewController.self)
+ return UIImage(
+ named: isStandardSize ? "outline_lock_black_24pt" : "baseline_alarm_on_black_48pt",
+ in: bundle, compatibleWith: nil)
+ }
+
+ func performCenteredTitle() -> MDCAlertController {
+ let alert = createMDCAlertController(title: "Center Aligned Title")
+ alert.titleAlignment = .center
+ MDCAlertControllerThemer.applyScheme(alertScheme, to: alert)
+ return alert
+ }
+
+ func performCenteredTitleWithIcon() -> MDCAlertController {
+ let alert = createMDCAlertController(title: "Center Aligned Title")
+ alert.titleIcon = sampleIcon()
+ alert.titleAlignment = .center
+ MDCAlertControllerThemer.applyScheme(alertScheme, to: alert)
+ return alert
+ }
+
+ func performNaturalTitleWithIcon() -> MDCAlertController {
+ let alert = createMDCAlertController(title: "Default (Natural) Title Alignment")
+ alert.titleIcon = sampleIcon()
+ MDCAlertControllerThemer.applyScheme(alertScheme, to: alert)
+ return alert
+ }
+
+ func performRightTitleWithResizedIcon() -> MDCAlertController {
+ let alert = createMDCAlertController(title: "Right Aligned Title")
+ alert.titleIcon = sampleIcon(isStandardSize: false)
+ alert.titleAlignment = .right
+ MDCAlertControllerThemer.applyScheme(alertScheme, to: alert)
+ return alert
+ }
+
+ func performTintedTitleIconNoTitle() -> MDCAlertController {
+ let alert = createMDCAlertController(title: nil)
+ alert.titleIcon = sampleIcon()
+ MDCAlertControllerThemer.applyScheme(alertScheme, to: alert)
+
+ // theming override: set the titleIconTintColor after the color scheme has been applied
+ alert.titleIconTintColor = .red
+
+ return alert
+ }
+
+ func performScrimColor() -> MDCAlertController {
+ let alert = createMDCAlertController(title: "Darker Scrim")
+ MDCAlertControllerThemer.applyScheme(alertScheme, to: alert)
+ alert.mdc_dialogPresentationController?.scrimColor = UIColor.black.withAlphaComponent(0.6)
+ return alert
+ }
+
+ private func createMDCAlertController(title: String?) -> MDCAlertController {
let alertController = MDCAlertController(title: title, message: """
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
diff --git a/components/Dialogs/examples/DialogsAlertViewController.m b/components/Dialogs/examples/DialogsAlertViewController.m
index 39d824f..c8afd14 100644
--- a/components/Dialogs/examples/DialogsAlertViewController.m
+++ b/components/Dialogs/examples/DialogsAlertViewController.m
@@ -31,14 +31,10 @@
- (void)viewDidLoad {
[super viewDidLoad];
- [self loadCollectionView:
- @[ @"Show Alert",
- @"Show Long Alert",
- @"Non-Dismissable Alert",
- @"Alert (Dynamic Type enabled)",
- @"Overpopulated Alert",
- @"Style Alert",
- @"Un-style Alert"]];
+ [self loadCollectionView:@[
+ @"Show Alert", @"Show Long Alert", @"Non-Dismissable Alert", @"Alert (Dynamic Type enabled)",
+ @"Overpopulated Alert", @"Style Alert", @"Un-style Alert", @"Low elevation Alert"
+ ]];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
@@ -65,6 +61,9 @@
case 6:
[self didTapUnstyleAlert];
break;
+ case 7:
+ [self didTapLowElevationAlert];
+ break;
}
}
@@ -382,6 +381,21 @@
[self presentViewController:materialAlertController animated:YES completion:NULL];
}
+- (IBAction)didTapLowElevationAlert {
+ NSString *titleString = @"Using Material alert controller?";
+ NSString *messageString = @"This is an alert controller with a low elevation.";
+ MDCAlertController *materialAlertController =
+ [MDCAlertController alertControllerWithTitle:titleString message:messageString];
+ [self themeAlertController:materialAlertController];
+
+ MDCAlertAction *okAction = [MDCAlertAction actionWithTitle:@"OK"
+ handler:^(MDCAlertAction *action) {
+ NSLog(@"%@", @"OK pressed");
+ }];
+ [materialAlertController addAction:okAction];
+ materialAlertController.elevation = 2;
+ [self presentViewController:materialAlertController animated:YES completion:NULL];
+}
@end
diff --git a/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/Contents.json b/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/Contents.json
new file mode 100755
index 0000000..e490f72
--- /dev/null
+++ b/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/Contents.json
@@ -0,0 +1,24 @@
+{
+ "images": [
+ {
+ "filename": "baseline_alarm_on_black_48pt_1x.png",
+ "idiom": "universal",
+ "scale": "1x"
+ },
+ {
+ "filename": "baseline_alarm_on_black_48pt_2x.png",
+ "idiom": "universal",
+ "scale": "2x"
+ },
+ {
+ "filename": "baseline_alarm_on_black_48pt_3x.png",
+ "idiom": "universal",
+ "scale": "3x"
+ }
+ ],
+ "info": {
+ "author": "xcode",
+ "template-rendering-intent": "template",
+ "version": 1
+ }
+}
\ No newline at end of file
diff --git a/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/baseline_alarm_on_black_48pt_1x.png b/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/baseline_alarm_on_black_48pt_1x.png
new file mode 100755
index 0000000..de67a60
--- /dev/null
+++ b/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/baseline_alarm_on_black_48pt_1x.png
Binary files differ
diff --git a/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/baseline_alarm_on_black_48pt_2x.png b/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/baseline_alarm_on_black_48pt_2x.png
new file mode 100755
index 0000000..7f0376c
--- /dev/null
+++ b/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/baseline_alarm_on_black_48pt_2x.png
Binary files differ
diff --git a/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/baseline_alarm_on_black_48pt_3x.png b/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/baseline_alarm_on_black_48pt_3x.png
new file mode 100755
index 0000000..dee911f
--- /dev/null
+++ b/components/Dialogs/examples/resources/DialogsAssets.xcassets/baseline_alarm_on_black_48pt.imageset/baseline_alarm_on_black_48pt_3x.png
Binary files differ
diff --git a/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/Contents.json b/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/Contents.json
new file mode 100755
index 0000000..949f29b
--- /dev/null
+++ b/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/Contents.json
@@ -0,0 +1,24 @@
+{
+ "images": [
+ {
+ "filename": "outline_lock_black_24pt_1x.png",
+ "idiom": "universal",
+ "scale": "1x"
+ },
+ {
+ "filename": "outline_lock_black_24pt_2x.png",
+ "idiom": "universal",
+ "scale": "2x"
+ },
+ {
+ "filename": "outline_lock_black_24pt_3x.png",
+ "idiom": "universal",
+ "scale": "3x"
+ }
+ ],
+ "info": {
+ "author": "xcode",
+ "template-rendering-intent": "template",
+ "version": 1
+ }
+}
\ No newline at end of file
diff --git a/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/outline_lock_black_24pt_1x.png b/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/outline_lock_black_24pt_1x.png
new file mode 100755
index 0000000..e8bc654
--- /dev/null
+++ b/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/outline_lock_black_24pt_1x.png
Binary files differ
diff --git a/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/outline_lock_black_24pt_2x.png b/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/outline_lock_black_24pt_2x.png
new file mode 100755
index 0000000..1f4a60b
--- /dev/null
+++ b/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/outline_lock_black_24pt_2x.png
Binary files differ
diff --git a/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/outline_lock_black_24pt_3x.png b/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/outline_lock_black_24pt_3x.png
new file mode 100755
index 0000000..590e60a
--- /dev/null
+++ b/components/Dialogs/examples/resources/DialogsAssets.xcassets/outline_lock_black_24pt.imageset/outline_lock_black_24pt_3x.png
Binary files differ
diff --git a/components/Dialogs/src/ColorThemer/MDCAlertColorThemer.m b/components/Dialogs/src/ColorThemer/MDCAlertColorThemer.m
index 5748392..6d50696 100644
--- a/components/Dialogs/src/ColorThemer/MDCAlertColorThemer.m
+++ b/components/Dialogs/src/ColorThemer/MDCAlertColorThemer.m
@@ -24,6 +24,14 @@
alertController.titleColor = [colorScheme.onSurfaceColor colorWithAlphaComponent:(CGFloat)0.87];
alertController.messageColor = [colorScheme.onSurfaceColor colorWithAlphaComponent:(CGFloat)0.60];
alertController.buttonTitleColor = colorScheme.primaryColor;
+ alertController.titleIconTintColor = colorScheme.primaryColor;
+
+ MDCDialogPresentationController *dialogPresentationController =
+ alertController.mdc_dialogPresentationController;
+ if (dialogPresentationController) {
+ dialogPresentationController.scrimColor =
+ [colorScheme.onSurfaceColor colorWithAlphaComponent:(CGFloat)0.32];
+ }
}
+ (void)applyColorScheme:(id<MDCColorScheme>)colorScheme {
diff --git a/components/Dialogs/src/DialogThemer/MaterialDialogs+DialogThemer.h b/components/Dialogs/src/DialogThemer/MaterialDialogs+DialogThemer.h
index 2bce799..048d5f9 100644
--- a/components/Dialogs/src/DialogThemer/MaterialDialogs+DialogThemer.h
+++ b/components/Dialogs/src/DialogThemer/MaterialDialogs+DialogThemer.h
@@ -13,3 +13,4 @@
// limitations under the License.
#import "MDCAlertControllerThemer.h"
+#import "MDCAlertScheme.h"
diff --git a/components/Dialogs/src/MDCAlertController.h b/components/Dialogs/src/MDCAlertController.h
index 332277a..eafdb81 100644
--- a/components/Dialogs/src/MDCAlertController.h
+++ b/components/Dialogs/src/MDCAlertController.h
@@ -76,6 +76,12 @@
/** The alignment applied to the title of the Alert Controller.*/
@property(nonatomic, assign) NSTextAlignment titleAlignment;
+/** An optional icon appearing above the title of the Alert Controller.*/
+@property(nonatomic, strong, nullable) UIImage *titleIcon;
+
+/** The tint color applied to the titleIcon. Leave empty to preserve original image color(s).*/
+@property(nonatomic, strong, nullable) UIColor *titleIconTintColor;
+
/** The font applied to the message of Alert Controller.*/
@property(nonatomic, strong, nullable) UIFont *messageFont;
@@ -94,6 +100,9 @@
/** The corner radius applied to the Alert Controller view. Default to 0 (no round corners) */
@property(nonatomic, assign) CGFloat cornerRadius;
+/** The elevation that will be applied to the Alert Controller view. Default to 24. */
+@property(nonatomic, assign) CGFloat elevation;
+
// TODO(iangordon): Add support for preferredAction to match UIAlertController.
// TODO(iangordon): Consider adding support for UITextFields to match UIAlertController.
diff --git a/components/Dialogs/src/MDCAlertController.m b/components/Dialogs/src/MDCAlertController.m
index 1eb0820..b689152 100644
--- a/components/Dialogs/src/MDCAlertController.m
+++ b/components/Dialogs/src/MDCAlertController.m
@@ -106,6 +106,7 @@
_alertTitle = [title copy];
_message = [message copy];
_actions = [[NSMutableArray alloc] init];
+ _titleAlignment = NSTextAlignmentNatural;
super.transitioningDelegate = _transitionController;
super.modalPresentationStyle = UIModalPresentationCustom;
@@ -219,6 +220,20 @@
}
}
+- (void)setTitleIcon:(UIImage *)titleIcon {
+ _titleIcon = titleIcon;
+ if (self.alertView) {
+ self.alertView.titleIcon = titleIcon;
+ }
+}
+
+- (void)setTitleIconTintColor:(UIColor *)titleIconTintColor {
+ _titleIconTintColor = titleIconTintColor;
+ if (self.alertView) {
+ self.alertView.titleIconTintColor = titleIconTintColor;
+ }
+}
+
- (void)setCornerRadius:(CGFloat)cornerRadius {
_cornerRadius = cornerRadius;
if (self.alertView) {
@@ -232,6 +247,15 @@
}
}
+- (void)setElevation:(CGFloat)elevation {
+ _elevation = elevation;
+ MDCDialogPresentationController *dialogPresentationController =
+ self.mdc_dialogPresentationController;
+ if (dialogPresentationController) {
+ dialogPresentationController.dialogElevation = elevation;
+ }
+}
+
- (void)mdc_setAdjustsFontForContentSizeCategory:(BOOL)adjusts {
_mdc_adjustsFontForContentSizeCategory = adjusts;
@@ -329,6 +353,8 @@
self.alertView.buttonFont = self.buttonFont;
self.alertView.buttonInkColor = self.buttonInkColor;
self.alertView.titleAlignment = self.titleAlignment;
+ self.alertView.titleIcon = self.titleIcon;
+ self.alertView.titleIconTintColor = self.titleIconTintColor;
self.alertView.cornerRadius = self.cornerRadius;
for (MDCAlertAction *action in self.actions) {
diff --git a/components/Dialogs/src/MDCAlertControllerView.h b/components/Dialogs/src/MDCAlertControllerView.h
index 2234c4a..4b13415 100644
--- a/components/Dialogs/src/MDCAlertControllerView.h
+++ b/components/Dialogs/src/MDCAlertControllerView.h
@@ -20,6 +20,8 @@
@property(nonatomic, strong, nullable) UIColor *titleColor UI_APPEARANCE_SELECTOR;
@property(nonatomic, assign) NSTextAlignment titleAlignment;
+@property(nonatomic, strong, nullable) UIImage *titleIcon;
+@property(nonatomic, strong, nullable) UIColor *titleIconTintColor;
@property(nonatomic, strong, nullable) UIFont *messageFont UI_APPEARANCE_SELECTOR;
@property(nonatomic, strong, nullable) UIColor *messageColor UI_APPEARANCE_SELECTOR;
diff --git a/components/Dialogs/src/MDCDialogPresentationController.h b/components/Dialogs/src/MDCDialogPresentationController.h
index 3753748..af2ea6e 100644
--- a/components/Dialogs/src/MDCDialogPresentationController.h
+++ b/components/Dialogs/src/MDCDialogPresentationController.h
@@ -50,6 +50,20 @@
@property(nonatomic, assign) CGFloat dialogCornerRadius;
/**
+ Customize the elevation of the shadow to match the presented view's shadow.
+
+ Defaults to 24.0.
+ */
+@property(nonatomic, assign) CGFloat dialogElevation;
+
+/**
+ Customize the color of the background scrim.
+
+ Defaults to a semi-transparent Black.
+ */
+@property(nonatomic, strong, nullable) UIColor *scrimColor;
+
+/**
Returns the size of the specified child view controller's content.
The size is initially based on container.preferredSize. Width is will have a minimum of 280 and a
diff --git a/components/Dialogs/src/MDCDialogPresentationController.m b/components/Dialogs/src/MDCDialogPresentationController.m
index 2e145ef..144da72 100644
--- a/components/Dialogs/src/MDCDialogPresentationController.m
+++ b/components/Dialogs/src/MDCDialogPresentationController.m
@@ -15,6 +15,7 @@
#import "MDCDialogPresentationController.h"
#import "MaterialKeyboardWatcher.h"
+#import "MaterialShadowLayer.h"
#import "private/MDCDialogShadowedView.h"
static CGFloat MDCDialogMinimumWidth = 280.0f;
@@ -30,7 +31,7 @@
// Tracking view that adds a shadow under the presented view. This view's frame should always match
// the presented view's.
-@property(nonatomic) UIView *trackingView;
+@property(nonatomic) MDCDialogShadowedView *trackingView;
@end
@@ -60,6 +61,22 @@
return _trackingView.layer.cornerRadius;
}
+- (void)setScrimColor:(UIColor *)scrimColor {
+ self.dimmingView.backgroundColor = scrimColor;
+}
+
+- (UIColor *)scrimColor {
+ return self.dimmingView.backgroundColor;
+}
+
+- (void)setDialogElevation:(CGFloat)dialogElevation {
+ _trackingView.elevation = dialogElevation;
+}
+
+- (CGFloat)dialogElevation {
+ return _trackingView.elevation;
+}
+
- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController
presentingViewController:(UIViewController *)presentingViewController {
self = [super initWithPresentedViewController:presentedViewController
diff --git a/components/Dialogs/src/private/MDCAlertControllerView+Private.h b/components/Dialogs/src/private/MDCAlertControllerView+Private.h
index 199572b..286346f 100644
--- a/components/Dialogs/src/private/MDCAlertControllerView+Private.h
+++ b/components/Dialogs/src/private/MDCAlertControllerView+Private.h
@@ -23,6 +23,8 @@
@property(nonatomic, nonnull, strong) UILabel *titleLabel;
@property(nonatomic, nonnull, strong) UILabel *messageLabel;
+@property(nonatomic, nullable, strong) UIImageView *titleIconImageView;
+
@property(nonatomic, nonnull, strong, readonly) NSArray<MDCFlatButton *> *actionButtons;
- (nonnull MDCButton *)addActionButtonTitle:(NSString *_Nonnull)actionTitle
diff --git a/components/Dialogs/src/private/MDCAlertControllerView+Private.m b/components/Dialogs/src/private/MDCAlertControllerView+Private.m
index 0612137..c18a6ae 100644
--- a/components/Dialogs/src/private/MDCAlertControllerView+Private.m
+++ b/components/Dialogs/src/private/MDCAlertControllerView+Private.m
@@ -28,6 +28,7 @@
static const UIEdgeInsets MDCDialogContentInsets = {24.0, 24.0, 24.0, 24.0};
static const CGFloat MDCDialogContentVerticalPadding = 20.0;
+static const CGFloat MDCDialogTitleIconVerticalPadding = 12.0;
static const UIEdgeInsets MDCDialogActionsInsets = {8.0, 8.0, 8.0, 8.0};
static const CGFloat MDCDialogActionsHorizontalPadding = 8.0;
@@ -53,6 +54,7 @@
}
@dynamic titleAlignment;
+@dynamic titleIcon;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
@@ -181,6 +183,31 @@
self.titleLabel.textAlignment = titleAlignment;
}
+- (UIImage *)titleIcon {
+ return self.titleIconImageView.image;
+}
+
+- (void)setTitleIcon:(UIImage *)titleIcon {
+ if (titleIcon == nil) {
+ [self.titleIconImageView removeFromSuperview];
+ self.titleIconImageView = nil;
+ } else if (self.titleIconImageView == nil) {
+ self.titleIconImageView = [[UIImageView alloc] initWithImage:titleIcon];
+ self.titleIconImageView.contentMode = UIViewContentModeScaleAspectFit;
+ [self.contentScrollView addSubview:self.titleIconImageView];
+ } else {
+ self.titleIconImageView.image = titleIcon;
+ }
+
+ self.titleIconImageView.tintColor = self.titleIconTintColor;
+ [self.titleIconImageView sizeToFit];
+}
+
+- (void)setTitleIconTintColor:(UIColor *)titleIconTintColor {
+ _titleIconTintColor = titleIconTintColor;
+ self.titleIconImageView.tintColor = titleIconTintColor;
+}
+
- (NSString *)message {
return self.messageLabel.text;
}
@@ -338,6 +365,13 @@
CGSize boundsSize = CGRectInfinite.size;
boundsSize.width = boundingWidth - MDCDialogContentInsets.left - MDCDialogContentInsets.right;
+ CGSize titleIconSize = CGSizeZero;
+ if (self.titleIconImageView != nil) {
+ // TODO(galiak): Have title-icon size respond to dynamic type or device screen size, once this:
+ // https://github.com/material-components/material-components-ios/issues/5198 is resolved.
+ titleIconSize = self.titleIconImageView.image.size;
+ }
+
CGSize titleSize = [self.titleLabel sizeThatFits:boundsSize];
CGSize messageSize = [self.messageLabel sizeThatFits:boundsSize];
@@ -345,10 +379,15 @@
contentWidth += MDCDialogContentInsets.left + MDCDialogContentInsets.right;
CGFloat contentInternalVerticalPadding = 0.0;
- if (0.0 < titleSize.height && 0.0 < messageSize.height) {
+ if ((0.0 < titleSize.height || 0.0 < titleIconSize.height) && 0.0 < messageSize.height) {
contentInternalVerticalPadding = MDCDialogContentVerticalPadding;
}
- CGFloat contentHeight = titleSize.height + contentInternalVerticalPadding + messageSize.height;
+ CGFloat contentTitleIconVerticalPadding = 0.0f;
+ if (0.0 < titleSize.height && 0.0 < titleIconSize.height) {
+ contentTitleIconVerticalPadding = MDCDialogTitleIconVerticalPadding;
+ }
+ CGFloat contentHeight = titleIconSize.height + contentTitleIconVerticalPadding +
+ titleSize.height + contentInternalVerticalPadding + messageSize.height;
contentHeight += MDCDialogContentInsets.top + MDCDialogContentInsets.bottom;
CGSize contentSize;
@@ -422,17 +461,31 @@
boundsSize.width = boundsSize.width - MDCDialogContentInsets.left - MDCDialogContentInsets.right;
CGSize titleSize = [self.titleLabel sizeThatFits:boundsSize];
titleSize.width = boundsSize.width;
+
+ CGSize titleIconSize = CGSizeZero;
+ if (self.titleIconImageView != nil) {
+ // TODO(galiak): Have title-icon size respond to dynamic type or device screen size, once this:
+ // https://github.com/material-components/material-components-ios/issues/5198 is resolved.
+ titleIconSize = self.titleIconImageView.image.size;
+ }
+
CGSize messageSize = [self.messageLabel sizeThatFits:boundsSize];
messageSize.width = boundsSize.width;
boundsSize.width = boundsSize.width + MDCDialogContentInsets.left + MDCDialogContentInsets.right;
CGFloat contentInternalVerticalPadding = 0.0;
- if (0.0 < titleSize.height && 0.0 < messageSize.height) {
+ if ((0.0 < titleSize.height || 0.0 < titleIconSize.height) && 0.0 < messageSize.height) {
contentInternalVerticalPadding = MDCDialogContentVerticalPadding;
}
+ CGFloat contentTitleIconVerticalPadding = 0.0f;
+ if (0.0 < titleSize.height && 0.0 < titleIconSize.height) {
+ contentTitleIconVerticalPadding = MDCDialogTitleIconVerticalPadding;
+ }
- CGRect titleFrame = CGRectMake(MDCDialogContentInsets.left, MDCDialogContentInsets.top,
- titleSize.width, titleSize.height);
+ CGFloat titleTop =
+ MDCDialogContentInsets.top + contentTitleIconVerticalPadding + titleIconSize.height;
+ CGRect titleFrame =
+ CGRectMake(MDCDialogContentInsets.left, titleTop, titleSize.width, titleSize.height);
CGRect messageFrame = CGRectMake(MDCDialogContentInsets.left,
CGRectGetMaxY(titleFrame) + contentInternalVerticalPadding,
messageSize.width, messageSize.height);
@@ -440,6 +493,22 @@
self.titleLabel.frame = titleFrame;
self.messageLabel.frame = messageFrame;
+ if (self.titleIconImageView != nil) {
+ // match the titleIcon alignment to the title alignment
+ CGFloat titleIconPosition = titleFrame.origin.x;
+ if (self.titleAlignment == NSTextAlignmentCenter) {
+ titleIconPosition = (contentSize.width - titleIconSize.width) / 2.0f;
+ } else if (self.titleAlignment == NSTextAlignmentRight ||
+ (self.titleAlignment == NSTextAlignmentNatural &&
+ [self mdf_effectiveUserInterfaceLayoutDirection] ==
+ UIUserInterfaceLayoutDirectionRightToLeft)) {
+ titleIconPosition = CGRectGetMaxX(titleFrame) - titleIconSize.width;
+ }
+ CGRect titleIconFrame = CGRectMake(titleIconPosition, MDCDialogContentInsets.top,
+ titleIconSize.width, titleIconSize.height);
+ self.titleIconImageView.frame = titleIconFrame;
+ }
+
// Actions
CGSize actionSize = [self calculateActionsSizeThatFitsWidth:boundsSize.width];
const CGFloat horizontalActionHeight =
diff --git a/components/Dialogs/src/private/MDCDialogShadowedView.h b/components/Dialogs/src/private/MDCDialogShadowedView.h
index ddde044..7e6061d 100644
--- a/components/Dialogs/src/private/MDCDialogShadowedView.h
+++ b/components/Dialogs/src/private/MDCDialogShadowedView.h
@@ -15,5 +15,5 @@
#import <UIKit/UIKit.h>
@interface MDCDialogShadowedView : UIView
-
+@property(nonatomic, assign) CGFloat elevation;
@end
diff --git a/components/Dialogs/src/private/MDCDialogShadowedView.m b/components/Dialogs/src/private/MDCDialogShadowedView.m
index 9dc024a..4013966 100644
--- a/components/Dialogs/src/private/MDCDialogShadowedView.m
+++ b/components/Dialogs/src/private/MDCDialogShadowedView.m
@@ -35,4 +35,12 @@
return self;
}
+- (CGFloat)elevation {
+ return [self shadowLayer].elevation;
+}
+
+- (void)setElevation:(CGFloat)elevation {
+ [[self shadowLayer] setElevation:elevation];
+}
+
@end
diff --git a/components/Dialogs/tests/unit/MDCAlertControllerAlertThemerTests.swift b/components/Dialogs/tests/unit/MDCAlertControllerAlertThemerTests.swift
index 7af07a4..c555fee 100644
--- a/components/Dialogs/tests/unit/MDCAlertControllerAlertThemerTests.swift
+++ b/components/Dialogs/tests/unit/MDCAlertControllerAlertThemerTests.swift
@@ -21,18 +21,20 @@
let defaultCornerRadius: CGFloat = 4.0
var alertScheme: MDCAlertScheme = MDCAlertScheme()
+ var alert = MDCAlertController(title: "Title", message: "Message")
+ var alertView: MDCAlertControllerView { return alert.view as! MDCAlertControllerView }
override func setUp() {
super.setUp()
alertScheme = MDCAlertScheme()
+ alertScheme.colorScheme = MDCSemanticColorScheme()
+ alertScheme.typographyScheme = MDCTypographyScheme()
+
+ alert = MDCAlertController(title: "Title", message: "Message")
}
func testDefaultAlertScheme() {
- // When
- let alertScheme = MDCAlertScheme()
-
- // Then
XCTAssertEqual(alertScheme.colorScheme.primaryColor, MDCSemanticColorScheme().primaryColor)
XCTAssertEqual(alertScheme.typographyScheme.body1, MDCTypographyScheme().body1)
XCTAssertEqual(alertScheme.cornerRadius, defaultCornerRadius)
@@ -41,11 +43,8 @@
func testApplyingAlertSchemeWithCustomColor() {
// Given
let colorScheme = MDCSemanticColorScheme()
-
- let alert = MDCAlertController(title: "Title", message: "Message")
- let alertView = alert.view as! MDCAlertControllerView
-
colorScheme.onSurfaceColor = .orange
+ colorScheme.primaryColor = .green
alertScheme.colorScheme = colorScheme
// When
@@ -57,14 +56,46 @@
alertScheme.colorScheme.onSurfaceColor.withAlphaComponent(0.87))
XCTAssertNotEqual(alertView.titleColor,
MDCSemanticColorScheme().onSurfaceColor.withAlphaComponent(0.87))
+ XCTAssertEqual(alertView.titleIconTintColor, colorScheme.primaryColor)
}
+ func testApplyingCustomTitleIconTintColor() {
+ // Given
+ let iconColor = UIColor.red
+ let primaryColor = UIColor.green
+ let colorScheme = MDCSemanticColorScheme()
+ colorScheme.primaryColor = primaryColor
+ alertScheme.colorScheme = colorScheme
+
+ // When
+ MDCAlertControllerThemer.applyScheme(alertScheme, to: alert)
+ alert.titleIconTintColor = iconColor
+
+ // Then
+ XCTAssertEqual(alert.buttonTitleColor, primaryColor)
+ XCTAssertEqual(alertView.buttonColor, primaryColor)
+ XCTAssertEqual(alertView.titleIconTintColor, iconColor)
+ }
+
+ func testApplyingAlertSchemeScrimColorToPresentationController() {
+ guard let presentationController = alert.mdc_dialogPresentationController else { return }
+
+ // Given
+ let colorScheme = MDCSemanticColorScheme()
+ colorScheme.onSurfaceColor = UIColor.green
+ alertScheme.colorScheme = colorScheme
+ let scrimColor = colorScheme.onSurfaceColor.withAlphaComponent(0.32)
+
+ // When
+ MDCAlertControllerThemer.applyScheme(alertScheme, to: alert)
+
+ // Then
+ XCTAssertEqual(presentationController.scrimColor, scrimColor)
+ }
+
func testApplyingAlertSchemeWithCustomTypography() {
// Given
let typographyScheme = MDCTypographyScheme()
- let alert = MDCAlertController(title: "Title", message: "Message")
- let alertView = alert.view as! MDCAlertControllerView
-
let testFont = UIFont.boldSystemFont(ofSize: 55.0)
typographyScheme.headline6 = testFont
alertScheme.typographyScheme = typographyScheme
@@ -82,9 +113,6 @@
func testApplyingAlertSchemeWithCustomShape() {
// Given
let cornerRadius: CGFloat = 33.3
- let alert = MDCAlertController(title: "Title", message: "Message")
- let alertView = alert.view as! MDCAlertControllerView
-
alertScheme.cornerRadius = cornerRadius
// When
diff --git a/components/Dialogs/tests/unit/MDCAlertControllerCustomizationTests.m b/components/Dialogs/tests/unit/MDCAlertControllerCustomizationTests.m
index 9f6434a..f367d46 100644
--- a/components/Dialogs/tests/unit/MDCAlertControllerCustomizationTests.m
+++ b/components/Dialogs/tests/unit/MDCAlertControllerCustomizationTests.m
@@ -25,19 +25,17 @@
@implementation MDCAlertControllerCustomizationTests
+MDCAlertController *alert;
+MDCAlertControllerView *alertView;
+
- (void)setUp {
[super setUp];
-}
-
-- (void)tearDown {
- [super tearDown];
+ alert = [MDCAlertController alertControllerWithTitle:@"Title" message:@"Message"];
+ alertView = (MDCAlertControllerView *)alert.view;
}
- (void)testApplyingTitleAlignment {
// Given
- MDCAlertController *alert = [MDCAlertController alertControllerWithTitle:@"Title"
- message:@"Message"];
- MDCAlertControllerView *alertView = (MDCAlertControllerView *)alert.view;
NSTextAlignment titleAlignment = NSTextAlignmentCenter;
// When
@@ -48,4 +46,76 @@
XCTAssertEqual(alertView.titleLabel.textAlignment, titleAlignment);
}
+- (void)testAddingTitleIconToAlert {
+ // Given
+ UIImage *icon = TestImage(CGSizeMake(24, 24));
+
+ // When
+ alert.titleIcon = icon;
+
+ // Then
+ XCTAssertNotNil(alert.titleIcon);
+ XCTAssertEqual(alertView.titleIcon, icon);
+ XCTAssertEqual(alertView.titleIconImageView.image, icon);
+}
+
+- (void)testApplyingTintToTitleIcon {
+ // Given
+ UIImage *icon = TestImage(CGSizeMake(24, 24));
+ UIColor *tintColor = UIColor.orangeColor;
+
+ // When
+ alert.titleIcon = icon;
+ alert.titleIconTintColor = tintColor;
+
+ // Then
+ XCTAssertNotNil(alert.titleIcon);
+ XCTAssertEqualObjects(alertView.titleIcon, icon);
+ XCTAssertEqualObjects(alertView.titleIconTintColor, tintColor);
+ XCTAssertEqualObjects(alertView.titleIconImageView.tintColor, tintColor);
+}
+
+- (void)testApplyingTintToTitleIconInAnyOrder {
+ // Given
+ UIImage *icon = TestImage(CGSizeMake(24, 24));
+ UIColor *tintColor = UIColor.orangeColor;
+
+ // When
+ alert.titleIconTintColor = tintColor;
+ alert.titleIcon = icon;
+
+ // Then
+ XCTAssertNotNil(alert.titleIcon);
+ XCTAssertEqualObjects(alertView.titleIcon, icon);
+ XCTAssertEqualObjects(alertView.titleIconTintColor, tintColor);
+ XCTAssertEqualObjects(alertView.titleIconImageView.tintColor, tintColor);
+}
+
+- (void)testApplyingScrimColorToPresentationController {
+ // Given
+ UIColor *scrimColor = [UIColor.orangeColor colorWithAlphaComponent:0.5];
+ MDCDialogPresentationController *presentationController = alert.mdc_dialogPresentationController;
+ if (presentationController == nil) {
+ return; // don't fail the test if mdc_dialogPresentationController is empty
+ }
+
+ // When
+ presentationController.scrimColor = scrimColor;
+
+ // Then
+ XCTAssertEqualObjects(alert.mdc_dialogPresentationController.scrimColor, scrimColor);
+}
+
+static inline UIImage *TestImage(CGSize size) {
+ CGFloat scale = [UIScreen mainScreen].scale;
+ UIGraphicsBeginImageContextWithOptions(size, false, scale);
+ [UIColor.redColor setFill];
+ CGRect fillRect = CGRectZero;
+ fillRect.size = size;
+ UIRectFill(fillRect);
+ UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ return image;
+}
+
@end
diff --git a/components/Dialogs/tests/unit/MDCAlertControllerTests.m b/components/Dialogs/tests/unit/MDCAlertControllerTests.m
index 2ca8bb3..3e71d08 100644
--- a/components/Dialogs/tests/unit/MDCAlertControllerTests.m
+++ b/components/Dialogs/tests/unit/MDCAlertControllerTests.m
@@ -16,6 +16,7 @@
#import "MaterialButtons.h"
#import "MaterialDialogs.h"
+#import "../../src/private/MDCDialogShadowedView.h"
#import "MDCAlertControllerView+Private.h"
#pragma mark - Subclasses for testing
@@ -30,6 +31,10 @@
@property(nonatomic, assign) NSInteger value;
@end
+@interface MDCDialogPresentationController (Testing)
+@property(nonatomic) MDCDialogShadowedView *trackingView;
+@end
+
@implementation MDCAlertControllerSubclass
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
@@ -304,4 +309,46 @@
cornerRadius, 0.0);
}
+- (void)testDefaultElevation {
+ // Given
+ CGFloat elevation = (CGFloat)MDCShadowElevationDialog;
+ MDCAlertController *alert = [MDCAlertController alertControllerWithTitle:@"title"
+ message:@"message"];
+ [alert addAction:[MDCAlertAction actionWithTitle:@"action1" handler:nil]];
+
+ // Then
+ MDCDialogShadowedView *shadowView = alert.mdc_dialogPresentationController.trackingView;
+ XCTAssertEqual(shadowView.elevation, elevation);
+}
+
+- (void)testCustomElevation {
+ // Given
+ CGFloat elevation = (CGFloat)2.0;
+ MDCAlertController *alert = [MDCAlertController alertControllerWithTitle:@"title"
+ message:@"message"];
+ [alert addAction:[MDCAlertAction actionWithTitle:@"action1" handler:nil]];
+
+ // When
+ alert.elevation = elevation;
+
+ // Then
+ MDCDialogShadowedView *shadowView = alert.mdc_dialogPresentationController.trackingView;
+ XCTAssertEqual(shadowView.elevation, elevation);
+}
+
+- (void)testCustomDialogPresentationElevation {
+ // Given
+ CGFloat elevation = (CGFloat)2.0;
+ MDCAlertController *alert = [MDCAlertController alertControllerWithTitle:@"title"
+ message:@"message"];
+ [alert addAction:[MDCAlertAction actionWithTitle:@"action1" handler:nil]];
+
+ // When
+ alert.mdc_dialogPresentationController.dialogElevation = elevation;
+
+ // Then
+ MDCDialogShadowedView *shadowView = alert.mdc_dialogPresentationController.trackingView;
+ XCTAssertEqual(shadowView.elevation, elevation);
+}
+
@end
diff --git a/components/FlexibleHeader/src/MDCFlexibleHeaderView.m b/components/FlexibleHeader/src/MDCFlexibleHeaderView.m
index 9d7149a..4a24d05 100644
--- a/components/FlexibleHeader/src/MDCFlexibleHeaderView.m
+++ b/components/FlexibleHeader/src/MDCFlexibleHeaderView.m
@@ -551,10 +551,10 @@
info.hasInjectedTopContentInset = NO;
scrollView.contentInset = insets;
- UIEdgeInsets scrollIndicatorInsets = _trackingScrollView.scrollIndicatorInsets;
+ UIEdgeInsets scrollIndicatorInsets = scrollView.scrollIndicatorInsets;
scrollIndicatorInsets.top -= info.injectedTopScrollIndicatorInset;
info.injectedTopScrollIndicatorInset = 0;
- _trackingScrollView.scrollIndicatorInsets = scrollIndicatorInsets;
+ scrollView.scrollIndicatorInsets = scrollIndicatorInsets;
}
- (CGFloat)fhv_existingContentInsetAdjustmentForScrollView:(UIScrollView *)scrollView {
diff --git a/components/LibraryInfo/src/MDCLibraryInfo.m b/components/LibraryInfo/src/MDCLibraryInfo.m
index 456ab9e..dab8612 100644
--- a/components/LibraryInfo/src/MDCLibraryInfo.m
+++ b/components/LibraryInfo/src/MDCLibraryInfo.m
@@ -19,7 +19,7 @@
// This string is updated automatically as a part of the release process and should not be edited
// manually. Do not rename this constant or change the formatting without updating the release
// scripts.
-static NSString const *MDCLibraryInfoVersionString = @"65.0.0";
+static NSString const *MDCLibraryInfoVersionString = @"66.0.0";
@implementation MDCLibraryInfo
diff --git a/components/LibraryInfo/tests/unit/LibraryInfoTests.swift b/components/LibraryInfo/tests/unit/LibraryInfoTests.swift
index 215695c..495a1d5 100644
--- a/components/LibraryInfo/tests/unit/LibraryInfoTests.swift
+++ b/components/LibraryInfo/tests/unit/LibraryInfoTests.swift
@@ -21,7 +21,7 @@
// Given
// This regex pattern does the following:
- // Accept: "65.0.0", etc.
+ // Accept: "66.0.0", etc.
// Reject: "0.0.0", "1.2", "1", "-1.2.3", "Hi, I'm a version 1.2.3", "1.2.3 is my version", etc.
//
// Note the major version must be >= 1 since "0.0.0" is used as the version when something goes
diff --git a/components/List/BUILD b/components/List/BUILD
index 35f21d0..120c65d 100644
--- a/components/List/BUILD
+++ b/components/List/BUILD
@@ -13,7 +13,8 @@
# limitations under the License.
load("//:material_components_ios.bzl",
- "mdc_public_objc_library")
+ "mdc_public_objc_library",
+ "mdc_objc_library")
licenses(["notice"]) # Apache 2.0
@@ -31,3 +32,16 @@
"@material_internationalization_ios//:MDFInternationalization",
],
)
+
+mdc_objc_library(
+ name = "TypographyThemer",
+ srcs = native.glob(["src/TypographyThemer/*.m"]),
+ hdrs = native.glob(["src/TypographyThemer/*.h"]),
+ includes = ["src/TypographyThemer"],
+ sdk_frameworks = ["UIKit"],
+ deps = [
+ ":List",
+ "//components/schemes/Typography",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/components/List/examples/MDCSelfSizingStereoCellExample.m b/components/List/examples/MDCSelfSizingStereoCellExample.m
index 3dcaee0..bd86af5 100644
--- a/components/List/examples/MDCSelfSizingStereoCellExample.m
+++ b/components/List/examples/MDCSelfSizingStereoCellExample.m
@@ -15,6 +15,7 @@
#import "MDCSelfSizingStereoCellExample.h"
#import "MDCSelfSizingStereoCell.h"
+#import "MaterialList+TypographyThemer.h"
static CGFloat const kArbitraryCellHeight = 75.f;
static NSString *const kSelfSizingStereoCellIdentifier = @"kSelfSizingStereoCellIdentifier";
@@ -27,6 +28,7 @@
@property(nonatomic, strong) UICollectionView *collectionView;
@property(nonatomic, strong) UICollectionViewFlowLayout *collectionViewLayout;
@property(nonatomic, strong) NSArray *randomStrings;
+@property(nonatomic, strong) MDCTypographyScheme *typographyScheme;
@property(nonatomic, assign) NSInteger numberOfCells;
@end
@@ -36,6 +38,8 @@
[super viewDidLoad];
self.parentViewController.automaticallyAdjustsScrollViewInsets = NO;
self.automaticallyAdjustsScrollViewInsets = NO;
+ self.typographyScheme = [[MDCTypographyScheme alloc] init];
+
[self createDataSource];
[self createCollectionView];
}
@@ -113,6 +117,8 @@
cell.leadingImageView.tintColor = [UIColor darkGrayColor];
cell.trailingImageView.tintColor = [UIColor darkGrayColor];
cell.mdc_adjustsFontForContentSizeCategory = YES;
+ [MDCSelfSizingStereoCellTypographyThemer applyTypographyScheme:self.typographyScheme
+ toSelfSizingStereoCell:cell];
return cell;
}
diff --git a/components/List/src/TypographyThemer/MDCSelfSizingStereoCellTypographyThemer.h b/components/List/src/TypographyThemer/MDCSelfSizingStereoCellTypographyThemer.h
new file mode 100644
index 0000000..3a45ede
--- /dev/null
+++ b/components/List/src/TypographyThemer/MDCSelfSizingStereoCellTypographyThemer.h
@@ -0,0 +1,35 @@
+// Copyright 2018-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 "MDCSelfSizingStereoCell.h"
+#import "MaterialTypographyScheme.h"
+
+#import <Foundation/Foundation.h>
+
+/**
+ The Material Design typography system's themer for instances of
+ MDCSelfSizingStereoCellTypographyThemer.
+ */
+@interface MDCSelfSizingStereoCellTypographyThemer : NSObject
+
+/**
+ Applies a typography scheme's properties to an MDCSelfSizingStereoCell.
+
+ @param typographyScheme The typography scheme to apply to the component instance.
+ @param cell A component instance to which the typography scheme should be applied.
+ */
++ (void)applyTypographyScheme:(id<MDCTypographyScheming>)typographyScheme
+ toSelfSizingStereoCell:(MDCSelfSizingStereoCell *)cell;
+
+@end
diff --git a/components/List/src/TypographyThemer/MDCSelfSizingStereoCellTypographyThemer.m b/components/List/src/TypographyThemer/MDCSelfSizingStereoCellTypographyThemer.m
new file mode 100644
index 0000000..1324637
--- /dev/null
+++ b/components/List/src/TypographyThemer/MDCSelfSizingStereoCellTypographyThemer.m
@@ -0,0 +1,25 @@
+// Copyright 2018-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 "MDCSelfSizingStereoCellTypographyThemer.h"
+
+@implementation MDCSelfSizingStereoCellTypographyThemer
+
++ (void)applyTypographyScheme:(id<MDCTypographyScheming>)typographyScheme
+ toSelfSizingStereoCell:(MDCSelfSizingStereoCell *)cell {
+ cell.titleLabel.font = typographyScheme.subtitle1;
+ cell.detailLabel.font = typographyScheme.body2;
+}
+
+@end
diff --git a/components/List/src/TypographyThemer/MaterialList+TypographyThemer.h b/components/List/src/TypographyThemer/MaterialList+TypographyThemer.h
new file mode 100644
index 0000000..f6a00f5
--- /dev/null
+++ b/components/List/src/TypographyThemer/MaterialList+TypographyThemer.h
@@ -0,0 +1,15 @@
+// Copyright 2018-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 "MDCSelfSizingStereoCellTypographyThemer.h"
diff --git a/components/NavigationDrawer/src/MDCBottomDrawerPresentationController.m b/components/NavigationDrawer/src/MDCBottomDrawerPresentationController.m
index e47029d..fdd0168 100644
--- a/components/NavigationDrawer/src/MDCBottomDrawerPresentationController.m
+++ b/components/NavigationDrawer/src/MDCBottomDrawerPresentationController.m
@@ -37,10 +37,14 @@
@implementation MDCBottomDrawerPresentationController
-// Override the presentedView property getter to return our container view controller's
-// view instead of the default.
- (UIView *)presentedView {
- return self.bottomDrawerContainerViewController.view;
+ if ([self.presentedViewController isKindOfClass:[MDCBottomDrawerViewController class]]) {
+ return super.presentedView;
+ } else {
+ // Override the presentedView property getter to return our container view controller's
+ // view instead of the default.
+ return self.bottomDrawerContainerViewController.view;
+ }
}
- (void)presentationTransitionWillBegin {
@@ -73,7 +77,12 @@
self.scrimView.accessibilityTraits |= UIAccessibilityTraitButton;
[self.containerView addSubview:self.scrimView];
- [self.containerView addSubview:self.bottomDrawerContainerViewController.view];
+
+ if ([self.presentedViewController isKindOfClass:[MDCBottomDrawerViewController class]]) {
+ [self.presentedView addSubview:self.bottomDrawerContainerViewController.view];
+ } else {
+ [self.containerView addSubview:self.bottomDrawerContainerViewController.view];
+ }
id<UIViewControllerTransitionCoordinator> transitionCoordinator =
[[self presentingViewController] transitionCoordinator];
diff --git a/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m b/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m
index 07123dd..05cef09 100644
--- a/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m
+++ b/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m
@@ -204,11 +204,11 @@
CGFloat headerHeightWithoutInset = self.contentHeaderHeight - topAreaInsetForHeader;
CGFloat contentDiff = contentYOffset - drawerOffset;
CGFloat maxScrollOrigin = self.trackingScrollView.contentSize.height -
- self.presentingViewBounds.size.height + headerHeightWithoutInset;
- BOOL scrollingUpInFull = contentDiff < 0 && self.trackingScrollView.bounds.origin.y > 0;
- if (self.scrollView.bounds.origin.y >= drawerOffset || scrollingUpInFull) {
+ CGRectGetHeight(self.presentingViewBounds) + headerHeightWithoutInset;
+ BOOL scrollingUpInFull = contentDiff < 0 && CGRectGetMinY(self.trackingScrollView.bounds) > 0;
+ if (CGRectGetMinY(self.scrollView.bounds) >= drawerOffset || scrollingUpInFull) {
// If we reach full screen or if we are scrolling up after being in full screen.
- if (self.trackingScrollView.bounds.origin.y < maxScrollOrigin || scrollingUpInFull) {
+ if (CGRectGetMinY(self.trackingScrollView.bounds) < maxScrollOrigin || scrollingUpInFull) {
// If we still didn't reach the end of the content, or if we are scrolling up after reaching
// the end of the content.
@@ -225,15 +225,16 @@
// Update the main content view's scrollView offset
CGRect contentViewBounds = self.trackingScrollView.bounds;
contentViewBounds.origin.y += contentDiff;
- contentViewBounds.origin.y = MIN(maxScrollOrigin, MAX(contentViewBounds.origin.y, 0));
+ contentViewBounds.origin.y = MIN(maxScrollOrigin, MAX(CGRectGetMinY(contentViewBounds), 0));
self.trackingScrollView.bounds = contentViewBounds;
} else {
- if (self.trackingScrollView.contentSize.height >= self.trackingScrollView.frame.size.height) {
+ if (self.trackingScrollView.contentSize.height >=
+ CGRectGetHeight(self.trackingScrollView.frame)) {
// Have the drawer's scrollView's content size be static so it will bounce when reaching the
// end of the content.
CGSize scrollViewContentSize = self.scrollView.contentSize;
scrollViewContentSize.height =
- drawerOffset + self.scrollView.frame.size.height + 2 * topAreaInsetForHeader;
+ drawerOffset + CGRectGetHeight(self.scrollView.frame) + 2 * topAreaInsetForHeader;
self.scrollView.contentSize = scrollViewContentSize;
}
}
diff --git a/components/Tabs/src/private/MDCItemBar.m b/components/Tabs/src/private/MDCItemBar.m
index 547aa3a..22266ef 100644
--- a/components/Tabs/src/private/MDCItemBar.m
+++ b/components/Tabs/src/private/MDCItemBar.m
@@ -623,10 +623,6 @@
}
- (void)updateFlowLayoutMetrics {
- // Layout metrics cannot be updated while offscreen.
- if (!self.window) {
- return;
- }
UIUserInterfaceSizeClass horizontalSizeClass = [self horizontalSizeClass];
@@ -656,7 +652,6 @@
// This is not animated because -updateFlowLayoutMetrics may be called in an animation block and
// the change will be still get animated anyway - using NO avoids 'double' animation and allows
// this method to be used without animation.
- NSAssert(_collectionView.window, @"Collection view must be in a window to update layout");
[_collectionView setCollectionViewLayout:_flowLayout animated:NO];
// Force immediate layout so the selection indicator can be placed accurately.
diff --git a/components/Tabs/src/private/MDCItemBarCell.m b/components/Tabs/src/private/MDCItemBarCell.m
index fd397b6..146c9fe 100644
--- a/components/Tabs/src/private/MDCItemBarCell.m
+++ b/components/Tabs/src/private/MDCItemBarCell.m
@@ -294,7 +294,8 @@
}
}
- CGFloat scale = self.window.screen.scale;
+ UIScreen *screen = self.window.screen ?: UIScreen.mainScreen;
+ CGFloat scale = screen.scale;
_imageView.bounds = imageBounds;
_imageView.center = MDCRoundCenterWithBoundsAndScale(imageCenter, _imageView.bounds, scale);
@@ -317,12 +318,9 @@
- (void)didMoveToWindow {
[super didMoveToWindow];
- if (self.window) {
- [self updateTransformsAnimated:NO];
+ [self updateTransformsAnimated:NO];
- // Layout depends on window scale.
- [self setNeedsLayout];
- }
+ [self setNeedsLayout];
}
#pragma mark - UICollectionReusableView
@@ -505,7 +503,7 @@
CGAffineTransform titleTransform = CGAffineTransformIdentity;
CGAffineTransform imageTransform = CGAffineTransformIdentity;
- UIScreen *screen = self.window.screen;
+ UIScreen *screen = self.window.screen ?: UIScreen.mainScreen;
const CGFloat screenScale = (screen ? screen.scale : 1);
CGFloat titleContentsScale = screenScale;
diff --git a/components/Tabs/tests/unit/MaterialTabsTests.m b/components/Tabs/tests/unit/MaterialTabsTests.m
index 362dd3d..9d8094f 100644
--- a/components/Tabs/tests/unit/MaterialTabsTests.m
+++ b/components/Tabs/tests/unit/MaterialTabsTests.m
@@ -85,4 +85,6 @@
XCTAssertEqual(_tabBar.selectedItem, _itemB);
}
+// TODO(#5199): Add a snapshot test to prove the tabs render without a window
+
@end
diff --git a/components/TextFields/src/MDCTextInputControllerBase.m b/components/TextFields/src/MDCTextInputControllerBase.m
index bf1763a..e7559fc 100644
--- a/components/TextFields/src/MDCTextInputControllerBase.m
+++ b/components/TextFields/src/MDCTextInputControllerBase.m
@@ -1580,7 +1580,6 @@
self.textInput.leadingUnderlineLabel.accessibilityLabel =
[NSString stringWithFormat:@"Error: %@.",
leadingUnderlineLabelText ? leadingUnderlineLabelText : @""];
- UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.textInput.leadingUnderlineLabel);
} else {
self.textInput.accessibilityValue = nil;
if ([self.textInput.leadingUnderlineLabel.text isEqualToString:self.helperText]) {
@@ -1589,6 +1588,8 @@
self.textInput.leadingUnderlineLabel.accessibilityLabel = nil;
}
}
+ UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
+ self.textInput.leadingUnderlineLabel);
}
-(void)setHelperText:(NSString *)helperText
diff --git a/components/schemes/Shape/examples/MDCShapeSchemeExampleViewController.h b/components/schemes/Shape/examples/MDCShapeSchemeExampleViewController.h
new file mode 100644
index 0000000..38e8121
--- /dev/null
+++ b/components/schemes/Shape/examples/MDCShapeSchemeExampleViewController.h
@@ -0,0 +1,19 @@
+// Copyright 2018-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 <UIKit/UIKit.h>
+
+@interface MDCShapeSchemeExampleViewController : UIViewController
+
+@end
diff --git a/components/schemes/Shape/examples/MDCShapeSchemeExampleViewController.m b/components/schemes/Shape/examples/MDCShapeSchemeExampleViewController.m
new file mode 100644
index 0000000..58103647
--- /dev/null
+++ b/components/schemes/Shape/examples/MDCShapeSchemeExampleViewController.m
@@ -0,0 +1,370 @@
+// Copyright 2018-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 "MDCShapeSchemeExampleViewController.h"
+
+#import "../../../BottomSheet/examples/supplemental/BottomSheetDummyCollectionViewController.h"
+#import "supplemental/MDCBottomSheetControllerShapeThemerDefaultMapping.h"
+#import "supplemental/MDCChipViewShapeThemerDefaultMapping.h"
+#import "supplemental/MDCFloatingButtonShapeThemerDefaultMapping.h"
+
+#import "MaterialAppBar+ColorThemer.h"
+#import "MaterialAppBar+TypographyThemer.h"
+#import "MaterialAppBar.h"
+#import "MaterialBottomSheet+ShapeThemer.h"
+#import "MaterialBottomSheet.h"
+#import "MaterialButtons+ButtonThemer.h"
+#import "MaterialButtons+ShapeThemer.h"
+#import "MaterialButtons.h"
+#import "MaterialCards+CardThemer.h"
+#import "MaterialCards+ShapeThemer.h"
+#import "MaterialCards.h"
+#import "MaterialChips+ChipThemer.h"
+#import "MaterialChips+ShapeThemer.h"
+#import "MaterialChips.h"
+#import "MaterialColorScheme.h"
+#import "MaterialShapeLibrary.h"
+#import "MaterialShapeScheme.h"
+#import "MaterialTypographyScheme.h"
+
+@interface MDCShapeSchemeExampleViewController ()
+@property(strong, nonatomic) MDCSemanticColorScheme *colorScheme;
+@property(strong, nonatomic) MDCShapeScheme *shapeScheme;
+@property(strong, nonatomic) MDCTypographyScheme *typographyScheme;
+
+@property(weak, nonatomic) IBOutlet MDCShapedView *smallComponentShape;
+@property(weak, nonatomic) IBOutlet MDCShapedView *mediumComponentShape;
+@property(weak, nonatomic) IBOutlet MDCShapedView *largeComponentShape;
+@property(weak, nonatomic) IBOutlet UISegmentedControl *smallComponentType;
+@property(weak, nonatomic) IBOutlet UISegmentedControl *mediumComponentType;
+@property(weak, nonatomic) IBOutlet UISegmentedControl *largeComponentType;
+@property(weak, nonatomic) IBOutlet UISlider *smallComponentValue;
+@property(weak, nonatomic) IBOutlet UISlider *mediumComponentValue;
+@property(weak, nonatomic) IBOutlet UISlider *largeComponentValue;
+@property(weak, nonatomic) IBOutlet UISegmentedControl *includeBaselineOverridesToggle;
+@property(weak, nonatomic) IBOutlet UIView *componentContentView;
+
+@property(strong, nonatomic) MDCButton *containedButton;
+@property(strong, nonatomic) MDCButton *outlinedButton;
+@property(strong, nonatomic) MDCFloatingButton *floatingButton;
+@property(strong, nonatomic) MDCChipView *chipView;
+@property(strong, nonatomic) MDCCard *card;
+@property(strong, nonatomic) MDCButton *presentBottomSheetButton;
+@property(strong, nonatomic) MDCBottomSheetController *bottomSheetController;
+@end
+
+@implementation MDCShapeSchemeExampleViewController
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ [self commonShapeSchemeExampleInit];
+ }
+ return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder {
+ self = [super initWithCoder:coder];
+ if (self) {
+ [self commonShapeSchemeExampleInit];
+ }
+ return self;
+}
+
+- (void)commonShapeSchemeExampleInit {
+ _colorScheme = [[MDCSemanticColorScheme alloc] init];
+ _shapeScheme = [[MDCShapeScheme alloc] init];
+ _typographyScheme = [[MDCTypographyScheme alloc] init];
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ _smallComponentShape.shapeGenerator = [[MDCRectangleShapeGenerator alloc] init];
+ _mediumComponentShape.shapeGenerator = [[MDCRectangleShapeGenerator alloc] init];
+ _largeComponentShape.shapeGenerator = [[MDCRectangleShapeGenerator alloc] init];
+
+ [self applySchemeColors];
+ [self initializeComponentry];
+}
+
+- (void)initializeComponentry {
+ MDCButtonScheme *buttonScheme = [[MDCButtonScheme alloc] init];
+ buttonScheme.colorScheme = self.colorScheme;
+ buttonScheme.shapeScheme = self.shapeScheme;
+ buttonScheme.typographyScheme = self.typographyScheme;
+
+ self.containedButton = [[MDCButton alloc] init];
+ [self.containedButton setTitle:@"Button" forState:UIControlStateNormal];
+ [MDCContainedButtonThemer applyScheme:buttonScheme toButton:self.containedButton];
+ self.containedButton.translatesAutoresizingMaskIntoConstraints = NO;
+ [self.componentContentView addSubview:self.containedButton];
+
+ self.floatingButton = [[MDCFloatingButton alloc] init];
+ UIImage *plusImage =
+ [[UIImage imageNamed:@"Plus"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+ [self.floatingButton setImage:plusImage forState:UIControlStateNormal];
+ [MDCFloatingActionButtonThemer applyScheme:buttonScheme toButton:self.floatingButton];
+ [self.floatingButton sizeToFit];
+ self.floatingButton.translatesAutoresizingMaskIntoConstraints = NO;
+ [self.componentContentView addSubview:self.floatingButton];
+
+ MDCChipViewScheme *chipViewScheme = [[MDCChipViewScheme alloc] init];
+ chipViewScheme.colorScheme = self.colorScheme;
+ chipViewScheme.shapeScheme = self.shapeScheme;
+ chipViewScheme.typographyScheme = self.typographyScheme;
+
+ self.chipView = [[MDCChipView alloc] init];
+ self.chipView.titleLabel.text = @"Material";
+ self.chipView.imageView.image = [self faceImage];
+ self.chipView.accessoryView = [self deleteButton];
+ self.chipView.minimumSize = CGSizeMake(140, 33);
+ self.chipView.translatesAutoresizingMaskIntoConstraints = NO;
+ [MDCChipViewThemer applyScheme:chipViewScheme toChipView:self.chipView];
+ [self.componentContentView addSubview:self.chipView];
+
+ MDCCardScheme *cardScheme = [[MDCCardScheme alloc] init];
+ cardScheme.colorScheme = self.colorScheme;
+ cardScheme.shapeScheme = self.shapeScheme;
+
+ self.card = [[MDCCard alloc] init];
+ self.card.translatesAutoresizingMaskIntoConstraints = NO;
+ [MDCCardThemer applyScheme:cardScheme toCard:self.card];
+ self.card.backgroundColor = _colorScheme.primaryColor;
+ [self.componentContentView addSubview:self.card];
+
+ NSArray<NSLayoutConstraint *> *cardConstraints =
+ [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[card]-|"
+ options:0
+ metrics:nil
+ views:@{@"card" : self.card}];
+ [self.view addConstraints:cardConstraints];
+
+ self.presentBottomSheetButton = [[MDCButton alloc] init];
+ [self.presentBottomSheetButton setTitle:@"Present Bottom Sheet" forState:UIControlStateNormal];
+ [MDCOutlinedButtonThemer applyScheme:buttonScheme toButton:self.presentBottomSheetButton];
+ self.presentBottomSheetButton.translatesAutoresizingMaskIntoConstraints = NO;
+ [self.componentContentView addSubview:self.presentBottomSheetButton];
+ [self.presentBottomSheetButton addTarget:self
+ action:@selector(presentBottomSheet)
+ forControlEvents:UIControlEventTouchUpInside];
+
+ NSArray<NSLayoutConstraint *> *bottomSheetConstraints = [NSLayoutConstraint
+ constraintsWithVisualFormat:@"H:|-[presentBottomSheetButton]-|"
+ options:0
+ metrics:nil
+ views:@{@"presentBottomSheetButton" : self.presentBottomSheetButton}];
+ [self.view addConstraints:bottomSheetConstraints];
+
+ NSArray<NSLayoutConstraint *> *componentConstraints = [NSLayoutConstraint
+ constraintsWithVisualFormat:@"V:|-(30)-[containedButton]-(20)-[floatingButton]-(20)-["
+ @"chipView]-(20)-[card(80)]-(20)-[presentBottomSheetButton]"
+ options:NSLayoutFormatAlignAllCenterX
+ metrics:nil
+ views:@{
+ @"containedButton" : self.containedButton,
+ @"floatingButton" : self.floatingButton,
+ @"chipView" : self.chipView,
+ @"card" : self.card,
+ @"presentBottomSheetButton" : self.presentBottomSheetButton
+ }];
+ [self.view addConstraints:componentConstraints];
+}
+
+- (void)presentBottomSheet {
+ BottomSheetDummyCollectionViewController *viewController =
+ [[BottomSheetDummyCollectionViewController alloc] initWithNumItems:102];
+ viewController.title = @"Shaped bottom sheet example";
+
+ MDCAppBarContainerViewController *container =
+ [[MDCAppBarContainerViewController alloc] initWithContentViewController:viewController];
+ container.preferredContentSize = CGSizeMake(500, 200);
+ container.appBarViewController.headerView.trackingScrollView = viewController.collectionView;
+ container.topLayoutGuideAdjustmentEnabled = YES;
+
+ [MDCAppBarColorThemer applyColorScheme:self.colorScheme
+ toAppBarViewController:container.appBarViewController];
+ [MDCAppBarTypographyThemer applyTypographyScheme:self.typographyScheme
+ toAppBarViewController:container.appBarViewController];
+
+ self.bottomSheetController =
+ [[MDCBottomSheetController alloc] initWithContentViewController:container];
+ self.bottomSheetController.trackingScrollView = viewController.collectionView;
+ [self updateComponentShapesWithBaselineOverrides:self.includeBaselineOverridesToggle
+ .selectedSegmentIndex == 0];
+ [self presentViewController:self.bottomSheetController animated:YES completion:nil];
+}
+
+- (UIImage *)faceImage {
+ NSBundle *bundle = [NSBundle bundleForClass:[MDCShapeSchemeExampleViewController class]];
+ UIImage *image = [UIImage imageNamed:@"ic_mask"
+ inBundle:bundle
+ compatibleWithTraitCollection:nil];
+ return image;
+}
+
+- (UIButton *)deleteButton {
+ NSBundle *bundle = [NSBundle bundleForClass:[MDCShapeSchemeExampleViewController class]];
+ UIImage *image = [UIImage imageNamed:@"ic_cancel"
+ inBundle:bundle
+ compatibleWithTraitCollection:nil];
+ image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+
+ UIButton *button = [[UIButton alloc] initWithFrame:CGRectZero];
+ button.tintColor = [UIColor colorWithWhite:0 alpha:0.7f];
+ [button setImage:image forState:UIControlStateNormal];
+
+ return button;
+}
+
+- (void)applySchemeColors {
+ _smallComponentShape.backgroundColor = _colorScheme.primaryColor;
+ _mediumComponentShape.backgroundColor = _colorScheme.primaryColor;
+ _largeComponentShape.backgroundColor = _colorScheme.primaryColor;
+
+ [_smallComponentType setTintColor:_colorScheme.primaryColor];
+ [_mediumComponentType setTintColor:_colorScheme.primaryColor];
+ [_largeComponentType setTintColor:_colorScheme.primaryColor];
+ [_includeBaselineOverridesToggle setTintColor:_colorScheme.primaryColor];
+}
+
+- (void)updateShapeSchemeValues {
+ MDCRectangleShapeGenerator *smallRect =
+ (MDCRectangleShapeGenerator *)_smallComponentShape.shapeGenerator;
+ smallRect.topLeftCorner = _shapeScheme.smallComponentShape.topLeftCorner;
+ smallRect.topRightCorner = _shapeScheme.smallComponentShape.topRightCorner;
+ smallRect.bottomLeftCorner = _shapeScheme.smallComponentShape.bottomLeftCorner;
+ smallRect.bottomRightCorner = _shapeScheme.smallComponentShape.bottomRightCorner;
+ _smallComponentShape.shapeGenerator = smallRect;
+
+ MDCRectangleShapeGenerator *mediumRect =
+ (MDCRectangleShapeGenerator *)_mediumComponentShape.shapeGenerator;
+ mediumRect.topLeftCorner = _shapeScheme.mediumComponentShape.topLeftCorner;
+ mediumRect.topRightCorner = _shapeScheme.mediumComponentShape.topRightCorner;
+ mediumRect.bottomLeftCorner = _shapeScheme.mediumComponentShape.bottomLeftCorner;
+ mediumRect.bottomRightCorner = _shapeScheme.mediumComponentShape.bottomRightCorner;
+ _mediumComponentShape.shapeGenerator = mediumRect;
+
+ MDCRectangleShapeGenerator *largeRect =
+ (MDCRectangleShapeGenerator *)_largeComponentShape.shapeGenerator;
+ largeRect.topLeftCorner = _shapeScheme.largeComponentShape.topLeftCorner;
+ largeRect.topRightCorner = _shapeScheme.largeComponentShape.topRightCorner;
+ largeRect.bottomLeftCorner = _shapeScheme.largeComponentShape.bottomLeftCorner;
+ largeRect.bottomRightCorner = _shapeScheme.largeComponentShape.bottomRightCorner;
+ _largeComponentShape.shapeGenerator = largeRect;
+
+ [self updateComponentShapes];
+}
+
+- (void)updateComponentShapes {
+ [MDCButtonShapeThemer applyShapeScheme:_shapeScheme toButton:self.containedButton];
+ [MDCButtonShapeThemer applyShapeScheme:_shapeScheme toButton:self.outlinedButton];
+ [MDCCardsShapeThemer applyShapeScheme:_shapeScheme toCard:self.card];
+ [MDCButtonShapeThemer applyShapeScheme:_shapeScheme toButton:self.presentBottomSheetButton];
+ [self updateComponentShapesWithBaselineOverrides:self.includeBaselineOverridesToggle
+ .selectedSegmentIndex == 0];
+}
+
+- (MDCShapeCategory *)changedCategoryFromType:(UISegmentedControl *)sender
+ andValue:(UISlider *)slider {
+ MDCShapeCategory *changedCategory;
+ if ([[sender titleForSegmentAtIndex:sender.selectedSegmentIndex] isEqualToString:@"Cut"]) {
+ // Cut Corner
+ changedCategory = [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyCut
+ andSize:slider.value];
+ } else {
+ // Rounded Corner
+ changedCategory = [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyRounded
+ andSize:slider.value];
+ }
+ return changedCategory;
+}
+
+- (IBAction)smallComponentTypeChanged:(UISegmentedControl *)sender {
+ _shapeScheme.smallComponentShape = [self changedCategoryFromType:sender
+ andValue:_smallComponentValue];
+ [self updateShapeSchemeValues];
+}
+
+- (IBAction)smallComponentValueChanged:(UISlider *)sender {
+ _shapeScheme.smallComponentShape = [self changedCategoryFromType:_smallComponentType
+ andValue:sender];
+
+ [self updateShapeSchemeValues];
+}
+
+- (IBAction)mediumComponentTypeChanged:(UISegmentedControl *)sender {
+ _shapeScheme.mediumComponentShape = [self changedCategoryFromType:sender
+ andValue:_mediumComponentValue];
+ [self updateShapeSchemeValues];
+}
+
+- (IBAction)mediumComponentValueChanged:(UISlider *)sender {
+ _shapeScheme.mediumComponentShape = [self changedCategoryFromType:_mediumComponentType
+ andValue:sender];
+
+ [self updateShapeSchemeValues];
+}
+
+- (IBAction)largeComponentTypeChanged:(UISegmentedControl *)sender {
+ _shapeScheme.largeComponentShape = [self changedCategoryFromType:sender
+ andValue:_largeComponentValue];
+ [self updateShapeSchemeValues];
+}
+
+- (IBAction)largeComponentValueChanged:(UISlider *)sender {
+ _shapeScheme.largeComponentShape = [self changedCategoryFromType:_largeComponentType
+ andValue:sender];
+
+ [self updateShapeSchemeValues];
+}
+
+- (IBAction)baselineOverrideValueChanged:(UISegmentedControl *)sender {
+ [self updateComponentShapesWithBaselineOverrides:sender.selectedSegmentIndex == 0];
+}
+
+- (void)updateComponentShapesWithBaselineOverrides:(BOOL)baselineOverrides {
+ if (!baselineOverrides) {
+ // We don't want baseline overrides.
+ [MDCBottomSheetControllerShapeThemerDefaultMapping applyShapeScheme:_shapeScheme
+ toBottomSheetController:self.bottomSheetController];
+ [MDCChipViewShapeThemerDefaultMapping applyShapeScheme:_shapeScheme toChipView:self.chipView];
+ [MDCFloatingButtonShapeThemerDefaultMapping applyShapeScheme:_shapeScheme
+ toButton:self.floatingButton];
+ } else {
+ // We do want baseline overrides.
+ [MDCBottomSheetControllerShapeThemer applyShapeScheme:_shapeScheme
+ toBottomSheetController:self.bottomSheetController];
+ [MDCChipViewShapeThemer applyShapeScheme:_shapeScheme toChipView:self.chipView];
+ [MDCFloatingButtonShapeThemer applyShapeScheme:_shapeScheme toButton:self.floatingButton];
+ }
+}
+
+@end
+
+#pragma mark - Catalog by convention
+@implementation MDCShapeSchemeExampleViewController (CatlogByConvention)
+
++ (NSDictionary *)catalogMetadata {
+ return @{
+ @"breadcrumbs" : @[ @"Shape", @"ShapeScheme" ],
+ @"description" :
+ @"The Shape scheme and theming allows components to be shaped on a theme level",
+ @"primaryDemo" : @YES,
+ @"presentable" : @NO,
+ @"storyboardName" : @"MDCShapeSchemeExampleViewController",
+ };
+}
+
+@end
diff --git a/components/schemes/Shape/examples/resources/MDCShapeSchemeExampleViewController.storyboard b/components/schemes/Shape/examples/resources/MDCShapeSchemeExampleViewController.storyboard
new file mode 100644
index 0000000..013a01b
--- /dev/null
+++ b/components/schemes/Shape/examples/resources/MDCShapeSchemeExampleViewController.storyboard
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="f36-Qf-c8i">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
+ <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--Shape Scheme Example View Controller-->
+ <scene sceneID="IPr-9m-w81">
+ <objects>
+ <viewController id="f36-Qf-c8i" customClass="MDCShapeSchemeExampleViewController" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="ldD-3m-huZ"/>
+ <viewControllerLayoutGuide type="bottom" id="Vjg-mW-28p"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="pMT-E5-noF">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="x2a-ZF-RRz">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <subviews>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BIW-yv-l5w">
+ <rect key="frame" x="5" y="20" width="70" height="75"/>
+ <subviews>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EN7-3m-ITa" customClass="MDCShapedView">
+ <rect key="frame" x="10" y="25" width="50" height="50"/>
+ <color key="backgroundColor" red="0.0" green="0.47058823529999999" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="50" id="ELm-bZ-sm8"/>
+ <constraint firstAttribute="height" constant="50" id="cEn-cl-NQF"/>
+ </constraints>
+ </view>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Small Component" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vc2-XS-Vr0">
+ <rect key="frame" x="10" y="0.0" width="129" height="20"/>
+ <fontDescription key="fontDescription" type="system" pointSize="16"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="EN7-3m-ITa" firstAttribute="top" secondItem="vc2-XS-Vr0" secondAttribute="bottom" constant="5" id="1xj-Hd-6Ns"/>
+ <constraint firstAttribute="bottom" secondItem="EN7-3m-ITa" secondAttribute="bottom" id="3D5-Jm-TJD"/>
+ <constraint firstItem="EN7-3m-ITa" firstAttribute="centerX" secondItem="BIW-yv-l5w" secondAttribute="centerX" id="4oQ-CU-Ei4"/>
+ <constraint firstItem="EN7-3m-ITa" firstAttribute="leading" secondItem="BIW-yv-l5w" secondAttribute="leading" constant="10" id="BE9-aZ-o3G"/>
+ <constraint firstItem="vc2-XS-Vr0" firstAttribute="top" secondItem="BIW-yv-l5w" secondAttribute="top" id="Gus-jE-C3l"/>
+ <constraint firstItem="vc2-XS-Vr0" firstAttribute="leading" secondItem="EN7-3m-ITa" secondAttribute="leading" id="YvE-ez-Vav"/>
+ <constraint firstAttribute="trailing" secondItem="EN7-3m-ITa" secondAttribute="trailing" constant="10" id="j9l-Tc-vtl"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HyU-f3-Nni">
+ <rect key="frame" x="5" y="105" width="100" height="105"/>
+ <subviews>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6U1-M0-YF3" customClass="MDCShapedView">
+ <rect key="frame" x="10" y="25" width="80" height="80"/>
+ <color key="backgroundColor" red="0.0" green="0.47058823529999999" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="80" id="wnn-jN-8cI"/>
+ <constraint firstAttribute="width" constant="80" id="x6V-pL-Ltd"/>
+ </constraints>
+ </view>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Medium Component" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9pE-qc-pKt">
+ <rect key="frame" x="10" y="0.0" width="148" height="20"/>
+ <fontDescription key="fontDescription" type="system" pointSize="16"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="6U1-M0-YF3" firstAttribute="top" secondItem="9pE-qc-pKt" secondAttribute="bottom" constant="5" id="BZW-RZ-jds"/>
+ <constraint firstAttribute="trailing" secondItem="6U1-M0-YF3" secondAttribute="trailing" constant="10" id="R0m-Em-lbJ"/>
+ <constraint firstItem="6U1-M0-YF3" firstAttribute="centerX" secondItem="HyU-f3-Nni" secondAttribute="centerX" id="gLY-J7-te3"/>
+ <constraint firstItem="6U1-M0-YF3" firstAttribute="leading" secondItem="HyU-f3-Nni" secondAttribute="leading" constant="10" id="oNA-vH-eEz"/>
+ <constraint firstItem="9pE-qc-pKt" firstAttribute="leading" secondItem="6U1-M0-YF3" secondAttribute="leading" id="qON-Hf-jKp"/>
+ <constraint firstAttribute="bottom" secondItem="6U1-M0-YF3" secondAttribute="bottom" id="zbp-bE-pGk"/>
+ <constraint firstItem="9pE-qc-pKt" firstAttribute="top" secondItem="HyU-f3-Nni" secondAttribute="top" id="zut-GH-vrx"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TJz-Ai-gH1">
+ <rect key="frame" x="5" y="220" width="140" height="145"/>
+ <subviews>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="o3w-aj-R37" customClass="MDCShapedView">
+ <rect key="frame" x="10" y="25" width="120" height="120"/>
+ <color key="backgroundColor" red="0.0" green="0.47058823529999999" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="120" id="KbA-wE-QyI"/>
+ <constraint firstAttribute="height" constant="120" id="Rs2-av-Krj"/>
+ </constraints>
+ </view>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Large Component" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BSX-RM-iBf">
+ <rect key="frame" x="10" y="0.0" width="131" height="20"/>
+ <fontDescription key="fontDescription" type="system" pointSize="16"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="o3w-aj-R37" firstAttribute="top" secondItem="BSX-RM-iBf" secondAttribute="bottom" constant="5" id="8of-aF-Gof"/>
+ <constraint firstItem="BSX-RM-iBf" firstAttribute="top" secondItem="TJz-Ai-gH1" secondAttribute="top" id="9Xr-Xw-xRy"/>
+ <constraint firstAttribute="trailing" secondItem="o3w-aj-R37" secondAttribute="trailing" constant="10" id="FEn-le-WVX"/>
+ <constraint firstItem="BSX-RM-iBf" firstAttribute="leading" secondItem="o3w-aj-R37" secondAttribute="leading" id="Ur4-z4-Jxg"/>
+ <constraint firstItem="o3w-aj-R37" firstAttribute="leading" secondItem="TJz-Ai-gH1" secondAttribute="leading" constant="10" id="Zoy-B9-ez2"/>
+ <constraint firstAttribute="bottom" secondItem="o3w-aj-R37" secondAttribute="bottom" id="c0u-rW-MOz"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ozm-OE-4QI">
+ <rect key="frame" x="221" y="21" width="149" height="73"/>
+ <subviews>
+ <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="16.5" translatesAutoresizingMaskIntoConstraints="NO" id="QWz-Y7-VXN">
+ <rect key="frame" x="3" y="38" width="143" height="31"/>
+ <connections>
+ <action selector="smallComponentValueChanged:" destination="f36-Qf-c8i" eventType="valueChanged" id="hcD-jh-cPs"/>
+ </connections>
+ </slider>
+ <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="SVL-Sx-e7n">
+ <rect key="frame" x="5" y="5" width="139" height="29"/>
+ <segments>
+ <segment title="Rounded"/>
+ <segment title="Cut"/>
+ </segments>
+ <connections>
+ <action selector="smallComponentTypeChanged:" destination="f36-Qf-c8i" eventType="valueChanged" id="k4B-L4-AkZ"/>
+ </connections>
+ </segmentedControl>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstAttribute="trailing" secondItem="QWz-Y7-VXN" secondAttribute="trailing" constant="5" id="9Qu-FU-bgi"/>
+ <constraint firstItem="QWz-Y7-VXN" firstAttribute="leading" secondItem="ozm-OE-4QI" secondAttribute="leading" constant="5" id="Gwm-mO-ji2"/>
+ <constraint firstItem="SVL-Sx-e7n" firstAttribute="top" secondItem="ozm-OE-4QI" secondAttribute="top" constant="5" id="JUB-Sy-e4E"/>
+ <constraint firstAttribute="trailing" secondItem="SVL-Sx-e7n" secondAttribute="trailing" constant="5" id="PPs-Sn-wA4"/>
+ <constraint firstAttribute="bottom" secondItem="QWz-Y7-VXN" secondAttribute="bottom" constant="5" id="Q52-I1-7K3"/>
+ <constraint firstItem="QWz-Y7-VXN" firstAttribute="top" secondItem="SVL-Sx-e7n" secondAttribute="bottom" constant="5" id="lWD-Ix-mc4"/>
+ <constraint firstItem="SVL-Sx-e7n" firstAttribute="leading" secondItem="ozm-OE-4QI" secondAttribute="leading" constant="5" id="nRG-bE-ll6"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pnw-rO-mOQ">
+ <rect key="frame" x="221" y="256" width="149" height="73"/>
+ <subviews>
+ <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="60" translatesAutoresizingMaskIntoConstraints="NO" id="qgp-VL-aY7">
+ <rect key="frame" x="3" y="38" width="143" height="31"/>
+ <connections>
+ <action selector="largeComponentValueChanged:" destination="f36-Qf-c8i" eventType="valueChanged" id="XTh-5v-XTc"/>
+ </connections>
+ </slider>
+ <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Tpc-oW-UIP">
+ <rect key="frame" x="5" y="5" width="139" height="29"/>
+ <segments>
+ <segment title="Rounded"/>
+ <segment title="Cut"/>
+ </segments>
+ <connections>
+ <action selector="largeComponentTypeChanged:" destination="f36-Qf-c8i" eventType="valueChanged" id="9OU-HA-BGe"/>
+ </connections>
+ </segmentedControl>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="qgp-VL-aY7" firstAttribute="leading" secondItem="pnw-rO-mOQ" secondAttribute="leading" constant="5" id="Gns-Do-nDg"/>
+ <constraint firstAttribute="trailing" secondItem="qgp-VL-aY7" secondAttribute="trailing" constant="5" id="IoH-zY-eIS"/>
+ <constraint firstItem="Tpc-oW-UIP" firstAttribute="top" secondItem="pnw-rO-mOQ" secondAttribute="top" constant="5" id="Swq-LU-sCF"/>
+ <constraint firstItem="Tpc-oW-UIP" firstAttribute="leading" secondItem="pnw-rO-mOQ" secondAttribute="leading" constant="5" id="V2I-c0-du2"/>
+ <constraint firstItem="qgp-VL-aY7" firstAttribute="top" secondItem="Tpc-oW-UIP" secondAttribute="bottom" constant="5" id="VVh-8h-Hri"/>
+ <constraint firstAttribute="bottom" secondItem="qgp-VL-aY7" secondAttribute="bottom" constant="5" id="a59-Uq-UVW"/>
+ <constraint firstAttribute="trailing" secondItem="Tpc-oW-UIP" secondAttribute="trailing" constant="5" id="dCc-wn-lIb"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qjc-FG-EwB">
+ <rect key="frame" x="221" y="121" width="149" height="73"/>
+ <subviews>
+ <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="40" translatesAutoresizingMaskIntoConstraints="NO" id="PRs-2f-WMd">
+ <rect key="frame" x="3" y="38" width="143" height="31"/>
+ <connections>
+ <action selector="mediumComponentValueChanged:" destination="f36-Qf-c8i" eventType="valueChanged" id="ehZ-aK-Jjv"/>
+ </connections>
+ </slider>
+ <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Sd0-HG-VvX">
+ <rect key="frame" x="5" y="5" width="139" height="29"/>
+ <segments>
+ <segment title="Rounded"/>
+ <segment title="Cut"/>
+ </segments>
+ <connections>
+ <action selector="mediumComponentTypeChanged:" destination="f36-Qf-c8i" eventType="valueChanged" id="KF3-Y9-eZb"/>
+ </connections>
+ </segmentedControl>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="PRs-2f-WMd" firstAttribute="top" secondItem="Sd0-HG-VvX" secondAttribute="bottom" constant="5" id="Equ-Pe-h75"/>
+ <constraint firstAttribute="trailing" secondItem="Sd0-HG-VvX" secondAttribute="trailing" constant="5" id="LCm-JE-moQ"/>
+ <constraint firstAttribute="trailing" secondItem="PRs-2f-WMd" secondAttribute="trailing" constant="5" id="YWV-GC-Cae"/>
+ <constraint firstItem="Sd0-HG-VvX" firstAttribute="leading" secondItem="qjc-FG-EwB" secondAttribute="leading" constant="5" id="hX5-Lo-keZ"/>
+ <constraint firstAttribute="bottom" secondItem="PRs-2f-WMd" secondAttribute="bottom" constant="5" id="jz9-Lp-8il"/>
+ <constraint firstItem="Sd0-HG-VvX" firstAttribute="top" secondItem="qjc-FG-EwB" secondAttribute="top" constant="5" id="ucm-Md-rkf"/>
+ <constraint firstItem="PRs-2f-WMd" firstAttribute="leading" secondItem="qjc-FG-EwB" secondAttribute="leading" constant="5" id="x8O-Sh-TQ1"/>
+ </constraints>
+ </view>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Baseline Overrides" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1rN-hK-7E7">
+ <rect key="frame" x="13" y="375" width="144" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="RG0-7W-Hgz">
+ <rect key="frame" x="262" y="371" width="100" height="29"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="100" id="bG3-Sv-SnO"/>
+ </constraints>
+ <segments>
+ <segment title="Yes"/>
+ <segment title="No"/>
+ </segments>
+ <connections>
+ <action selector="baselineOverrideValueChanged:" destination="f36-Qf-c8i" eventType="valueChanged" id="XRO-dn-Fod"/>
+ </connections>
+ </segmentedControl>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GQ0-Wh-yVz">
+ <rect key="frame" x="5" y="404" width="365" height="354"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="354" id="aII-9E-ClL"/>
+ </constraints>
+ </view>
+ </subviews>
+ <constraints>
+ <constraint firstItem="BIW-yv-l5w" firstAttribute="leading" secondItem="x2a-ZF-RRz" secondAttribute="leading" constant="5" id="0SF-Es-vpk"/>
+ <constraint firstAttribute="trailing" secondItem="qjc-FG-EwB" secondAttribute="trailing" constant="5" id="4JW-pf-zKg"/>
+ <constraint firstItem="GQ0-Wh-yVz" firstAttribute="leading" secondItem="x2a-ZF-RRz" secondAttribute="leading" constant="5" id="8KN-4k-9th"/>
+ <constraint firstItem="RG0-7W-Hgz" firstAttribute="centerY" secondItem="1rN-hK-7E7" secondAttribute="centerY" id="9DV-nK-fOv"/>
+ <constraint firstItem="ozm-OE-4QI" firstAttribute="centerY" secondItem="BIW-yv-l5w" secondAttribute="centerY" id="BBe-BD-9LV"/>
+ <constraint firstItem="GQ0-Wh-yVz" firstAttribute="top" secondItem="RG0-7W-Hgz" secondAttribute="bottom" constant="5" id="D22-a4-Owb"/>
+ <constraint firstAttribute="trailingMargin" secondItem="RG0-7W-Hgz" secondAttribute="trailing" constant="5" id="FI4-Oi-cj2"/>
+ <constraint firstItem="pnw-rO-mOQ" firstAttribute="centerY" secondItem="TJz-Ai-gH1" secondAttribute="centerY" id="KyR-bm-aGw"/>
+ <constraint firstAttribute="trailing" secondItem="pnw-rO-mOQ" secondAttribute="trailing" constant="5" id="LPH-NH-70m"/>
+ <constraint firstItem="1rN-hK-7E7" firstAttribute="top" secondItem="TJz-Ai-gH1" secondAttribute="bottom" constant="10" id="LUl-ry-0RF"/>
+ <constraint firstItem="TJz-Ai-gH1" firstAttribute="top" secondItem="HyU-f3-Nni" secondAttribute="bottom" constant="10" id="On4-tC-UsA"/>
+ <constraint firstItem="qjc-FG-EwB" firstAttribute="centerY" secondItem="HyU-f3-Nni" secondAttribute="centerY" id="SA3-AD-55C"/>
+ <constraint firstItem="HyU-f3-Nni" firstAttribute="top" secondItem="BIW-yv-l5w" secondAttribute="bottom" constant="10" id="WXT-8z-br6"/>
+ <constraint firstItem="GQ0-Wh-yVz" firstAttribute="centerX" secondItem="x2a-ZF-RRz" secondAttribute="centerX" id="YvN-wZ-bmK"/>
+ <constraint firstAttribute="bottom" secondItem="GQ0-Wh-yVz" secondAttribute="bottom" constant="20" id="ZdJ-Ey-K6f"/>
+ <constraint firstItem="TJz-Ai-gH1" firstAttribute="leading" secondItem="x2a-ZF-RRz" secondAttribute="leading" constant="5" id="caj-sv-tFn"/>
+ <constraint firstItem="BIW-yv-l5w" firstAttribute="top" secondItem="x2a-ZF-RRz" secondAttribute="top" constant="20" id="en2-K4-PZn"/>
+ <constraint firstItem="HyU-f3-Nni" firstAttribute="leading" secondItem="x2a-ZF-RRz" secondAttribute="leading" constant="5" id="k7m-eY-kDE"/>
+ <constraint firstItem="1rN-hK-7E7" firstAttribute="leading" secondItem="x2a-ZF-RRz" secondAttribute="leadingMargin" constant="5" id="l1a-T8-Y0o"/>
+ <constraint firstAttribute="trailing" secondItem="ozm-OE-4QI" secondAttribute="trailing" constant="5" id="mUY-tQ-Iz3"/>
+ <constraint firstAttribute="trailing" secondItem="GQ0-Wh-yVz" secondAttribute="trailing" constant="5" id="rJ3-r1-Tka"/>
+ </constraints>
+ </scrollView>
+ </subviews>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstAttribute="trailing" secondItem="x2a-ZF-RRz" secondAttribute="trailing" id="SMr-XW-kTN"/>
+ <constraint firstItem="x2a-ZF-RRz" firstAttribute="width" secondItem="pMT-E5-noF" secondAttribute="width" id="X79-gp-Bcr"/>
+ <constraint firstItem="x2a-ZF-RRz" firstAttribute="top" secondItem="pMT-E5-noF" secondAttribute="top" id="hke-5g-ERg"/>
+ <constraint firstItem="x2a-ZF-RRz" firstAttribute="leading" secondItem="pMT-E5-noF" secondAttribute="leading" id="qTn-0F-YRQ"/>
+ <constraint firstAttribute="bottom" secondItem="x2a-ZF-RRz" secondAttribute="bottom" id="tXt-9S-B1t"/>
+ </constraints>
+ </view>
+ <connections>
+ <outlet property="componentContentView" destination="GQ0-Wh-yVz" id="lnb-aC-e0F"/>
+ <outlet property="includeBaselineOverridesToggle" destination="RG0-7W-Hgz" id="6Us-Do-9ps"/>
+ <outlet property="largeComponentShape" destination="o3w-aj-R37" id="xkt-9Q-Pi4"/>
+ <outlet property="largeComponentType" destination="Tpc-oW-UIP" id="8tB-yX-hFH"/>
+ <outlet property="largeComponentValue" destination="qgp-VL-aY7" id="ede-Gx-lUE"/>
+ <outlet property="mediumComponentShape" destination="6U1-M0-YF3" id="2a0-5y-5tT"/>
+ <outlet property="mediumComponentType" destination="Sd0-HG-VvX" id="eCL-89-csV"/>
+ <outlet property="mediumComponentValue" destination="PRs-2f-WMd" id="R9w-PZ-F2k"/>
+ <outlet property="smallComponentShape" destination="EN7-3m-ITa" id="DgN-n9-Eqz"/>
+ <outlet property="smallComponentType" destination="SVL-Sx-e7n" id="4mt-jB-XQr"/>
+ <outlet property="smallComponentValue" destination="QWz-Y7-VXN" id="QcO-zz-0Z8"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="x8v-UI-Lpf" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="-50.399999999999999" y="232.53373313343329"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/components/schemes/Shape/examples/supplemental/MDCBottomSheetControllerShapeThemerDefaultMapping.h b/components/schemes/Shape/examples/supplemental/MDCBottomSheetControllerShapeThemerDefaultMapping.h
new file mode 100644
index 0000000..eed4cc6
--- /dev/null
+++ b/components/schemes/Shape/examples/supplemental/MDCBottomSheetControllerShapeThemerDefaultMapping.h
@@ -0,0 +1,33 @@
+// Copyright 2018-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 <UIKit/UIKit.h>
+
+#import "MaterialBottomSheet+ShapeThemer.h"
+
+/**
+ The Material Design shape system's themer for instances of MDCBottomSheetController.
+ */
+@interface MDCBottomSheetControllerShapeThemerDefaultMapping : MDCBottomSheetControllerShapeThemer
+
+/**
+ Applies a shape scheme's properties to an MDCBottomSheetController.
+
+ @param shapeScheme The shape scheme to apply to the component instance.
+ @param bottomSheetController A component instance to which the shape scheme should be applied.
+ */
++ (void)applyShapeScheme:(nonnull id<MDCShapeScheming>)shapeScheme
+ toBottomSheetController:(nonnull MDCBottomSheetController *)bottomSheetController;
+
+@end
diff --git a/components/schemes/Shape/examples/supplemental/MDCBottomSheetControllerShapeThemerDefaultMapping.m b/components/schemes/Shape/examples/supplemental/MDCBottomSheetControllerShapeThemerDefaultMapping.m
new file mode 100644
index 0000000..e86bac7
--- /dev/null
+++ b/components/schemes/Shape/examples/supplemental/MDCBottomSheetControllerShapeThemerDefaultMapping.m
@@ -0,0 +1,36 @@
+// Copyright 2018-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 "MDCBottomSheetControllerShapeThemerDefaultMapping.h"
+
+@implementation MDCBottomSheetControllerShapeThemerDefaultMapping
+
++ (void)applyShapeScheme:(id<MDCShapeScheming>)shapeScheme
+ toBottomSheetController:(MDCBottomSheetController *)bottomSheetController {
+ // Shape Generator for the Extended state of the Bottom Sheet.
+ MDCRectangleShapeGenerator *rectangleShapeExtended = [[MDCRectangleShapeGenerator alloc] init];
+ // For a Bottom Sheet the corner values that can be set are the top corners.
+ rectangleShapeExtended.topLeftCorner = shapeScheme.largeComponentShape.topLeftCorner;
+ rectangleShapeExtended.topRightCorner = shapeScheme.largeComponentShape.topRightCorner;
+ [bottomSheetController setShapeGenerator:rectangleShapeExtended forState:MDCSheetStateExtended];
+
+ // Shape Generator for the Preferred state of the Bottom Sheet.
+ MDCRectangleShapeGenerator *rectangleShapePreferred = [[MDCRectangleShapeGenerator alloc] init];
+ // For a Bottom Sheet the corner values that can be set are the top corners.
+ rectangleShapePreferred.topLeftCorner = shapeScheme.mediumComponentShape.topLeftCorner;
+ rectangleShapePreferred.topRightCorner = shapeScheme.mediumComponentShape.topRightCorner;
+ [bottomSheetController setShapeGenerator:rectangleShapePreferred forState:MDCSheetStatePreferred];
+}
+
+@end
diff --git a/components/schemes/Shape/examples/supplemental/MDCChipViewShapeThemerDefaultMapping.h b/components/schemes/Shape/examples/supplemental/MDCChipViewShapeThemerDefaultMapping.h
new file mode 100644
index 0000000..ad2f9bb
--- /dev/null
+++ b/components/schemes/Shape/examples/supplemental/MDCChipViewShapeThemerDefaultMapping.h
@@ -0,0 +1,33 @@
+// Copyright 2018-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 <UIKit/UIKit.h>
+
+#import "MaterialChips+ShapeThemer.h"
+
+/**
+ The Material Design shape system's themer for instances of MDCChipView.
+ */
+@interface MDCChipViewShapeThemerDefaultMapping : MDCChipViewShapeThemer
+
+/**
+ Applies a shape scheme's properties to an MDCChipView.
+
+ @param shapeScheme The shape scheme to apply to the component instance.
+ @param chipView A component instance to which the shape scheme should be applied.
+ */
++ (void)applyShapeScheme:(nonnull id<MDCShapeScheming>)shapeScheme
+ toChipView:(nonnull MDCChipView *)chipView;
+
+@end
diff --git a/components/schemes/Shape/examples/supplemental/MDCChipViewShapeThemerDefaultMapping.m b/components/schemes/Shape/examples/supplemental/MDCChipViewShapeThemerDefaultMapping.m
new file mode 100644
index 0000000..f551144
--- /dev/null
+++ b/components/schemes/Shape/examples/supplemental/MDCChipViewShapeThemerDefaultMapping.m
@@ -0,0 +1,29 @@
+// Copyright 2018-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 "MDCChipViewShapeThemerDefaultMapping.h"
+
+@implementation MDCChipViewShapeThemerDefaultMapping
+
++ (void)applyShapeScheme:(nonnull id<MDCShapeScheming>)shapeScheme
+ toChipView:(nonnull MDCChipView *)chipView {
+ MDCRectangleShapeGenerator *rectangleShape = [[MDCRectangleShapeGenerator alloc] init];
+ rectangleShape.topLeftCorner = shapeScheme.smallComponentShape.topLeftCorner;
+ rectangleShape.topRightCorner = shapeScheme.smallComponentShape.topRightCorner;
+ rectangleShape.bottomLeftCorner = shapeScheme.smallComponentShape.bottomLeftCorner;
+ rectangleShape.bottomRightCorner = shapeScheme.smallComponentShape.bottomRightCorner;
+ chipView.shapeGenerator = rectangleShape;
+}
+
+@end
diff --git a/components/schemes/Shape/examples/supplemental/MDCFloatingButtonShapeThemerDefaultMapping.h b/components/schemes/Shape/examples/supplemental/MDCFloatingButtonShapeThemerDefaultMapping.h
new file mode 100644
index 0000000..89967a2
--- /dev/null
+++ b/components/schemes/Shape/examples/supplemental/MDCFloatingButtonShapeThemerDefaultMapping.h
@@ -0,0 +1,33 @@
+// Copyright 2018-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 <UIKit/UIKit.h>
+
+#import "MaterialButtons+ShapeThemer.h"
+
+/**
+ The Material Design shape system's themer for instances of MDCFloatingButton.
+ */
+@interface MDCFloatingButtonShapeThemerDefaultMapping : MDCFloatingButtonShapeThemer
+
+/**
+ Applies a shape scheme's properties to an MDCFloatingButton.
+
+ @param shapeScheme The shape scheme to apply to the component instance.
+ @param button A component instance to which the shape scheme should be applied.
+ */
++ (void)applyShapeScheme:(nonnull id<MDCShapeScheming>)shapeScheme
+ toButton:(nonnull MDCFloatingButton *)button;
+
+@end
diff --git a/components/schemes/Shape/examples/supplemental/MDCFloatingButtonShapeThemerDefaultMapping.m b/components/schemes/Shape/examples/supplemental/MDCFloatingButtonShapeThemerDefaultMapping.m
new file mode 100644
index 0000000..2c870a7
--- /dev/null
+++ b/components/schemes/Shape/examples/supplemental/MDCFloatingButtonShapeThemerDefaultMapping.m
@@ -0,0 +1,29 @@
+// Copyright 2018-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 "MDCFloatingButtonShapeThemerDefaultMapping.h"
+
+@implementation MDCFloatingButtonShapeThemerDefaultMapping
+
++ (void)applyShapeScheme:(nonnull id<MDCShapeScheming>)shapeScheme
+ toButton:(nonnull MDCFloatingButton *)button {
+ MDCRectangleShapeGenerator *rectangleShape = [[MDCRectangleShapeGenerator alloc] init];
+ rectangleShape.topLeftCorner = shapeScheme.smallComponentShape.topLeftCorner;
+ rectangleShape.topRightCorner = shapeScheme.smallComponentShape.topRightCorner;
+ rectangleShape.bottomLeftCorner = shapeScheme.smallComponentShape.bottomLeftCorner;
+ rectangleShape.bottomRightCorner = shapeScheme.smallComponentShape.bottomRightCorner;
+ button.shapeGenerator = rectangleShape;
+}
+
+@end
diff --git a/components/schemes/Shape/src/MDCShapeCategory.h b/components/schemes/Shape/src/MDCShapeCategory.h
index 3e8937c..472827a 100644
--- a/components/schemes/Shape/src/MDCShapeCategory.h
+++ b/components/schemes/Shape/src/MDCShapeCategory.h
@@ -19,11 +19,11 @@
This enum consists of the different types of shape corners.
- MDCShapeCornerFamilyRounded: A rounded corner.
- - MDCShapeCornerFamilyAngled: An angled/cut corner.
+ - MDCShapeCornerFamilyCut: A cut corner.
*/
typedef NS_ENUM(NSInteger, MDCShapeCornerFamily) {
MDCShapeCornerFamilyRounded,
- MDCShapeCornerFamilyAngled,
+ MDCShapeCornerFamilyCut,
};
/**
diff --git a/components/schemes/Shape/src/MDCShapeCategory.m b/components/schemes/Shape/src/MDCShapeCategory.m
index 3a8e837..1c013dc 100644
--- a/components/schemes/Shape/src/MDCShapeCategory.m
+++ b/components/schemes/Shape/src/MDCShapeCategory.m
@@ -26,7 +26,7 @@
if (self = [super init]) {
MDCCornerTreatment *cornerTreatment;
switch (cornerFamily) {
- case MDCShapeCornerFamilyAngled:
+ case MDCShapeCornerFamilyCut:
cornerTreatment = [MDCCornerTreatment cornerWithCut:cornerSize];
break;
case MDCShapeCornerFamilyRounded:
diff --git a/components/schemes/Shape/src/MDCShapeScheme.h b/components/schemes/Shape/src/MDCShapeScheme.h
index bd2ec9d..995657e 100644
--- a/components/schemes/Shape/src/MDCShapeScheme.h
+++ b/components/schemes/Shape/src/MDCShapeScheme.h
@@ -26,19 +26,19 @@
@protocol MDCShapeScheming
/**
- The shape defining the small surfaced components.
+ The shape defining small sized components.
*/
-@property(nonnull, readonly, nonatomic) MDCShapeCategory *smallSurfaceShape;
+@property(nonnull, readonly, nonatomic) MDCShapeCategory *smallComponentShape;
/**
- The shape defining the medium surfaced components.
+ The shape defining medium sized components.
*/
-@property(nonnull, readonly, nonatomic) MDCShapeCategory *mediumSurfaceShape;
+@property(nonnull, readonly, nonatomic) MDCShapeCategory *mediumComponentShape;
/**
- The shape defining the large surfaced components.
+ The shape defining large sized components.
*/
-@property(nonnull, readonly, nonatomic) MDCShapeCategory *largeSurfaceShape;
+@property(nonnull, readonly, nonatomic) MDCShapeCategory *largeComponentShape;
@end
@@ -59,9 +59,9 @@
@interface MDCShapeScheme : NSObject <MDCShapeScheming>
// Redeclare protocol properties as readwrite
-@property(nonnull, readwrite, nonatomic) MDCShapeCategory *smallSurfaceShape;
-@property(nonnull, readwrite, nonatomic) MDCShapeCategory *mediumSurfaceShape;
-@property(nonnull, readwrite, nonatomic) MDCShapeCategory *largeSurfaceShape;
+@property(nonnull, readwrite, nonatomic) MDCShapeCategory *smallComponentShape;
+@property(nonnull, readwrite, nonatomic) MDCShapeCategory *mediumComponentShape;
+@property(nonnull, readwrite, nonatomic) MDCShapeCategory *largeComponentShape;
/**
Initializes the shape scheme with the latest material defaults.
diff --git a/components/schemes/Shape/src/MDCShapeScheme.m b/components/schemes/Shape/src/MDCShapeScheme.m
index 837df1e..236b596 100644
--- a/components/schemes/Shape/src/MDCShapeScheme.m
+++ b/components/schemes/Shape/src/MDCShapeScheme.m
@@ -25,13 +25,13 @@
if (self) {
switch (defaults) {
case MDCShapeSchemeDefaultsMaterial201809:
- _smallSurfaceShape =
+ _smallComponentShape =
[[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyRounded
andSize:4.f];
- _mediumSurfaceShape =
+ _mediumComponentShape =
[[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyRounded
andSize:4.f];
- _largeSurfaceShape =
+ _largeComponentShape =
[[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyRounded
andSize:0.f];
break;
diff --git a/components/schemes/Shape/tests/unit/MDCShapeSchemeTests.m b/components/schemes/Shape/tests/unit/MDCShapeSchemeTests.m
index 2977b23..df32e82 100644
--- a/components/schemes/Shape/tests/unit/MDCShapeSchemeTests.m
+++ b/components/schemes/Shape/tests/unit/MDCShapeSchemeTests.m
@@ -25,8 +25,8 @@
- (void)testShapeCategoryEquality {
// Given
- MDCShapeCategory *cat1 =
- [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyAngled andSize:2.1f];
+ MDCShapeCategory *cat1 = [[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyCut
+ andSize:2.1f];
MDCShapeCategory *cat2 = [[MDCShapeCategory alloc] init];
MDCCornerTreatment *corner =
[MDCCornerTreatment cornerWithCut:2.1f valueType:MDCCornerTreatmentValueTypeAbsolute];
@@ -46,9 +46,9 @@
[[MDCShapeScheme alloc] initWithDefaults:MDCShapeSchemeDefaultsMaterial201809];
// Then
- XCTAssertEqualObjects(initScheme.largeSurfaceShape, mdDefaultScheme.largeSurfaceShape);
- XCTAssertEqualObjects(initScheme.mediumSurfaceShape, mdDefaultScheme.mediumSurfaceShape);
- XCTAssertEqualObjects(initScheme.smallSurfaceShape, mdDefaultScheme.smallSurfaceShape);
+ XCTAssertEqualObjects(initScheme.largeComponentShape, mdDefaultScheme.largeComponentShape);
+ XCTAssertEqualObjects(initScheme.mediumComponentShape, mdDefaultScheme.mediumComponentShape);
+ XCTAssertEqualObjects(initScheme.smallComponentShape, mdDefaultScheme.smallComponentShape);
}
- (void)testInitWithMaterialDefaults {
@@ -57,13 +57,13 @@
[[MDCShapeScheme alloc] initWithDefaults:MDCShapeSchemeDefaultsMaterial201809];
// Then
- XCTAssertEqualObjects(shapeScheme.largeSurfaceShape,
+ XCTAssertEqualObjects(shapeScheme.largeComponentShape,
[[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyRounded
andSize:0.f]);
- XCTAssertEqualObjects(shapeScheme.mediumSurfaceShape,
+ XCTAssertEqualObjects(shapeScheme.mediumComponentShape,
[[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyRounded
andSize:4.f]);
- XCTAssertEqualObjects(shapeScheme.smallSurfaceShape,
+ XCTAssertEqualObjects(shapeScheme.smallComponentShape,
[[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyRounded
andSize:4.f]);
}
diff --git a/contributing/alpha_components.md b/contributing/alpha_components.md
index 0f6e417..29ec274 100644
--- a/contributing/alpha_components.md
+++ b/contributing/alpha_components.md
@@ -12,8 +12,12 @@
any other.
From the point of view of the public, Alpha components are not made available as part of our
-published pod. External clients that wish to use an Alpha component in their app will need to
-manually clone the repo and add the code to their project. This is by design.
+published pod. External clients that wish to use an Alpha component in their Podfile will need to
+manually specify the MaterialComponentsAlpha target and our repo.
+```
+ pod 'MaterialComponentsAlpha', :git => 'https://github.com/material-components/material-components-ios.git'
+```
+When the component graduates to "Ready" clients will need to change their specs to point at the main pod.
Alpha components are not subject to our deprecation policy and we will not provide behavioral flags
for gradual migration of runtime behaviors.
@@ -37,7 +41,7 @@
This component is an [alpha component](../../contributing/alpha_components.md). This means the API is
subject to change without notice and without incrementing major/minor version numbers. To use this
-component, you must manually clone the material-components-ios repo and add the following to your Podfile:
+component add the following to your Podfile:
- pod 'MaterialComponentsAlpha', :path => 'path/to/material-components-ios'
+ pod 'MaterialComponentsAlpha', :path => 'https://github.com/material-components/material-components-ios.git'
```
diff --git a/contributing/releasing.md b/contributing/releasing.md
index fab332d..35d611c 100644
--- a/contributing/releasing.md
+++ b/contributing/releasing.md
@@ -59,6 +59,9 @@
Name the Pull Request title "[WIP] Release Candidate." until you are able to provide the version as the title.
+Add "@Release-blocking clients" to the pull request's reviewers. This is the mechanism by which
+release-blocking clients are notified of a new release.
+
**Do not use GitHub's big green button to merge the approved pull request.** Release are an
exception to our normal squash-and-merge procedure.
@@ -193,7 +196,7 @@
Send our local podspec through the CocoaPods linter:
- pod lib lint MaterialComponents.podspec
+ pod lib lint MaterialComponents.podspec --skip-tests
CocoaPods publishes a directory of publicly available pods through its **trunk** service.
Note: Ensure that you can [push the podspec](#publish-to-cocoapods) later by checking for `MaterialComponents` in your list of available `Pods` when you:
@@ -274,9 +277,11 @@
## Publish to Cocoapods
git checkout stable
- pod trunk push MaterialComponents.podspec
+ pod trunk push MaterialComponents.podspec --skip-tests
## Coordinate with release-blocking clients to finish work
Any work that was started by the [Release-blocking clients](#release-blocking-clients)
(dragon) step above may need to be finalized.
+
+Also follow last instructions in the [internal release instructions](http://go/mdc-releasing)
diff --git a/demos/supplemental/RemoteImageServiceForMDCDemos.podspec b/demos/supplemental/RemoteImageServiceForMDCDemos.podspec
index 2202833..359443a 100644
--- a/demos/supplemental/RemoteImageServiceForMDCDemos.podspec
+++ b/demos/supplemental/RemoteImageServiceForMDCDemos.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "RemoteImageServiceForMDCDemos"
- s.version = "65.0.0"
+ s.version = "66.0.0"
s.summary = "A helper image class for the MDC demos."
s.description = "This spec is made for use in the MDC demos. It gets images via url."
s.homepage = "https://github.com/material-components/material-components-ios"
diff --git a/docs/faq/README.md b/docs/faq/README.md
index 14a1463..01ed134 100644
--- a/docs/faq/README.md
+++ b/docs/faq/README.md
@@ -19,7 +19,7 @@
Roboto is not required for Material Design. The Typography component defaults to using Apple's system font.
-### Will we risk not being featured by Apple anymore?
+### Will we risk not being featured by Apple anymore if we use MDC-iOS?
Apple features good products with good design and apps using MDC-iOS have been featured.
diff --git a/scripts/external/material-motion-apidiff b/scripts/external/material-motion-apidiff
index 7be2232..f896480 160000
--- a/scripts/external/material-motion-apidiff
+++ b/scripts/external/material-motion-apidiff
@@ -1 +1 @@
-Subproject commit 7be2232f454d3836c0620522d1b09ab9b77d6d03
+Subproject commit f896480395a6c67855cde7048078cd42ae0fce21