diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b4e2e03150..15ae95885ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,57 @@ +# 120.0.0 + +In this major release, we deleted the `elevationOverlayColor` property from MDCSemanticColorScheme, added a `placeholderColor` property to MDCTextControls, added a `shapedBorderColor` property and a `shapedBorderWidth` property to MDCShapedView, and made multiple bug fixes. + +## Breaking changes + +### ColorScheme +The `elevationOverlayColor` property has been deleted. + +## New features + +### ShapedView +Added `shapedBorderColor` and `shapedBorderWidth` properties. + +### TextControls +Added `placeholderColor` property. + +## Component changes + +### BottomSheet + +* [Fix bug that was causing messy animation when a keyboard is going to appear after the bottom sheet dismisses.](https://github.com/material-components/material-components-ios/commit/4deaee13215776f82c104e4008c68168f8a62fba) (Alyssa Weiss) + +### NavigationDrawer + +* [Rotation UI Bug Fix This change is a slight alteration to the change introduced in cl/347036858 this moves the added code to the bottom of the method so as to not interfere with the recursive call.](https://github.com/material-components/material-components-ios/commit/6b4b0290a9df02f995f306e96a188b4b80745870) (Nobody) + +### ShadowLayer + +* [Add example for performance testing.](https://github.com/material-components/material-components-ios/commit/8da92053bd494128be6f659dd04c24f95ffa8b74) (Cody Weaver) + +### Shapes + +* [Add properties to configure the border color/width of `MDCShapedView`.](https://github.com/material-components/material-components-ios/commit/2d6db967af07c5805c7ded4cc56a7735a6c6337f) (Darren Mo) + +### Snackbar + +* [Add present+dismiss unit test for legacy snackbar.](https://github.com/material-components/material-components-ios/commit/11e4afa57cb8e59403715aa6bac4ec74788d1462) (Yarden Eitan) +* [Make imports more explicit](https://github.com/material-components/material-components-ios/commit/2158cbeda7e7b30e74d3635e315e707c06ef560a) (Cody Weaver) + +### Tabs + +* [Remove iOS 10 check in accessibilityTrait handling since only iOS 10 + is supported now](https://github.com/material-components/material-components-ios/commit/738a505dacefbb2371b5e0ae04989192eaa56370) (Alyssa Weiss) + +### TextControls + +* [Add placeholderColor property](https://github.com/material-components/material-components-ios/commit/48808bfe67683fbed035a9519be0b958ae9ae714) (Andrew Overton) + +### schemes/Color + +* [Delete elevationOverlayColor: It is not used in any theming extensions.](https://github.com/material-components/material-components-ios/commit/4195a48cca0c55245629f7eecb650ee1d292e635) (Randall Li) + +--- + # 119.5.0 In this minor release, we added a new userDraggingEnabled API to MDCBottomDrawerViewController. diff --git a/MaterialComponents.podspec b/MaterialComponents.podspec index 6fa9977d2ff..f2a42397d9c 100644 --- a/MaterialComponents.podspec +++ b/MaterialComponents.podspec @@ -2,7 +2,7 @@ load 'scripts/generated/icons.rb' Pod::Spec.new do |mdc| mdc.name = "MaterialComponents" - mdc.version = "119.5.0" + mdc.version = "120.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" diff --git a/MaterialComponentsEarlGreyTests.podspec b/MaterialComponentsEarlGreyTests.podspec index 003934941be..a6378ce239a 100644 --- a/MaterialComponentsEarlGreyTests.podspec +++ b/MaterialComponentsEarlGreyTests.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "MaterialComponentsEarlGreyTests" - s.version = "119.5.0" + s.version = "120.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 7fe26d35d49..671c81eee67 100644 --- a/MaterialComponentsExamples.podspec +++ b/MaterialComponentsExamples.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "MaterialComponentsExamples" - s.version = "119.5.0" + s.version = "120.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/MaterialComponentsSnapshotTests.podspec b/MaterialComponentsSnapshotTests.podspec index 3122c153aec..36b50d9e130 100644 --- a/MaterialComponentsSnapshotTests.podspec +++ b/MaterialComponentsSnapshotTests.podspec @@ -53,7 +53,7 @@ end Pod::Spec.new do |s| s.name = "MaterialComponentsSnapshotTests" - s.version = "119.5.0" + s.version = "120.0.0" s.authors = "The Material Components authors." s.summary = "This spec is an aggregate of all the Material Components snapshot tests." s.homepage = "https://github.com/material-components/material-components-ios" diff --git a/VERSION b/VERSION index 9428d873429..57ee5f4db73 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -119.5.0 +120.0.0 diff --git a/catalog/MDCCatalog/Info.plist b/catalog/MDCCatalog/Info.plist index c06b6a2b89c..54ec6ca455b 100644 --- a/catalog/MDCCatalog/Info.plist +++ b/catalog/MDCCatalog/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 119.5.0 + 120.0.0 CFBundleSignature ???? CFBundleVersion - 119.5.0 + 120.0.0 LSRequiresIPhoneOS UIAppFonts diff --git a/catalog/MDCDragons/Info.plist b/catalog/MDCDragons/Info.plist index 1af0398bfca..f925fa87ce7 100644 --- a/catalog/MDCDragons/Info.plist +++ b/catalog/MDCDragons/Info.plist @@ -15,9 +15,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 119.5.0 + 120.0.0 CFBundleVersion - 119.5.0 + 120.0.0 LSRequiresIPhoneOS UILaunchStoryboardName diff --git a/catalog/MaterialCatalog/MaterialCatalog.podspec b/catalog/MaterialCatalog/MaterialCatalog.podspec index 9d2b229c93b..dbb74aca153 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 = "119.5.0" + s.version = "120.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/BottomSheet/src/MDCBottomSheetPresentationController.m b/components/BottomSheet/src/MDCBottomSheetPresentationController.m index cba003e418c..297c4446f40 100644 --- a/components/BottomSheet/src/MDCBottomSheetPresentationController.m +++ b/components/BottomSheet/src/MDCBottomSheetPresentationController.m @@ -17,6 +17,7 @@ #import #import "private/MDCSheetContainerView.h" +#import "MDCBottomSheetController.h" #import "MDCBottomSheetPresentationControllerDelegate.h" #import "MDCSheetContainerViewDelegate.h" #import "MaterialMath.h" @@ -228,6 +229,7 @@ - (void)dismissPresentedControllerIfNecessary:(UITapGestureRecognizer *)tapRecog return; } + self.sheetView.willBeDismissed = YES; id strongDelegate = self.delegate; [self.presentingViewController dismissViewControllerAnimated:YES diff --git a/components/BottomSheet/src/private/MDCSheetContainerView.h b/components/BottomSheet/src/private/MDCSheetContainerView.h index 70482b0a59c..31f2d084d18 100644 --- a/components/BottomSheet/src/private/MDCSheetContainerView.h +++ b/components/BottomSheet/src/private/MDCSheetContainerView.h @@ -22,6 +22,7 @@ @property(nonatomic, weak, nullable) id delegate; @property(nonatomic, readonly) MDCSheetState sheetState; @property(nonatomic) CGFloat preferredSheetHeight; +@property(nonatomic) BOOL willBeDismissed; /** When set to false, the bottom sheet controller can't be dismissed by dragging the sheet down. diff --git a/components/BottomSheet/src/private/MDCSheetContainerView.m b/components/BottomSheet/src/private/MDCSheetContainerView.m index 705e63c85c3..5193092fb95 100644 --- a/components/BottomSheet/src/private/MDCSheetContainerView.m +++ b/components/BottomSheet/src/private/MDCSheetContainerView.m @@ -14,6 +14,7 @@ #import "MDCSheetContainerView.h" +#import "MDCSheetState.h" #import "MDCDraggableView.h" #import "MDCDraggableViewDelegate.h" #import "MDCSheetBehavior.h" @@ -60,6 +61,7 @@ - (instancetype)initWithFrame:(CGRect)frame scrollView:(UIScrollView *)scrollView { self = [super initWithFrame:frame]; if (self) { + self.willBeDismissed = NO; if (UIAccessibilityIsVoiceOverRunning()) { _sheetState = MDCSheetStateExtended; } else { @@ -358,7 +360,12 @@ - (void)sheetBehaviorDidUpdate { - (void)keyboardStateChangedWithNotification:(__unused NSNotification *)notification { if (self.window) { - [self animatePaneWithInitialVelocity:CGPointZero]; + // Only add animation if the view is not set to be dismissed with the new keyboard. Otherwise, + // the view will first adjust height to fit above the keyboard and then dismiss, which appears + // glitchy on the screen. + if (!self.willBeDismissed) { + [self animatePaneWithInitialVelocity:CGPointZero]; + } } } diff --git a/components/LibraryInfo/src/MDCLibraryInfo.m b/components/LibraryInfo/src/MDCLibraryInfo.m index 3c72fcbf3be..36b171c7b42 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 kMDCLibraryInfoVersionString = @"119.5.0"; +static NSString* const kMDCLibraryInfoVersionString = @"120.0.0"; @implementation MDCLibraryInfo diff --git a/components/LibraryInfo/tests/unit/LibraryInfoTests.m b/components/LibraryInfo/tests/unit/LibraryInfoTests.m index cfe6878ebb6..bc78c0dd91e 100644 --- a/components/LibraryInfo/tests/unit/LibraryInfoTests.m +++ b/components/LibraryInfo/tests/unit/LibraryInfoTests.m @@ -26,7 +26,7 @@ - (void)testVersionFormat { // Given // This regex pattern does the following: - // Accept: "119.5.0", etc. + // Accept: "120.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/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m b/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m index feddd349bcd..3d52c524926 100644 --- a/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m +++ b/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m @@ -15,9 +15,11 @@ #import "MDCBottomDrawerContainerViewController.h" #import "MDCBottomDrawerHeader.h" +#import "MDCBottomDrawerState.h" #import "MDCBottomDrawerContainerViewControllerDelegate.h" -#import "MDCBottomDrawerHeaderMask.h" #import "MDCBottomDrawerShadowedView.h" +#import "MaterialShadowElevations.h" +#import "MaterialShadowLayer.h" #import "MaterialApplication.h" #import "MaterialMath.h" #import "MaterialUIMetrics.h" @@ -1099,11 +1101,6 @@ - (void)cacheLayoutCalculationsWithAddedContentHeight:(CGFloat)addedContentHeigh CGFloat scrollingDistance = _contentHeaderTopInset + totalHeight; _contentHeightSurplus = scrollingDistance - containerHeight; - // readded `presentingViewYOffset` because offset is cancelled out - // by being included in both the `scrollingDistance` and `containerHeight`. - // Because `containerHeight` is used in independent calculations - // we can't remove the offset from there. - _contentHeightSurplus += self.presentingViewYOffset; if ([self shouldPresentFullScreen]) { self.drawerState = MDCBottomDrawerStateFullScreen; } else if (_contentHeightSurplus <= 0) { @@ -1116,6 +1113,13 @@ - (void)cacheLayoutCalculationsWithAddedContentHeight:(CGFloat)addedContentHeigh CGFloat addedContentheight = _contentHeaderTopInset - _contentHeightSurplus; [self cacheLayoutCalculationsWithAddedContentHeight:addedContentheight]; } + // Readded `presentingViewYOffset` because offset is cancelled out + // by being included in both the `scrollingDistance` and `containerHeight`. + // Because `containerHeight` is used in independent calculations + // we can't remove the offset from there. + // This y-offset should be readded at the end of this method, this is to prevent it from being + // included in the recursive call in the conditional above. + _contentHeightSurplus += self.presentingViewYOffset; } - (CGFloat)transitionPercentageForContentOffset:(CGPoint)contentOffset diff --git a/components/NavigationDrawer/tests/unit/MDCNavigationDrawerTest.m b/components/NavigationDrawer/tests/unit/MDCNavigationDrawerTest.m index 2d799e16e83..8a28b26389c 100644 --- a/components/NavigationDrawer/tests/unit/MDCNavigationDrawerTest.m +++ b/components/NavigationDrawer/tests/unit/MDCNavigationDrawerTest.m @@ -294,12 +294,6 @@ - (void)testContentHeightSurplusIsAddingYOffset { self.navigationDrawer.headerViewController.preferredContentSize = CGSizeMake(100, 200); self.navigationDrawer.contentViewController.preferredContentSize = CGSizeMake(100, 200); [self.navigationDrawer.presentationController presentationTransitionWillBegin]; - // This will be used to assert the `contentHeightSurplus` The height surplus is calculated by - // adding the content height and the header height. We then add the `presentingViewYOffset`. - // The offset is calculated by subtracting the frame height with the presenting bounds height. - // The presenting view bounds here is 0 and the content and header height get cancelled out in - // the surplus calculation. So the surplus ends up being the frame height - CGFloat frameHeight = CGRectGetHeight(self.navigationDrawer.view.frame); // When self.navigationDrawer.maximumDrawerHeight = 0; @@ -314,7 +308,7 @@ - (void)testContentHeightSurplusIsAddingYOffset { XCTAssertEqual(presentationController.bottomDrawerContainerViewController.maximumDrawerHeight, 0); XCTAssertEqual(presentationController.bottomDrawerContainerViewController.contentHeightSurplus, - frameHeight); + 880); } else { XCTFail(@"The presentation controller should be class of kind " @"MDCBottomDrawerPresentationController but is %@", diff --git a/components/ShadowLayer/examples/MDCShadowPerformanceExample.swift b/components/ShadowLayer/examples/MDCShadowPerformanceExample.swift new file mode 100644 index 00000000000..3e4e40f282a --- /dev/null +++ b/components/ShadowLayer/examples/MDCShadowPerformanceExample.swift @@ -0,0 +1,232 @@ +// Copyright 2020-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 +import MaterialComponents.MaterialAppBar +import MaterialComponents.MaterialAppBar_Theming +import MaterialComponents.MaterialBottomNavigation +import MaterialComponents.MaterialButtons +import MaterialComponents.MaterialButtons_Theming +import MaterialComponents.MaterialCards +import MaterialComponents.MaterialCards_Theming +import MaterialComponents.MaterialShadowElevations +import MaterialComponents.MaterialContainerScheme + +/// An example for testing the performance of `MDCShadowLayer`. This example is not intended to +/// demonstrate how to setup any specific components but rather to push `MDCShadowLayer` to the +/// limits for metric testing. +class MDCShadowPerformanceExample: + UIViewController, + UICollectionViewDelegate, + UICollectionViewDataSource, + UICollectionViewDelegateFlowLayout +{ + + /// Injected `MDCAppBarViewController` so we can render the shadow on it. + lazy var appBar = makeAppBar() + + /// The _plus_ FAB. + let createButton = MDCFloatingButton() + + /// Used to render a _top_ shadow on a component that is pinned to the bottom. + let bottomNavBar = MDCBottomNavigationBar() + + /// Used for styling the sub components based on the app container scheme. + // `@objc` is required for `setupTransition` to work within `MDCDragonsController`. + @objc var containerScheme: MDCContainerScheming = MDCContainerScheme() + + /// The main scroll view content. + let collectionView = UICollectionView( + frame: .zero, + collectionViewLayout: UICollectionViewFlowLayout()) + + /// Number of cells in the `collectionView`. + let cellCount = 200 + + /// Cell reuse identifier. + let cellIdentifier = "Cell" + + /// Padding between cells. + let defaultPadding: CGFloat = 8 + + /// The title of the example + fileprivate static let exampleTitle = "Shadow & Performance" + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = containerScheme.colorScheme.backgroundColor + appBar.headerView.observesTrackingScrollViewScrollEvents = true + appBar.applyPrimaryTheme(withScheme: containerScheme) + appBar.didMove(toParent: self) + appBar.navigationBar.title = MDCShadowPerformanceExample.exampleTitle + + collectionView.dataSource = self + collectionView.delegate = self + collectionView.backgroundColor = containerScheme.colorScheme.backgroundColor + collectionView.alwaysBounceVertical = true + collectionView.register(MDCCardCollectionCell.self, forCellWithReuseIdentifier: cellIdentifier) + collectionView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(collectionView) + view.addSubview(appBar.view) + appBar.headerView.trackingScrollView = collectionView + + createButton.sizeToFit() + let plusImage = UIImage(named: "ic_add") + createButton.setImage(plusImage, for: .normal) + createButton.accessibilityLabel = "Create" + createButton.applySecondaryTheme(withScheme: containerScheme) + view.addSubview(createButton) + + view.addSubview(bottomNavBar) + bottomNavBar.titleVisibility = .always + bottomNavBar.alignment = .centered + let tabBarItem1 = UITabBarItem(title: "Home", image: UIImage(named: "ic_home"), tag: 0) + let tabBarItem2 = + UITabBarItem(title: "Messages", image: UIImage(named: "ic_email"), tag: 1) + bottomNavBar.items = [tabBarItem1, tabBarItem2] + bottomNavBar.selectedItem = tabBarItem2 + } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + let width = view.bounds.width + let height = view.bounds.height + var safeArea: UIEdgeInsets = .zero + if #available(iOS 11.0, *) { + safeArea = view.safeAreaInsets + collectionView.contentInsetAdjustmentBehavior = .always + } + + collectionView.frame = CGRect( + origin: .zero, size: CGSize(width: width, height: height - (safeArea.bottom + safeArea.top))) + + let size = bottomNavBar.sizeThatFits(view.bounds.size) + var bottomNavBarFrame = CGRect( + x: 0, + y: height - size.height, + width: size.width, + height: size.height) + bottomNavBarFrame.size.height += safeArea.bottom + bottomNavBarFrame.origin.y -= safeArea.bottom + bottomNavBar.frame = bottomNavBarFrame + + let createButtonDimension: CGFloat = 56 + let createButtonPadding: CGFloat = 16 + createButton.frame = CGRect( + x: width - (createButtonDimension + safeArea.left + createButtonPadding), + y: bottomNavBarFrame.origin.y - (createButtonDimension + createButtonPadding), + width: createButtonDimension, + height: createButtonDimension + ) + } + + private func makeAppBar() -> MDCAppBarViewController { + let appBarViewController = MDCAppBarViewController() + addChild(appBarViewController) + appBarViewController.headerView.minMaxHeightIncludesSafeArea = false + appBarViewController.inferTopSafeAreaInsetFromViewController = true + appBarViewController.headerView.canOverExtend = false + return appBarViewController + } + + // MARK: Collection View methods + + func collectionView( + _ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath + ) -> UICollectionViewCell { + + let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: cellIdentifier, for: indexPath) + guard let cardCell = cell as? MDCCardCollectionCell else { return cell } + + cardCell.enableRippleBehavior = true + cardCell.isAccessibilityElement = true + cardCell.accessibilityLabel = title + cardCell.setShadowElevation(.cardResting, for: .normal) + cardCell.applyTheme(withScheme: containerScheme) + + return cardCell + } + + func numberOfSections(in collectionView: UICollectionView) -> Int { + return 1 + } + + func collectionView( + _ collectionView: UICollectionView, + numberOfItemsInSection section: Int + ) -> Int { + return cellCount + } + + func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + sizeForItemAt indexPath: IndexPath + ) -> CGSize { + let cardSize = (collectionView.bounds.size.width / 3) - 12 + return CGSize(width: cardSize, height: cardSize) + } + + func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + insetForSectionAt section: Int + ) -> UIEdgeInsets { + return UIEdgeInsets( + top: defaultPadding, + left: defaultPadding, + bottom: defaultPadding, + right: defaultPadding + ) + } + + func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + minimumLineSpacingForSectionAt section: Int + ) -> CGFloat { + return defaultPadding + } + + func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + minimumInteritemSpacingForSectionAt section: Int + ) -> CGFloat { + return defaultPadding + } +} + +// MARK: Catalog by convention +extension MDCShadowPerformanceExample { + @objc class func catalogMetadata() -> [String: Any] { + return [ + "breadcrumbs": ["Shadow", MDCShadowPerformanceExample.exampleTitle], + "primaryDemo": false, + "presentable": true, + "description": """ + This example is not intended to demonstrate how to setup any specific components but rather to + push `MDCShadowLayer` to the limits for metric testing. + """, + ] + } + + @objc func catalogShouldHideNavigation() -> Bool { + return true + } +} diff --git a/components/Shapes/src/MDCShapedView.h b/components/Shapes/src/MDCShapedView.h index 9756d1270e1..82036c3d29b 100644 --- a/components/Shapes/src/MDCShapedView.h +++ b/components/Shapes/src/MDCShapedView.h @@ -43,6 +43,20 @@ */ @property(nonatomic, strong, nullable) IBOutlet id shapeGenerator; +/** + The stroke color of the shape generated by shapeGenerator. + + The default is nil, which results in no stroke being drawn. + */ +@property(nonatomic, copy, nullable) UIColor *shapedBorderColor; + +/** + The stroke width of the shape generated by shapeGenerator. + + The default is 0, which results in no stroke being drawn. + */ +@property(nonatomic, assign) CGFloat shapedBorderWidth; + /** Initializes an MDCShapedView. diff --git a/components/Shapes/src/MDCShapedView.m b/components/Shapes/src/MDCShapedView.m index 1ab396121b8..2774d26ca6e 100644 --- a/components/Shapes/src/MDCShapedView.m +++ b/components/Shapes/src/MDCShapedView.m @@ -65,6 +65,22 @@ - (void)setShapeGenerator:(id)shapeGenerator { return self.layer.shapeGenerator; } +- (UIColor *)shapedBorderColor { + return self.layer.shapedBorderColor; +} + +- (void)setShapedBorderColor:(UIColor *)shapedBorderColor { + self.layer.shapedBorderColor = shapedBorderColor; +} + +- (CGFloat)shapedBorderWidth { + return self.layer.shapedBorderWidth; +} + +- (void)setShapedBorderWidth:(CGFloat)shapedBorderWidth { + self.layer.shapedBorderWidth = shapedBorderWidth; +} + // MDCShapedView captures backgroundColor assigments so that they can be set to the // MDCShapedShadowLayer fillColor. If we don't do this the background of the layer will obscure any // shapes drawn by the shape layer. diff --git a/components/Shapes/tests/snapshot/MDCShapedViewSnapshotTests.m b/components/Shapes/tests/snapshot/MDCShapedViewSnapshotTests.m index e9568292017..5f04e3be75b 100644 --- a/components/Shapes/tests/snapshot/MDCShapedViewSnapshotTests.m +++ b/components/Shapes/tests/snapshot/MDCShapedViewSnapshotTests.m @@ -54,19 +54,18 @@ - (void)generateSnapshotAndVerifyView { - (void)testRectShapedViewWithBorderWidthAndCorrectMaskingOfContent { // Given - MDCShapedShadowLayer *shadowLayer = (MDCShapedShadowLayer *)self.shapedView.layer; MDCRectangleShapeGenerator *shapeGenerator = [[MDCRectangleShapeGenerator alloc] init]; MDCRoundedCornerTreatment *cornerTreatment = [MDCRoundedCornerTreatment cornerWithRadius:50.f]; [shapeGenerator setCorners:cornerTreatment]; - shadowLayer.shapedBorderWidth = 10; - shadowLayer.shapedBorderColor = UIColor.redColor; + self.shapedView.shapedBorderWidth = 10; + self.shapedView.shapedBorderColor = UIColor.redColor; UIView *contentView = [[UIView alloc] initWithFrame:self.shapedView.bounds]; contentView.backgroundColor = UIColor.systemPinkColor; [self.shapedView addSubview:contentView]; // When self.shapedView.shapeGenerator = shapeGenerator; - contentView.layer.mask = shadowLayer.shapeLayer; + contentView.layer.mask = ((MDCShapedShadowLayer *)self.shapedView.layer).shapeLayer; // Then [self generateSnapshotAndVerifyView]; @@ -77,12 +76,12 @@ - (void)testRectShapedViewWithCornerRadiusBySettingABorderWidthToPositiveThenZer MDCRectangleShapeGenerator *shapeGenerator = [[MDCRectangleShapeGenerator alloc] init]; MDCRoundedCornerTreatment *cornerTreatment = [MDCRoundedCornerTreatment cornerWithRadius:50.f]; [shapeGenerator setCorners:cornerTreatment]; - ((MDCShapedShadowLayer *)self.shapedView.layer).shapedBorderWidth = 10; - ((MDCShapedShadowLayer *)self.shapedView.layer).shapedBorderColor = UIColor.redColor; + self.shapedView.shapedBorderWidth = 10; + self.shapedView.shapedBorderColor = UIColor.redColor; // When self.shapedView.shapeGenerator = shapeGenerator; - ((MDCShapedShadowLayer *)self.shapedView.layer).shapedBorderWidth = 0; + self.shapedView.shapedBorderWidth = 0; // Then [self generateSnapshotAndVerifyView]; @@ -93,8 +92,8 @@ - (void)testRectShapedViewWithCornerRadius { MDCRectangleShapeGenerator *shapeGenerator = [[MDCRectangleShapeGenerator alloc] init]; MDCRoundedCornerTreatment *cornerTreatment = [MDCRoundedCornerTreatment cornerWithRadius:50.f]; [shapeGenerator setCorners:cornerTreatment]; - ((MDCShapedShadowLayer *)self.shapedView.layer).shapedBorderWidth = 10; - ((MDCShapedShadowLayer *)self.shapedView.layer).shapedBorderColor = UIColor.redColor; + self.shapedView.shapedBorderWidth = 10; + self.shapedView.shapedBorderColor = UIColor.redColor; // When self.shapedView.shapeGenerator = shapeGenerator; @@ -112,8 +111,8 @@ - (void)testSmallRectShapedViewWithCornerRadiusSameAsBoarderWidth { shapeGenerator.topRightCornerOffset = CGPointMake(-40.f, 40.f); shapeGenerator.bottomLeftCornerOffset = CGPointMake(40.f, -40.f); shapeGenerator.bottomRightCornerOffset = CGPointMake(-40.f, -40.f); - ((MDCShapedShadowLayer *)self.shapedView.layer).shapedBorderWidth = 10; - ((MDCShapedShadowLayer *)self.shapedView.layer).shapedBorderColor = UIColor.redColor; + self.shapedView.shapedBorderWidth = 10; + self.shapedView.shapedBorderColor = UIColor.redColor; // When self.shapedView.shapeGenerator = shapeGenerator; diff --git a/components/Snackbar/tests/unit/MDCSnackbarMessageViewTests.m b/components/Snackbar/tests/unit/MDCSnackbarMessageViewTests.m index f03fa184c4a..1196aa20542 100644 --- a/components/Snackbar/tests/unit/MDCSnackbarMessageViewTests.m +++ b/components/Snackbar/tests/unit/MDCSnackbarMessageViewTests.m @@ -14,13 +14,17 @@ #import +#import "supplemental/MDCFakeMDCSnackbarManagerDelegate.h" +#import "MaterialButtons.h" +#import "MaterialShadowElevations.h" #import "MaterialSnackbar.h" #import "MaterialTypography.h" -#import "supplemental/MDCFakeMDCSnackbarManagerDelegate.h" #import "../../src/private/MDCSnackbarManagerInternal.h" #import "../../src/private/MDCSnackbarOverlayView.h" +static const int64_t kDispatchTimeWait = (int64_t)((CGFloat)0.2 * NSEC_PER_SEC); + @interface MDCSnackbarManagerInternal (Testing) @property(nonatomic) MDCSnackbarMessageView *currentSnackbar; @property(nonatomic) MDCSnackbarOverlayView *overlayView; @@ -523,8 +527,7 @@ - (void)testMessageStaysWhenFocusOnShowIsEnabled { // When [self.manager showMessage:self.message]; XCTestExpectation *expectation = [self expectationWithDescription:@"completed"]; - dispatch_time_t popTime = - dispatch_time(DISPATCH_TIME_NOW, (int64_t)((CGFloat)0.2 * NSEC_PER_SEC)); + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, kDispatchTimeWait); dispatch_after(popTime, dispatch_get_main_queue(), ^{ [expectation fulfill]; }); @@ -562,8 +565,7 @@ - (void)testMessageStaysWhenDurationIsZero { // When [self.manager showMessage:self.message]; XCTestExpectation *expectation = [self expectationWithDescription:@"completed"]; - dispatch_time_t popTime = - dispatch_time(DISPATCH_TIME_NOW, (int64_t)((CGFloat)0.2 * NSEC_PER_SEC)); + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, kDispatchTimeWait); dispatch_after(popTime, dispatch_get_main_queue(), ^{ [expectation fulfill]; }); @@ -605,8 +607,7 @@ - (void)testSettingPresentationHostViewOverrideDisplaysSnackbarInCorrectView { // When [self.manager showMessage:self.message]; XCTestExpectation *expectation = [self expectationWithDescription:@"completed"]; - dispatch_time_t popTime = - dispatch_time(DISPATCH_TIME_NOW, (int64_t)((CGFloat)0.1 * NSEC_PER_SEC)); + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, kDispatchTimeWait); dispatch_after(popTime, dispatch_get_main_queue(), ^{ [expectation fulfill]; }); @@ -690,4 +691,23 @@ - (void)testsnackbarIsPresentingDelegateCalled { [self waitForExpectationsWithTimeout:0.2 handler:nil]; } +- (void)testLegacySnackbarMessagePresentsThenDismisses { + // Given + MDCSnackbarMessage.usesLegacySnackbar = YES; + self.message.duration = 0.1; + + // When + [self.manager showMessage:self.message]; + XCTestExpectation *expectation = [self expectationWithDescription:@"completed"]; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, kDispatchTimeWait); + dispatch_after(popTime, dispatch_get_main_queue(), ^{ + [expectation fulfill]; + }); + [self waitForExpectationsWithTimeout:3 handler:nil]; + + // Then + XCTAssertNil(self.manager.internalManager.currentSnackbar); + MDCSnackbarMessage.usesLegacySnackbar = NO; +} + @end diff --git a/components/Tabs/src/TabBarView/MDCTabBarView.m b/components/Tabs/src/TabBarView/MDCTabBarView.m index 33ed66e366e..90505a3d65f 100644 --- a/components/Tabs/src/TabBarView/MDCTabBarView.m +++ b/components/Tabs/src/TabBarView/MDCTabBarView.m @@ -561,10 +561,7 @@ - (BOOL)isAccessibilityElement { } - (UIAccessibilityTraits)accessibilityTraits { - if (@available(iOS 10.0, *)) { - return [super accessibilityTraits] | UIAccessibilityTraitTabBar; - } - return [super accessibilityTraits]; + return [super accessibilityTraits] | UIAccessibilityTraitTabBar; } #pragma mark - Custom APIs diff --git a/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.h b/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.h index 17ef855203e..b33195f8ecb 100644 --- a/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.h +++ b/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.h @@ -223,4 +223,10 @@ values are allowed. */ @property(nonatomic, strong, nullable) NSString *placeholder; +/** + The color of the placeholder. The default value is the color used by the placeholder in @c + UITextField. + */ +@property(nonatomic, strong, null_resettable) UIColor *placeholderColor; + @end diff --git a/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.m b/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.m index acf4db55ab6..e20c713a87c 100644 --- a/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.m +++ b/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.m @@ -21,7 +21,10 @@ #import "private/MDCBaseTextAreaLayout.h" #import "private/MDCBaseTextAreaTextView.h" #import "MDCBaseTextAreaDelegate.h" +#import "MDCTextControlLabelBehavior.h" +#import "MDCTextControlState.h" #import "MaterialTextControlsPrivate+BaseStyle.h" +#import "MDCTextControlAssistiveLabelDrawPriority.h" #import "MaterialTextControlsPrivate+Shared.h" static char *const kKVOContextMDCBaseTextArea = "kKVOContextMDCBaseTextArea"; @@ -109,6 +112,7 @@ - (void)initializeProperties { self.minimumNumberOfVisibleRows = kMDCBaseTextAreaDefaultMinimumNumberOfVisibleLines; self.maximumNumberOfVisibleRows = kMDCBaseTextAreaDefaultMaximumNumberOfVisibleLines; self.gradientManager = [[MDCTextControlGradientManager alloc] init]; + self.placeholderColor = [self defaultPlaceholderColor]; } - (void)setUpTapGesture { @@ -418,7 +422,7 @@ - (NSAttributedString *)determineAttributedPlaceholder { if ([self shouldPlaceholderBeVisible]) { NSDictionary *attributes = @{ NSParagraphStyleAttributeName : [self defaultPlaceholderParagraphStyle], - NSForegroundColorAttributeName : [self defaultPlaceholderColor], + NSForegroundColorAttributeName : self.placeholderColor, NSFontAttributeName : self.normalFont }; return [[NSAttributedString alloc] initWithString:self.placeholder attributes:attributes]; @@ -529,6 +533,10 @@ - (void)setPlaceholder:(NSString *)placeholder { [self setNeedsLayout]; } +- (void)setPlaceholderColor:(UIColor *)placeholderColor { + _placeholderColor = placeholderColor ?: [self defaultPlaceholderColor]; +} + #pragma mark MDCTextControl Protocol Accessors - (void)setLeadingView:(UIView *)leadingView { diff --git a/components/TextControls/tests/snapshot/MDCBaseTextAreaSnapshotTests.m b/components/TextControls/tests/snapshot/MDCBaseTextAreaSnapshotTests.m index 66c89bce949..8a2de87bd4e 100644 --- a/components/TextControls/tests/snapshot/MDCBaseTextAreaSnapshotTests.m +++ b/components/TextControls/tests/snapshot/MDCBaseTextAreaSnapshotTests.m @@ -107,6 +107,20 @@ - (void)testTextAreaWithLabelAndPlaceholderWhileEditing { [self validateTextArea:textArea]; } +- (void)testTextAreaWithLabelAndCustomColorPlaceholderWhileEditing { + // Given + MDCBaseTextArea *textArea = self.textArea; + + // When + textArea.placeholderColor = [UIColor blueColor]; + textArea.placeholder = @"This is a custom color placeholder."; + textArea.label.text = @"This is a floating label"; + [textArea.textView becomeFirstResponder]; + + // Then + [self validateTextArea:textArea]; +} + - (void)testTextAreaWithArabigLabelAndPlaceholderWhileEditingRTL { // Given MDCBaseTextArea *textArea = self.textArea; diff --git a/components/schemes/Color/src/MDCSemanticColorScheme.h b/components/schemes/Color/src/MDCSemanticColorScheme.h index bd54b78c990..21f7cf02027 100644 --- a/components/schemes/Color/src/MDCSemanticColorScheme.h +++ b/components/schemes/Color/src/MDCSemanticColorScheme.h @@ -75,11 +75,6 @@ */ @property(nonnull, readonly, copy, nonatomic) UIColor *onBackgroundColor; -/** - A color that is used for the elevation overlays, applied with an alpha on top of surfaces. - */ -@property(nonnull, readonly, copy, nonatomic) UIColor *elevationOverlayColor; - /** A flag that indicates whether the overlay color should be applied on an elevated surface in Dark Mode. There is no elevation overlay applied in Light Mode. @@ -123,7 +118,6 @@ typedef NS_ENUM(NSInteger, MDCColorSchemeDefaults) { @property(nonnull, readwrite, copy, nonatomic) UIColor *onSecondaryColor; @property(nonnull, readwrite, copy, nonatomic) UIColor *onSurfaceColor; @property(nonnull, readwrite, copy, nonatomic) UIColor *onBackgroundColor; -@property(nonnull, readwrite, copy, nonatomic) UIColor *elevationOverlayColor; @property(readwrite, assign, nonatomic) BOOL elevationOverlayEnabledForDarkMode; /** diff --git a/components/schemes/Color/src/MDCSemanticColorScheme.m b/components/schemes/Color/src/MDCSemanticColorScheme.m index 049a2f31dca..37cfaace00b 100644 --- a/components/schemes/Color/src/MDCSemanticColorScheme.m +++ b/components/schemes/Color/src/MDCSemanticColorScheme.m @@ -54,7 +54,6 @@ - (instancetype)initWithDefaults:(MDCColorSchemeDefaults)defaults { _onSecondaryColor = ColorFromRGB(0x000000); _onSurfaceColor = ColorFromRGB(0x000000); _onBackgroundColor = ColorFromRGB(0x000000); - _elevationOverlayColor = ColorFromRGB(0x000000); _elevationOverlayEnabledForDarkMode = NO; break; case MDCColorSchemeDefaultsMaterialDark201907: @@ -68,7 +67,6 @@ - (instancetype)initWithDefaults:(MDCColorSchemeDefaults)defaults { _onSecondaryColor = ColorFromRGB(0x000000); _onSurfaceColor = ColorFromRGB(0xFFFFFF); _onBackgroundColor = ColorFromRGB(0xFFFFFF); - _elevationOverlayColor = ColorFromRGB(0xFFFFFF); _elevationOverlayEnabledForDarkMode = YES; break; case MDCColorSchemeDefaultsMaterial201907: { @@ -123,9 +121,6 @@ - (instancetype)initWithDefaults:(MDCColorSchemeDefaults)defaults { defaultColor:ColorFromRGB(0x000000)]; _onBackgroundColor = [UIColor colorWithUserInterfaceStyleDarkColor:ColorFromRGB(0xFFFFFF) defaultColor:ColorFromRGB(0x000000)]; - _elevationOverlayColor = - [UIColor colorWithUserInterfaceStyleDarkColor:ColorFromRGB(0xFFFFFF) - defaultColor:ColorFromRGB(0x000000)]; _elevationOverlayEnabledForDarkMode = YES; break; } diff --git a/components/schemes/Color/tests/unit/MDCSemanticColorSchemeTests.m b/components/schemes/Color/tests/unit/MDCSemanticColorSchemeTests.m index c65eaacc52e..5c42e49e514 100644 --- a/components/schemes/Color/tests/unit/MDCSemanticColorSchemeTests.m +++ b/components/schemes/Color/tests/unit/MDCSemanticColorSchemeTests.m @@ -48,7 +48,6 @@ - (void)testInitMatchesInitWithMaterialDefaults { XCTAssertEqualObjects(initScheme.onSecondaryColor, mdDefaultScheme.onSecondaryColor); XCTAssertEqualObjects(initScheme.onSurfaceColor, mdDefaultScheme.onSurfaceColor); XCTAssertEqualObjects(initScheme.onBackgroundColor, mdDefaultScheme.onBackgroundColor); - XCTAssertEqualObjects(initScheme.elevationOverlayColor, mdDefaultScheme.elevationOverlayColor); XCTAssertEqual(initScheme.elevationOverlayEnabledForDarkMode, mdDefaultScheme.elevationOverlayEnabledForDarkMode); } @@ -69,7 +68,6 @@ - (void)testInitWithMaterialDefaults { XCTAssertEqualObjects(colorScheme.onSecondaryColor, ColorFromRGB(0x000000)); XCTAssertEqualObjects(colorScheme.onSurfaceColor, ColorFromRGB(0x000000)); XCTAssertEqualObjects(colorScheme.onBackgroundColor, ColorFromRGB(0x000000)); - XCTAssertEqualObjects(colorScheme.elevationOverlayColor, ColorFromRGB(0x000000)); XCTAssertEqual(colorScheme.elevationOverlayEnabledForDarkMode, NO); } @@ -89,7 +87,6 @@ - (void)testInitWithMaterialDefaultsDark { XCTAssertEqualObjects(colorScheme.onSecondaryColor, ColorFromRGB(0x000000)); XCTAssertEqualObjects(colorScheme.onSurfaceColor, ColorFromRGB(0xFFFFFF)); XCTAssertEqualObjects(colorScheme.onBackgroundColor, ColorFromRGB(0xFFFFFF)); - XCTAssertEqualObjects(colorScheme.elevationOverlayColor, ColorFromRGB(0xFFFFFF)); XCTAssertEqual(colorScheme.elevationOverlayEnabledForDarkMode, YES); } @@ -134,9 +131,6 @@ - (void)testInitWithMaterialDefaults201907WhenUserInterfaceStyleIsDarkForiOS13 { XCTAssertEqualObjects( [colorScheme.onBackgroundColor resolvedColorWithTraitCollection:traitCollection], ColorFromRGB(0xFFFFFF)); - XCTAssertEqualObjects( - [colorScheme.elevationOverlayColor resolvedColorWithTraitCollection:traitCollection], - ColorFromRGB(0xFFFFFF)); XCTAssertEqual(colorScheme.elevationOverlayEnabledForDarkMode, YES); } #endif // MDC_AVAILABLE_SDK_IOS(13_0) @@ -183,9 +177,6 @@ - (void)testInitWithMaterialDefaults201907WhenUserInterfaceStyleIsLightForiOS13 XCTAssertEqualObjects( [colorScheme.onBackgroundColor resolvedColorWithTraitCollection:traitCollection], ColorFromRGB(0x000000)); - XCTAssertEqualObjects( - [colorScheme.elevationOverlayColor resolvedColorWithTraitCollection:traitCollection], - ColorFromRGB(0x000000)); XCTAssertEqual(colorScheme.elevationOverlayEnabledForDarkMode, YES); } #endif // MDC_AVAILABLE_SDK_IOS(13_0) @@ -209,7 +200,6 @@ - (void)testInitWithMaterialDefaults201907WhenUserInterfaceStyleIsLightForPreiOS XCTAssertEqualObjects(colorScheme.onSecondaryColor, ColorFromRGB(0x000000)); XCTAssertEqualObjects(colorScheme.onSurfaceColor, ColorFromRGB(0x000000)); XCTAssertEqualObjects(colorScheme.onBackgroundColor, ColorFromRGB(0x000000)); - XCTAssertEqualObjects(colorScheme.elevationOverlayColor, ColorFromRGB(0x000000)); XCTAssertEqual(colorScheme.elevationOverlayEnabledForDarkMode, YES); } } @@ -262,9 +252,6 @@ - (void)testInitWithMaterialDefaults201907WhenUserInterfaceStyleIsLightForPreiOS XCTAssertEqualObjects( [colorScheme.onBackgroundColor resolvedColorWithTraitCollection:traitCollection], ColorFromRGB(0xFFFFFF)); - XCTAssertEqualObjects( - [colorScheme.elevationOverlayColor resolvedColorWithTraitCollection:traitCollection], - ColorFromRGB(0xFFFFFF)); XCTAssertEqual(colorScheme.elevationOverlayEnabledForDarkMode, YES); } #endif // MDC_AVAILABLE_SDK_IOS(13_0) @@ -318,9 +305,6 @@ - (void)testInitWithMaterialDefaults201907WhenUserInterfaceStyleIsLightForPreiOS XCTAssertEqualObjects( [colorScheme.onBackgroundColor resolvedColorWithTraitCollection:traitCollection], ColorFromRGB(0x000000)); - XCTAssertEqualObjects( - [colorScheme.elevationOverlayColor resolvedColorWithTraitCollection:traitCollection], - ColorFromRGB(0x000000)); XCTAssertEqual(colorScheme.elevationOverlayEnabledForDarkMode, YES); } #endif // MDC_AVAILABLE_SDK_IOS(13_0) diff --git a/demos/supplemental/RemoteImageServiceForMDCDemos.podspec b/demos/supplemental/RemoteImageServiceForMDCDemos.podspec index 6a2951c8655..c9772dcac16 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 = "119.5.0" + s.version = "120.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"