diff:
@@ -427,6 +427,7 @@ Pod::Spec.new do |mdc|
spec.ios.deployment_target = '8.0'
spec.public_header_files = "components/#{component.base_name}/src/#{spec.base_name}/*.h"
spec.source_files = "components/#{component.base_name}/src/#{spec.base_name}/*.{h,m}"
+ spec.dependency "MaterialComponents/Palettes"
spec.dependency "MaterialComponents/Slider/Component"
spec.dependency "MaterialComponents/Themes"
end

diff:
@param colorScheme The color scheme to apply to MDCSlider.
@param slider A MDCSlider instance to apply a color scheme.
*/
-+ (void)applyColorScheme:(NSObject<MDCColorScheme> *)colorScheme
- toSlider:(MDCSlider *)slider;
++ (void)applyColorScheme:(nonnull NSObject<MDCColorScheme> *)colorScheme
+ toSlider:(nonnull MDCSlider *)slider;
+
+/**
+ * A default color scheme for sliders displayed on light backgrounds. The primary color is blue and
+ * the primary light and primary dark are gray.
+ */
++ (nonnull MDCBasicColorScheme *)defaultSliderLightColorScheme;
+
+/**
+ * A default color scheme for sliders displayed on dark backgrounds. The primary color is blue and
+ * the primary light and primary dark are white.
+ */
++ (nonnull MDCBasicColorScheme *)defaultSliderDarkColorScheme;
+
@end

diff:
*/
#import "MDCSliderColorThemer.h"
+#import "MaterialPalettes.h"
+
+static const CGFloat kSliderThemerLightAlpha = 0.26f;
+static const CGFloat kSliderThemerDarkAlpha = 0.3f;
@implementation MDCSliderColorThemer
toSlider:(MDCSlider *)slider {
slider.trackBackgroundColor = colorScheme.primaryLightColor;
slider.color = colorScheme.primaryColor;
+ slider.disabledColor = colorScheme.primaryDarkColor;
+}
+
+#pragma mark - Default color schemes
+
++ (MDCBasicColorScheme *)defaultSliderLightColorScheme {
+ UIColor *lightTrackOffColor =
+ [[UIColor whiteColor] colorWithAlphaComponent:kSliderThemerLightAlpha];
+ UIColor *lightDisabledColor =
+ [[UIColor whiteColor] colorWithAlphaComponent:kSliderThemerLightAlpha];
+
+ MDCBasicColorScheme *lightScheme =
+ [[MDCBasicColorScheme alloc] initWithPrimaryColor:MDCPalette.bluePalette.tint500
+ primaryLightColor:lightTrackOffColor
+ primaryDarkColor:lightDisabledColor];
+ return lightScheme;
+}
+
++ (MDCBasicColorScheme *)defaultSliderDarkColorScheme {
+ UIColor *darkTrackOffColor =
+ [[UIColor whiteColor] colorWithAlphaComponent:kSliderThemerDarkAlpha];
+ UIColor *darkDisabledColor =
+ [[UIColor whiteColor] colorWithAlphaComponent:kSliderThemerDarkAlpha];
+
+ MDCBasicColorScheme *darkScheme =
+ [[MDCBasicColorScheme alloc] initWithPrimaryColor:MDCPalette.bluePalette.tint500
+ primaryLightColor:darkTrackOffColor
+ primaryDarkColor:darkDisabledColor];
+ return darkScheme;
}
@end

diff:
@@ -48,6 +48,13 @@ IB_DESIGNABLE
*/
@property(nonatomic, strong, null_resettable) UIColor *color;
+/**
+ The color of the cursor (thumb) and track while the slider is disabled.
+
+ Default color is gray.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *disabledColor;
+
/*
The color of the unfilled track that the cursor moves along (right side).

diff:
@@ -98,13 +98,23 @@ static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
- (void)setTrackBackgroundColor:(UIColor *)trackBackgroundColor {
_thumbTrack.trackOffColor =
trackBackgroundColor ? trackBackgroundColor : [[self class] defaultTrackOffColor];
- ;
}
- (UIColor *)trackBackgroundColor {
return _thumbTrack.trackOffColor;
}
+- (void)setDisabledColor:(UIColor *)disabledColor {
+ _thumbTrack.trackDisabledColor =
+ disabledColor ?: [[self class] defaultDisabledColor];
+ _thumbTrack.thumbDisabledColor =
+ disabledColor ?: [[self class] defaultDisabledColor];
+}
+
+- (UIColor *)disabledColor {
+ return _thumbTrack.trackDisabledColor;
+}
+
- (void)setColor:(UIColor *)color {
_thumbTrack.primaryColor = color ? color : [[self class] defaultColor];
}

diff:
@@ -336,6 +336,31 @@ static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
XCTAssertEqualObjects(actualColor, expectedColor);
}
+- (void)testDisabledColor {
+ // Given
+ MDCSlider *slider = [[MDCSlider alloc] init];
+
+ // When
+ UIColor *actualColor = slider.disabledColor;
+
+ // Then
+ UIColor *expectedColor = [[UIColor blackColor] colorWithAlphaComponent:0.26f];
+ XCTAssertEqualObjects(actualColor, expectedColor);
+}
+
+- (void)testDisabledColorNullRestable {
+ // Given
+ MDCSlider *slider = [[MDCSlider alloc] init];
+
+ // When
+ slider.trackBackgroundColor = nil;
+
+ // Then
+ UIColor *actualColor = slider.trackBackgroundColor;
+ UIColor *expectedColor = [[UIColor blackColor] colorWithAlphaComponent:0.26f];
+ XCTAssertEqualObjects(actualColor, expectedColor);
+}
+
#pragma mark numeric value label
- (void)testNumericValueLabelString {

original_message: Create default light and dark color schemes for MDCSlider (#2362)


message:
[ProgressView] Use MDCPalettes for default tint color
* [ProgressView] Use MDCPalettes for default tint color
* Removed unnecessary method
* [ProgressView] Correcting merge mistake.
I accidentally kept it 'sss' instead of 'spec' when I did a web-based update.

change_type: MODIFY

diff:
@@ -391,6 +391,7 @@ Pod::Spec.new do |mdc|
spec.source_files = "components/#{component.base_name}/src/*.{h,m}"
spec.dependency "MDFInternationalization"
+ spec.dependency "MaterialComponents/Palettes"
spec.dependency "MaterialComponents/private/Math"
end
component.subspec "ColorThemer" do |spec|

diff:
#import "MDFInternationalization.h"
#import "MaterialMath.h"
+#import "MaterialPalettes.h"
-// Blue 500 from https://material.io/guidelines/style/color.html#color-color-palette .
-static const uint32_t MDCProgressViewDefaultTintColor = 0x2196F3;
+static inline UIColor *MDCProgressViewDefaultTintColor(void) {
+ return MDCPalette.bluePalette.tint500;
+}
// The ratio by which to desaturate the progress tint color to obtain the default track tint color.
static const CGFloat MDCProgressViewTrackColorDesaturation = 0.3f;
-// Creates a UIColor from a 24-bit RGB color encoded as an integer.
-static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
- return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
- green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
- blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
- alpha:1];
-}
-
static const NSTimeInterval MDCProgressViewAnimationDuration = 0.25;
@interface MDCProgressView ()
@@ -79,7 +73,7 @@ static const NSTimeInterval MDCProgressViewAnimationDuration = 0.25;
_progressView = [[UIView alloc] initWithFrame:CGRectZero];
[self addSubview:_progressView];
- _progressView.backgroundColor = [[self class] defaultProgressTintColor];
+ _progressView.backgroundColor = MDCProgressViewDefaultTintColor();
_trackView.backgroundColor =
[[self class] defaultTrackTintColorForProgressTintColor:_progressView.backgroundColor];
}
@@ -105,7 +99,7 @@ static const NSTimeInterval MDCProgressViewAnimationDuration = 0.25;
- (void)setProgressTintColor:(UIColor *)progressTintColor {
if (progressTintColor == nil) {
- progressTintColor = [[self class] defaultProgressTintColor];
+ progressTintColor = MDCProgressViewDefaultTintColor();
}
self.progressView.backgroundColor = progressTintColor;
}
@@ -264,10 +258,6 @@ static const NSTimeInterval MDCProgressViewAnimationDuration = 0.25;
return UIViewAnimationOptionCurveLinear;
}
-+ (UIColor *)defaultProgressTintColor {
- return MDCColorFromRGB(MDCProgressViewDefaultTintColor);
-}
-
+ (UIColor *)defaultTrackTintColorForProgressTintColor:(UIColor *)progressTintColor {
CGFloat hue, saturation, brightness, alpha;
if ([progressTintColor getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) {

license: Apache License 2.0

original_message:
[ProgressView] Use MDCPalettes for default tint color (#2368)

* [ProgressView] Use MDCPalettes for default tint color

* Removed unnecessary method

* [ProgressView] Correcting merge mistake.

I accidentally kept it 'sss' instead of 'spec' when I did a web-based update.


diff:
@@ -120,15 +120,6 @@ class PageControlSwiftExampleViewController: UIViewController, UIScrollViewDeleg
scrollView.setContentOffset(offset, animated: true)
}
- // Creates a UIColor from a 24-bit RGB color encoded as an integer.
- // Pass in hex color values like so: ColorFromRGB(0x1EAAF1).
- class func ColorFromRGB(_ rgbValue: UInt32) -> UIColor {
- return UIColor.init(red: ((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255,
- green: ((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255,
- blue: ((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255,
- alpha: 1)
- }
-
// MARK: - CatalogByConvention
@objc class func catalogBreadcrumbs() -> [String] {

original_message: [PageControl] Removed unused ColorFromRGB function (#2365)


diff:
@@ -215,6 +215,11 @@ static const CGFloat kSingleCycleRotation =
return CGSizeMake(edge, edge);
}
+- (CGSize)sizeThatFits:(CGSize)size {
+ CGFloat edge = 2 * _radius + _strokeWidth;
+ return CGSizeMake(edge, edge);
+}
+
#pragma mark - Public methods
- (void)startAnimating {

original_message: Implement sizeThatFits on MDCActivityIndicator (#2380)


diff:
@@ -226,6 +226,7 @@ Pod::Spec.new do |mdc|
component.dependency "MaterialComponents/CollectionCells"
component.dependency "MaterialComponents/CollectionLayoutAttributes"
component.dependency "MaterialComponents/Ink"
+ component.dependency "MaterialComponents/Palettes"
component.dependency "MaterialComponents/ShadowElevations"
component.dependency "MaterialComponents/ShadowLayer"
component.dependency "MaterialComponents/Typography"

diff:
#import "MDCCollectionInfoBarView.h"
+#import "MaterialPalettes.h"
#import "MaterialShadowLayer.h"
#import "MaterialTypography.h"
@@ -25,16 +26,12 @@ const CGFloat MDCCollectionInfoBarFooterHeight = 48.0f;
static const CGFloat MDCCollectionInfoBarLabelHorizontalPadding = 16.0f;
-// Colors derived from https://material.io/guidelines/style/color.html#color-color-palette .
-static const uint32_t kCollectionInfoBarBlueColor = 0x448AFF; // Blue A200
-static const uint32_t kCollectionInfoBarRedColor = 0xF44336; // Red 500
+static inline UIColor *CollectionInfoBarBlueColor(void) {
+ return MDCPalette.bluePalette.accent200;
+}
-// Creates a UIColor from a 24-bit RGB color encoded as an integer.
-static inline UIColor *ColorFromRGB(uint32_t rgbValue) {
- return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
- green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
- blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
- alpha:1];
+static inline UIColor *CollectionInfoBarRedColor(void) {
+ return MDCPalette.redPalette.tint500;
}
@interface ShadowedView : UIView
@@ -163,7 +160,7 @@ static inline UIColor *ColorFromRGB(uint32_t rgbValue) {
self.allowsTap = NO;
self.shouldApplyBackgroundViewShadow = NO;
self.textAlignment = NSTextAlignmentLeft;
- self.tintColor = ColorFromRGB(kCollectionInfoBarBlueColor);
+ self.tintColor = CollectionInfoBarBlueColor();
self.titleLabel.textColor = [UIColor whiteColor];
self.autoDismissAfterDuration = 1.0f;
self.backgroundView.alpha = 0.9f;
@@ -172,7 +169,7 @@ static inline UIColor *ColorFromRGB(uint32_t rgbValue) {
self.shouldApplyBackgroundViewShadow = YES;
self.textAlignment = NSTextAlignmentCenter;
self.tintColor = [UIColor whiteColor];
- self.titleLabel.textColor = ColorFromRGB(kCollectionInfoBarRedColor);
+ self.titleLabel.textColor = CollectionInfoBarRedColor();
self.autoDismissAfterDuration = 0.0f;
self.backgroundView.alpha = 1.0f;
self.isAccessibilityElement = YES;

original_message: [Collections] Use MDCPalettes for info bar colors (#2364)


diff:
@@ -429,6 +429,7 @@ Pod::Spec.new do |mdc|
spec.public_header_files = "components/#{component.base_name}/src/*.h"
spec.source_files = "components/#{component.base_name}/src/*.{h,m}", "components/#{component.base_name}/src/private/*.{h,m}"
+ spec.dependency "MaterialComponents/Palettes"
spec.dependency "MaterialComponents/private/ThumbTrack"
end
component.subspec "ColorThemer" do |spec|

diff:
#import "MDCSlider.h"
#import "private/MDCSlider_Subclassable.h"
+#import "MaterialPalettes.h"
#import "MaterialThumbTrack.h"
static const CGFloat kSliderDefaultWidth = 100.0f;
@@ -26,15 +27,8 @@ static const CGFloat kSliderThumbRadius = 6.0f;
static const CGFloat kSliderAccessibilityIncrement = 0.1f; // Matches UISlider's percent increment.
static const CGFloat kSliderLightThemeTrackAlpha = 0.26f;
-// Blue 500 from https://material.io/guidelines/style/color.html#color-color-palette .
-static const uint32_t MDCBlueColor = 0x2196F3;
-
-// Creates a UIColor from a 24-bit RGB color encoded as an integer.
-static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
- return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
- green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
- blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
- alpha:1];
+static inline UIColor *MDCThumbTrackDefaultColor(void) {
+ return MDCPalette.bluePalette.tint500;
}
@interface MDCSlider () <MDCThumbTrackDelegate>
@@ -61,7 +55,7 @@ static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
- (void)commonMDCSliderInit {
_thumbTrack =
- [[MDCThumbTrack alloc] initWithFrame:self.bounds onTintColor:[[self class] defaultColor]];
+ [[MDCThumbTrack alloc] initWithFrame:self.bounds onTintColor:MDCThumbTrackDefaultColor()];
_thumbTrack.delegate = self;
_thumbTrack.disabledTrackHasThumbGaps = YES;
_thumbTrack.trackEndsAreInset = YES;
@@ -116,7 +110,7 @@ static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
}
- (void)setColor:(UIColor *)color {
- _thumbTrack.primaryColor = color ? color : [[self class] defaultColor];
+ _thumbTrack.primaryColor = color ? color : MDCThumbTrackDefaultColor();
}
- (UIColor *)color {
@@ -339,10 +333,6 @@ static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
[self sendActionsForControlEvents:UIControlEventTouchCancel];
}
-+ (UIColor *)defaultColor {
- return MDCColorFromRGB(MDCBlueColor);
-}
-
+ (UIColor *)defaultTrackOffColor {
return [[UIColor blackColor] colorWithAlphaComponent:kSliderLightThemeTrackAlpha];
}

diff:
#import <XCTest/XCTest.h>
+#import "MaterialPalettes.h"
#import "MaterialThumbTrack.h"
#import "MaterialSlider.h"
static const int kNumberOfRepeats = 20;
static const CGFloat kEpsilonAccuracy = 0.001f;
-// Blue 500 from https://material.io/guidelines/style/color.html#color-color-palette .
-static const uint32_t MDCBlueColor = 0x2196F3;
-
-// Creates a UIColor from a 24-bit RGB color encoded as an integer.
-static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
- return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
- green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
- blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
- alpha:1];
-}
-
@interface MDCSlider (TestInterface)
- (NSString *)thumbTrack:(MDCThumbTrack *)thumbTrack stringForValue:(CGFloat)value;
@@ -477,7 +467,7 @@ static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
#pragma mark private test helpers
- (UIColor *)blueColor {
- return MDCColorFromRGB(MDCBlueColor);
+ return MDCPalette.bluePalette.tint500;
}
- (CGFloat)randomNumber {

original_message: [Slider] Use MDCPalettes for default thumb track color (#2369)


diff:
@@ -33,9 +33,9 @@ static const CGFloat kSliderThemerDarkAlpha = 0.3f;
+ (MDCBasicColorScheme *)defaultSliderLightColorScheme {
UIColor *lightTrackOffColor =
- [[UIColor whiteColor] colorWithAlphaComponent:kSliderThemerLightAlpha];
+ [[UIColor blackColor] colorWithAlphaComponent:kSliderThemerLightAlpha];
UIColor *lightDisabledColor =
- [[UIColor whiteColor] colorWithAlphaComponent:kSliderThemerLightAlpha];
+ [[UIColor blackColor] colorWithAlphaComponent:kSliderThemerLightAlpha];
MDCBasicColorScheme *lightScheme =
[[MDCBasicColorScheme alloc] initWithPrimaryColor:MDCPalette.bluePalette.tint500

original_message: Correct colors for slider default light color scheme (#2409)


diff:
@@ -131,4 +131,13 @@ IB_DESIGNABLE
*/
- (void)activityIndicatorAnimationDidFinish:(nonnull MDCActivityIndicator *)activityIndicator;
+/**
+ When setIndicatorMode:animated: is called the spinner animates the transition from the current
+ mode to the new mode. This method is called after the animation completes or immediately if no
+ animation is requested.
+
+ @param activityIndicator Caller
+ */
+- (void)activityIndicatorModeTransitionDidFinish:(nonnull MDCActivityIndicator *)activityIndicator;
+
@end

diff:
@@ -290,6 +290,10 @@ static const CGFloat kSingleCycleRotation =
[self addTransitionToIndeterminateCycle];
break;
}
+ } else {
+ if ([_delegate respondsToSelector:@selector(activityIndicatorModeTransitionDidFinish:)]) {
+ [_delegate activityIndicatorModeTransitionDidFinish:self];
+ }
}
}
@@ -516,6 +520,9 @@ static const CGFloat kSingleCycleRotation =
// Special case for 0% progress.
_cycleCount = nearestCycle;
[self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToIndeterminate];
+ if ([_delegate respondsToSelector:@selector(activityIndicatorModeTransitionDidFinish:)]) {
+ [_delegate activityIndicatorModeTransitionDidFinish:self];
+ }
return;
}
@@ -542,6 +549,9 @@ static const CGFloat kSingleCycleRotation =
[CATransaction setCompletionBlock:^{
[self
strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToIndeterminate];
+ if ([_delegate respondsToSelector:@selector(activityIndicatorModeTransitionDidFinish:)]) {
+ [_delegate activityIndicatorModeTransitionDidFinish:self];
+ }
}];
[CATransaction setDisableActions:YES];
@@ -582,6 +592,9 @@ static const CGFloat kSingleCycleRotation =
_currentProgress = 0.0f;
_lastProgress = _currentProgress;
[self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToDeterminate];
+ if ([_delegate respondsToSelector:@selector(activityIndicatorModeTransitionDidFinish:)]) {
+ [_delegate activityIndicatorModeTransitionDidFinish:self];
+ }
} else {
_currentProgress = MAX(_progress, _minStrokeDifference);
@@ -600,6 +613,9 @@ static const CGFloat kSingleCycleRotation =
[CATransaction setCompletionBlock:^{
[self
strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToDeterminate];
+ if ([_delegate respondsToSelector:@selector(activityIndicatorModeTransitionDidFinish:)]) {
+ [_delegate activityIndicatorModeTransitionDidFinish:self];
+ }
}];
[CATransaction setDisableActions:YES];
[CATransaction mdm_setTimeScaleFactor:@(duration)];

original_message: Add a delegate callback for the activity indicator mode animation (#2537)


change_type: ADD

diff:
+/*
+ Copyright 2016-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 "MaterialActivityIndicator.h"
+#import "MaterialButtons.h"
+
+static const CGFloat kActivityIndicatorExampleArrowHeadSize = 5.0f;
+static const CGFloat kActivityIndicatorExampleStrokeWidth = 2.0f;
+
+static const NSTimeInterval kActivityIndicatorExampleAnimationDuration = 2.0 / 3.0;
+
+
+@interface ActivityIndicatorTransitionExample : UIViewController <MDCActivityIndicatorDelegate>
+@end
+
+@implementation ActivityIndicatorTransitionExample {
+ MDCActivityIndicator *_activityIndicator;
+ MDCButton *_button;
+
+ CALayer *_rotationContainer;
+ CALayer *_refreshArrowContainer;
+ CAShapeLayer *_refreshArrowPoint;
+ CAShapeLayer *_refreshStrokeLayer;
+}
+
+- (id)init {
+ self = [super init];
+ if (self) {
+ self.title = @"Activity Indicator Transition";
+ self.view.backgroundColor = [UIColor whiteColor];
+ }
+ return self;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ _activityIndicator = [[MDCActivityIndicator alloc] initWithFrame:CGRectZero];
+ [_activityIndicator sizeToFit];
+ _activityIndicator.center = CGPointMake(self.view.bounds.size.width / 2, 100);
+ _activityIndicator.delegate = self;
+ [self.view addSubview:_activityIndicator];
+
+ _button = [[MDCButton alloc] init];
+ [_button addTarget:self
+ action:@selector(startRefreshing)
+ forControlEvents:UIControlEventTouchUpInside];
+ [_button setTitle:@"Refresh" forState:UIControlStateNormal];
+ [_button sizeToFit];
+ _button.center = CGPointMake(self.view.bounds.size.width / 2, 200);
+ [self.view addSubview:_button];
+
+ // Layers used in the custom transition animation.
+
+ _rotationContainer = [CALayer layer];
+ [_activityIndicator.layer addSublayer:_rotationContainer];
+
+ _refreshArrowContainer = [CALayer layer];
+ [_rotationContainer addSublayer:_refreshArrowContainer];
+
+ CGMutablePathRef refreshArrowPath = CGPathCreateMutable();
+ CGPathMoveToPoint(refreshArrowPath, NULL, 0, -kActivityIndicatorExampleArrowHeadSize);
+ CGPathAddLineToPoint(refreshArrowPath, NULL, kActivityIndicatorExampleArrowHeadSize, 0);
+ CGPathAddLineToPoint(refreshArrowPath, NULL, 0, kActivityIndicatorExampleArrowHeadSize);
+ CGPathCloseSubpath(refreshArrowPath);
+
+ _refreshArrowPoint = [CAShapeLayer layer];
+ _refreshArrowPoint.anchorPoint = CGPointMake(.5, 1);
+ _refreshArrowPoint.path = refreshArrowPath;
+ [_refreshArrowContainer addSublayer:_refreshArrowPoint];
+
+ CGPathRelease(refreshArrowPath);
+
+ _refreshStrokeLayer = [CAShapeLayer layer];
+ _refreshStrokeLayer.lineWidth = kActivityIndicatorExampleStrokeWidth;
+ _refreshStrokeLayer.fillColor = [UIColor clearColor].CGColor;
+ _refreshStrokeLayer.strokeColor = [UIColor blackColor].CGColor;
+ _refreshStrokeLayer.strokeStart = 0;
+ _refreshStrokeLayer.strokeEnd = .8f;
+ [_rotationContainer addSublayer:_refreshStrokeLayer];
+
+ _rotationContainer.transform = CATransform3DMakeRotation((CGFloat)M_PI * .65f, 0, 0, 1);
+ _refreshArrowContainer.transform = CATransform3DMakeRotation(1.6f * (float)M_PI, 0, 0, 1);
+
+ [CATransaction commit];
+}
+
+- (void)viewWillLayoutSubviews {
+ [super viewWillLayoutSubviews];
+
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES];
+
+ CGRect bounds = _activityIndicator.bounds;
+ _rotationContainer.bounds = bounds;
+ _rotationContainer.position = CGPointMake(bounds.size.width / 2, bounds.size.height / 2);
+
+ _refreshStrokeLayer.bounds = _rotationContainer.bounds;
+ _refreshStrokeLayer.position = _rotationContainer.position;
+
+ _refreshArrowContainer.bounds = _rotationContainer.bounds;
+ _refreshArrowContainer.position = _rotationContainer.position;
+
+ _refreshArrowPoint.position =
+ CGPointMake(bounds.size.width / 2, kActivityIndicatorExampleStrokeWidth / 2.0f);
+
+ CGFloat offsetRadius = _activityIndicator.radius - kActivityIndicatorExampleStrokeWidth / 2.0f;
+ UIBezierPath *strokePath = [UIBezierPath bezierPathWithArcCenter:_refreshStrokeLayer.position
+ radius:offsetRadius
+ startAngle:-1.0f * (CGFloat)M_PI_2
+ endAngle:3.0f * (CGFloat)M_PI_2
+ clockwise:YES];
+ _refreshStrokeLayer.path = strokePath.CGPath;
+
+ [CATransaction commit];
+}
+
+- (void)startRefreshing {
+ _button.enabled = NO;
+
+ MDCActivityIndicatorTransition *transition =
+ [[MDCActivityIndicatorTransition alloc] initWithAnimation:^(CGFloat start, CGFloat end) {
+ [self addFromRefreshIconAnimationsToActivityIndicatorWithStrokeStart:start strokeEnd:end];
+ }];
+ transition.duration = kActivityIndicatorExampleAnimationDuration;
+ transition.completion = ^{
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES];
+ _rotationContainer.hidden = YES;
+ [_refreshArrowContainer removeAllAnimations];
+ [_refreshArrowPoint removeAllAnimations];
+ [CATransaction commit];
+
+ dispatch_time_t stopTime =
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
+ dispatch_after(stopTime, dispatch_get_main_queue(), ^{
+ [self stopRefreshing];
+ });
+ };
+
+ [_activityIndicator startAnimatingWithTransition:transition
+ cycleStartIndex:1];
+}
+
+- (void)stopRefreshing {
+ [_refreshStrokeLayer removeAllAnimations];
+ [_rotationContainer removeAllAnimations];
+
+ MDCActivityIndicatorTransition *transition =
+ [[MDCActivityIndicatorTransition alloc] initWithAnimation:^(CGFloat start, CGFloat end) {
+ [self addToRefreshIconAnimationsFromActivityIndicatorWithStrokeStart:start strokeEnd:end];
+ }];
+ transition.duration = kActivityIndicatorExampleAnimationDuration;
+ transition.completion = ^{
+ _button.enabled = YES;
+ };
+
+ [_activityIndicator stopAnimatingWithTransition:transition];
+}
+
+#pragma mark - Private
+
+- (void)addFromRefreshIconAnimationsToActivityIndicatorWithStrokeStart:(CGFloat)strokeStart
+ strokeEnd:(CGFloat)strokeEnd {
+ // Outer rotation
+ CABasicAnimation *outerRotationAnimation =
+ [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+ outerRotationAnimation.fromValue = @((CGFloat)M_PI * .65f);
+ outerRotationAnimation.toValue = @(strokeEnd * 2 * M_PI);
+ outerRotationAnimation.fillMode = kCAFillModeForwards;
+ outerRotationAnimation.removedOnCompletion = NO;
+ [_rotationContainer addAnimation:outerRotationAnimation forKey:@"transform.rotation.z"];
+
+ CGFloat difference = strokeEnd - strokeStart;
+
+ // Stroke start
+ CABasicAnimation *strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
+ strokeStartAnimation.fromValue = @(0);
+ // Ensure the stroke never disappears by never hitting stroke end's toValue.
+ strokeStartAnimation.toValue = @(1.0f - difference);
+ strokeStartAnimation.fillMode = kCAFillModeBoth;
+ strokeStartAnimation.removedOnCompletion = NO;
+ [_refreshStrokeLayer addAnimation:strokeStartAnimation forKey:@"strokeStart"];
+
+ // Stroke end
+ CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+ strokeEndAnimation.fromValue = @(_refreshStrokeLayer.strokeEnd);
+ strokeEndAnimation.toValue = @(1);
+ strokeEndAnimation.fillMode = kCAFillModeBoth;
+ strokeEndAnimation.removedOnCompletion = NO;
+ [_refreshStrokeLayer addAnimation:strokeEndAnimation forKey:@"strokeEnd"];
+
+ // Refresh arrow rotation and scale
+ CABasicAnimation *refreshArrowRotation =
+ [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+ refreshArrowRotation.fromValue = @(M_PI * 1.6f);
+ refreshArrowRotation.toValue = @(M_PI * 2);
+ refreshArrowRotation.fillMode = kCAFillModeForwards;
+ refreshArrowRotation.removedOnCompletion = NO;
+ [_refreshArrowContainer addAnimation:refreshArrowRotation forKey:@"transform.rotation.z"];
+
+ CABasicAnimation *arrowPointScaleAnimation =
+ [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+ arrowPointScaleAnimation.fromValue = @(1);
+ arrowPointScaleAnimation.toValue = @(0);
+ arrowPointScaleAnimation.fillMode = kCAFillModeForwards;
+ arrowPointScaleAnimation.removedOnCompletion = NO;
+ [_refreshArrowPoint addAnimation:arrowPointScaleAnimation forKey:@"transform.scale"];
+}
+
+- (void)addToRefreshIconAnimationsFromActivityIndicatorWithStrokeStart:(CGFloat)strokeStart
+ strokeEnd:(CGFloat)strokeEnd {
+ // Adjust stroke position to offset outer rotation angle and ensure stroke position is in range
+ // [0,1] for smooth animation
+ strokeStart -= .325f;
+ strokeStart = strokeStart < 0 ? strokeStart + 1 : strokeStart;
+ strokeEnd -= .325f;
+ strokeEnd = strokeEnd < 0 ? strokeEnd + 1 : strokeEnd;
+
+ _rotationContainer.hidden = NO;
+
+ // Stroke start
+ CABasicAnimation *strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
+ strokeStartAnimation.fromValue = @(strokeStart);
+ strokeStartAnimation.toValue = @(0);
+ strokeStartAnimation.fillMode = kCAFillModeBoth;
+ strokeStartAnimation.removedOnCompletion = NO;
+ [_refreshStrokeLayer addAnimation:strokeStartAnimation forKey:@"strokeStart"];
+
+ // Stroke end
+ CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+ strokeEndAnimation.fromValue = @(strokeEnd);
+ strokeEndAnimation.toValue = @(.8f);
+ strokeEndAnimation.fillMode = kCAFillModeBoth;
+ strokeEndAnimation.removedOnCompletion = NO;
+ [_refreshStrokeLayer addAnimation:strokeEndAnimation forKey:@"strokeEnd"];
+
+ // Refresh arrow rotation and scale
+ CABasicAnimation *refreshArrowRotation =
+ [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+ refreshArrowRotation.fromValue = @(strokeStart * 2 * M_PI);
+ refreshArrowRotation.toValue = @(1.6f * M_PI);
+ refreshArrowRotation.fillMode = kCAFillModeForwards;
+ refreshArrowRotation.removedOnCompletion = NO;
+ [_refreshArrowContainer addAnimation:refreshArrowRotation forKey:@"transform.rotation.z"];
+
+ CABasicAnimation *arrowPointScaleAnimation =
+ [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+ arrowPointScaleAnimation.fromValue = @(0);
+ arrowPointScaleAnimation.toValue = @(1);
+ arrowPointScaleAnimation.fillMode = kCAFillModeForwards;
+ arrowPointScaleAnimation.removedOnCompletion = NO;
+ [_refreshArrowPoint addAnimation:arrowPointScaleAnimation forKey:@"transform.scale"];
+}
+
+#pragma mark - Catalog by Convention
+
++ (NSArray *)catalogBreadcrumbs {
+ return @[ @"Activity Indicator", @"Activity Indicator Transition" ];
+}
+
++ (BOOL)catalogIsPrimaryDemo {
+ return NO;
+}
+
++ (BOOL)catalogIsPresentable {
+ return YES;
+}
+
+@end

diff:
#import <UIKit/UIKit.h>
+@class MDCActivityIndicatorTransition;
@protocol MDCActivityIndicatorDelegate;
/**
@@ -109,12 +110,30 @@ IB_DESIGNABLE
*/
- (void)startAnimating;
+/**
+ Starts the animated activity indicator after performing the provided transition. The animation
+ cycle will begin on the cycleStartIndex provided. The startTransition will be applied with the
+ starting and ending positions of the indicator stroke at the moment when the animation will begin
+ taking into account the provided cycleStartIndex in the range [0,1]. The indicatorMode must be
+ MDCActivityIndicatorModeIndeterminate before calling.
+ */
+- (void)startAnimatingWithTransition:(nonnull MDCActivityIndicatorTransition *)startTransition
+ cycleStartIndex:(NSInteger)cycleStartIndex;
+
/**
Stops the animated activity indicator with a short opacity and stroke width animation. Does nothing
if the spinner is not animating.
*/
- (void)stopAnimating;
+/**
+ Stops the animated activity indicator and then performs the provided transition. The provided
+ stopTransition will be called with the starting and ending positions of the indicator stroke at the
+ moment when the animation will begin in the range [0,1]. The indicatorMode must be
+ MDCActivityIndicatorModeIndeterminate before calling.
+ */
+- (void)stopAnimatingWithTransition:(nonnull MDCActivityIndicatorTransition *)stopTransition;
+
@end
/**
@@ -141,3 +160,38 @@ IB_DESIGNABLE
- (void)activityIndicatorModeTransitionDidFinish:(nonnull MDCActivityIndicator *)activityIndicator;
@end
+
+typedef void (^MDCActivityIndicatorAnimation)(CGFloat strokeStart, CGFloat strokeEnd);
+
+/**
+ Describes an animation that can be provided to an MDCActivityIndicator instance to perform before
+ or after its standard cycle animation.
+ */
+@interface MDCActivityIndicatorTransition : NSObject
+
+/**
+ The animations to be performed by MDCActivityIndicator. In this block add CAAnimations to be
+ animated before or after MDCActivityIndicator's cycle animation. MDCActivityIndicator will trigger
+ these animations and call completion after they complete.
+ */
+@property(nonatomic, copy, nonnull) MDCActivityIndicatorAnimation animation;
+
+/**
+ The completion block to call after animation's completion. This should be used to clean up any
+ layers placed and animating on the MDCActivityIndicator.
+ */
+@property(nonatomic, copy, nullable) void (^completion)(void);
+
+/**
+ The duration of the animation.
+ */
+@property(nonatomic, assign) NSTimeInterval duration;
+
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+- (nonnull instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
+
+- (nonnull instancetype)initWithAnimation:
+ (_Nonnull MDCActivityIndicatorAnimation)animation NS_DESIGNATED_INITIALIZER;
+
+@end

diff:
@@ -95,6 +95,12 @@ static const CGFloat kSingleCycleRotation =
*/
@property(nonatomic, strong, readonly, nullable) CAShapeLayer *trackLayer;
+/**
+ The currently queued stop transition, which will be run as soon as the current animation cycle
+ completes. At all other times should be nil.
+ */
+@property(nonatomic, strong, nullable) MDCActivityIndicatorTransition *stopTransition;
+
@end
@implementation MDCActivityIndicator {
@@ -236,9 +242,73 @@ static const CGFloat kSingleCycleRotation =
_animating = YES;
- if (self.window && !_backgrounded) {
+ if (!self.window || _backgrounded) {
+ return;
+ }
+
+ [self actuallyStartAnimating];
+}
+
+- (void)startAnimatingWithTransition:(nonnull MDCActivityIndicatorTransition *)startTransition
+ cycleStartIndex:(NSInteger)cycleStartIndex {
+ if (_animating) {
+ return;
+ }
+
+ BOOL indeterminate = self.indicatorMode == MDCActivityIndicatorModeIndeterminate;
+ NSAssert(indeterminate, @"startAnimatingWithStartAnimation requires an indeterminate mode.");
+ if (!indeterminate) {
+ return;
+ }
+
+ if (_animatingOut) {
+ if ([_delegate respondsToSelector:@selector(activityIndicatorAnimationDidFinish:)]) {
+ [_delegate activityIndicatorAnimationDidFinish:self];
+ }
+ [self removeAnimations];
+ }
+
+ _animating = YES;
+
+ if (!self.window || _backgrounded) {
+ return;
+ }
+
+ _cycleStartIndex = cycleStartIndex;
+ _cycleCount = _cycleStartIndex;
+
+ _animationInProgress = YES;
+
+ [CATransaction begin];
+ {
+ [CATransaction setCompletionBlock:^{
+ _animationInProgress = NO;
+
[self actuallyStartAnimating];
+
+ _cycleColorsIndex = self.cycleColors.count > 0 ? cycleStartIndex % self.cycleColors.count : 0;
+ [self applyPropertiesWithoutAnimation:^{
+ [self updateStrokeColor];
+ }];
+
+ if (startTransition.completion) {
+ startTransition.completion();
+ }
+ }];
+ [CATransaction setAnimationDuration:startTransition.duration];
+ [CATransaction setDisableActions:YES];
+
+ CGFloat outerRotation = kOuterRotationIncrement * _cycleStartIndex;
+ CGFloat innerRotation = _cycleStartIndex * (CGFloat)M_PI;
+ CGFloat strokeStart =
+ (CGFloat)fmod(innerRotation + outerRotation, 2 * M_PI) / (CGFloat)(2 * M_PI);
+
+ CGFloat strokeEnd = _minStrokeDifference + strokeStart;
+ strokeEnd = strokeEnd > 1 ? strokeEnd - 1 : strokeEnd;
+
+ startTransition.animation(strokeStart, strokeEnd);
}
+ [CATransaction commit];
}
- (void)stopAnimating {
@@ -251,6 +321,23 @@ static const CGFloat kSingleCycleRotation =
[self animateOut];
}
+- (void)stopAnimatingWithTransition:(MDCActivityIndicatorTransition *)stopTransition {
+ if (!_animating) {
+ return;
+ }
+
+ BOOL indeterminate = self.indicatorMode == MDCActivityIndicatorModeIndeterminate;
+ NSAssert(indeterminate, @"stopAnimationWithTransition requires an indeterminate mode.");
+ if (!indeterminate) {
+ return;
+ }
+
+ _animating = NO;
+ _animatingOut = YES;
+
+ self.stopTransition = stopTransition;
+}
+
- (void)stopAnimatingImmediately {
if (!_animating) {
return;
@@ -290,7 +377,7 @@ static const CGFloat kSingleCycleRotation =
[self addTransitionToIndeterminateCycle];
break;
}
- } else {
+ } else if (!_animating) {
if ([_delegate respondsToSelector:@selector(activityIndicatorModeTransitionDidFinish:)]) {
[_delegate activityIndicatorModeTransitionDidFinish:self];
}
@@ -428,6 +515,47 @@ static const CGFloat kSingleCycleRotation =
}
}
+- (void)addStopAnimation {
+ MDCActivityIndicatorTransition *stopTransition = self.stopTransition;
+
+ CGFloat innerRotation =
+ [[_strokeLayer valueForKeyPath:MDMKeyPathRotation] floatValue];
+ CGFloat outerRotation =
+ [[_outerRotationLayer valueForKeyPath:MDMKeyPathRotation] floatValue];
+ CGFloat totalRotation =
+ (CGFloat)fmod(innerRotation + outerRotation, 2 * M_PI) / (CGFloat)(2 * M_PI);
+
+ CGFloat strokeStart = _strokeLayer.strokeStart + totalRotation;
+ strokeStart = strokeStart > 1 ? strokeStart - 1 : strokeStart;
+
+ CGFloat strokeEnd = _strokeLayer.strokeEnd + totalRotation;
+ strokeEnd = strokeEnd > 1 ? strokeEnd - 1 : strokeEnd;
+
+ [self applyPropertiesWithoutAnimation:^{
+ _strokeLayer.strokeStart = 0.0f;
+ _strokeLayer.strokeEnd = 0.0f;
+ }];
+
+ [CATransaction begin];
+ {
+ [CATransaction setCompletionBlock:^{
+ if (stopTransition.completion) {
+ stopTransition.completion();
+ }
+ if (stopTransition == self.stopTransition) {
+ if ([_delegate respondsToSelector:@selector(activityIndicatorAnimationDidFinish:)]) {
+ [_delegate activityIndicatorAnimationDidFinish:self];
+ }
+ [self removeAnimations];
+ }
+ }];
+ [CATransaction setAnimationDuration:stopTransition.duration];
+ [CATransaction setDisableActions:YES];
+ stopTransition.animation(strokeStart, strokeEnd);
+ }
+ [CATransaction commit];
+}
+
- (void)updateStrokePath {
CGFloat offsetRadius = _radius - _strokeLayer.lineWidth / 2.0f;
UIBezierPath *strokePath = [UIBezierPath bezierPathWithArcCenter:_strokeLayer.position
@@ -683,6 +811,12 @@ static const CGFloat kSingleCycleRotation =
if (!_animationsAdded) {
return;
}
+
+ if (self.stopTransition) {
+ [self addStopAnimation];
+ return;
+ }
+
if (state == MDCActivityIndicatorStateIndeterminate) {
if (self.cycleColors.count > 0) {
self.cycleColorsIndex = (self.cycleColorsIndex + 1) % self.cycleColors.count;
@@ -760,6 +894,7 @@ static const CGFloat kSingleCycleRotation =
- (void)removeAnimations {
_animationsAdded = NO;
_animatingOut = NO;
+ self.stopTransition = nil;
[_strokeLayer removeAllAnimations];
[_outerRotationLayer removeAllAnimations];
@@ -871,3 +1006,13 @@ static const CGFloat kSingleCycleRotation =
}
@end
+
+@implementation MDCActivityIndicatorTransition
+- (nonnull instancetype)initWithAnimation:(_Nonnull MDCActivityIndicatorAnimation)animation {
+ self = [super init];
+ if (self) {
+ self.animation = animation;
+ }
+ return self;
+}
+@end

original_message: Add an api to MDCActivityIndicator to allow animations before/after animating (#2766)


message: Fixing Implicit Self inside blocks.

diff:
@@ -141,9 +141,9 @@ static const NSTimeInterval kActivityIndicatorExampleAnimationDuration = 2.0 / 3
transition.completion = ^{
[CATransaction begin];
[CATransaction setDisableActions:YES];
- _rotationContainer.hidden = YES;
- [_refreshArrowContainer removeAllAnimations];
- [_refreshArrowPoint removeAllAnimations];
+ self->_rotationContainer.hidden = YES;
+ [self->_refreshArrowContainer removeAllAnimations];
+ [self->_refreshArrowPoint removeAllAnimations];
[CATransaction commit];
dispatch_time_t stopTime =
@@ -167,7 +167,7 @@ static const NSTimeInterval kActivityIndicatorExampleAnimationDuration = 2.0 / 3
}];
transition.duration = kActivityIndicatorExampleAnimationDuration;
transition.completion = ^{
- _button.enabled = YES;
+ self->_button.enabled = YES;
};
[_activityIndicator stopAnimatingWithTransition:transition];

diff:
delay:0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
- _scrollView.contentOffset = offset;
+ self->_scrollView.contentOffset = offset;
}
completion:nil];
}

original_message: Fixing Implicit Self inside blocks. (#2954)


message: Fix new collaborator issues link

diff:
@@ -53,7 +53,7 @@ Occasionally it is necessary to hotfix the framework. See [hotfixing.md](hotfixi
## Finding an issue to work on
MDC-iOS uses GitHub to file and track issues.
-To find an issue to work on, filter the issues list by the ["is:New Collaborator Friendly" label](https://github.com/material-components/material-components-ios/labels/is%3ANew%20Collaborator%20Friendly).
+To find an issue to work on, filter the issues list by the ["is:fixit" label](https://github.com/material-components/material-components-ios/labels/is%3Afixit).
## The small print

original_message: Fix new collaborator issues link (#2978)


diff:
@@ -76,7 +76,8 @@ static const CGFloat MDCTextInputEditingRectRightViewPaddingCorrection = -2.f;
NSString *interfaceBuilderPlaceholder = super.placeholder;
if ([aDecoder containsValueForKey:MDCTextFieldFundamentKey]) {
- _fundament = [aDecoder decodeObjectForKey:MDCTextFieldFundamentKey];
+ _fundament = [aDecoder decodeObjectOfClass:[MDCTextInputCommonFundament class]
+ forKey:MDCTextFieldFundamentKey];
} else {
_fundament = [[MDCTextInputCommonFundament alloc] initWithTextInput:self];
}

diff:
@@ -73,9 +73,12 @@ static inline NSString *_Nullable MDCNSStringFromCGLineJoin(CGLineJoin lineJoin)
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
- _borderFillColor = [coder decodeObjectForKey:MDCTextInputBorderViewBorderFillColorKey];
- _borderPath = [coder decodeObjectForKey:MDCTextInputBorderViewBorderPathKey];
- _borderStrokeColor = [coder decodeObjectForKey:MDCTextInputBorderViewBorderStrokeColorKey];
+ _borderFillColor = [coder decodeObjectOfClass:[UIColor class]
+ forKey:MDCTextInputBorderViewBorderFillColorKey];
+ _borderPath = [coder decodeObjectOfClass:[UIBezierPath class]
+ forKey:MDCTextInputBorderViewBorderPathKey];
+ _borderStrokeColor = [coder decodeObjectOfClass:[UIColor class]
+ forKey:MDCTextInputBorderViewBorderStrokeColorKey];
[self commonMDCTextInputBorderViewInit];
}
return self;

diff:
@@ -159,16 +159,20 @@ static inline UIColor *MDCTextInputUnderlineColor() {
if (self) {
[self commonMDCTextInputCommonFundamentInit];
- _borderPath = [aDecoder decodeObjectForKey:MDCTextInputFundamentBorderPathKey];
- _borderView = [aDecoder decodeObjectForKey:MDCTextInputFundamentBorderViewKey];
- _clearButton = [aDecoder decodeObjectForKey:MDCTextInputFundamentClearButtonKey];
+ _borderPath = [aDecoder decodeObjectOfClass:[UIBezierPath class]
+ forKey:MDCTextInputFundamentBorderPathKey];
+ _borderView = [aDecoder decodeObjectOfClass:[MDCTextInputBorderView class]
+ forKey:MDCTextInputFundamentBorderViewKey];
+ _clearButton = [aDecoder decodeObjectOfClass:[UIButton class]
+ forKey:MDCTextInputFundamentClearButtonKey];
_hidesPlaceholderOnInput = [aDecoder decodeBoolForKey:MDCTextInputFundamentHidesPlaceholderKey];
- _leadingUnderlineLabel = [aDecoder decodeObjectForKey:MDCTextInputFundamentLeadingLabelKey];
+ _leadingUnderlineLabel = [aDecoder decodeObjectOfClass:[UILabel class]
+ forKey:MDCTextInputFundamentLeadingLabelKey];
_mdc_adjustsFontForContentSizeCategory =
[aDecoder decodeBoolForKey:MDCTextInputFundamentMDCAdjustsFontsKey];
_placeholderLabel = [aDecoder decodeObjectOfClass:[UILabel class]
forKey:MDCTextInputFundamentPlaceholderLabelKey];
- _textInput = [aDecoder decodeObjectOfClass:[UIView<MDCTextInput> class]
+ _textInput = [aDecoder decodeObjectOfClass:[UIView class]
forKey:MDCTextInputFundamentTextInputKey];
_textColor =
[aDecoder decodeObjectOfClass:[UIColor class] forKey:MDCTextInputFundamentTextColorKey];

original_message: Adding secure coding for all MDCTextfield and properties of it. (#2990)


message: ChipView class check for encoding.

diff:
@@ -230,26 +230,34 @@ static inline CGSize CGSizeShrinkWithInsets(CGSize size, UIEdgeInsets edgeInsets
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
- _imageView = [aDecoder decodeObjectForKey:MDCChipImageViewKey];
- _selectedImageView = [aDecoder decodeObjectForKey:MDCChipSelectedImageViewKey];
- _titleLabel = [aDecoder decodeObjectForKey:MDCChipTitleLabelKey];
- _accessoryView = [aDecoder decodeObjectForKey:MDCChipAccessoryViewKey];
+ _imageView = [aDecoder decodeObjectOfClass:[UIImageView class] forKey:MDCChipImageViewKey];
+ _selectedImageView = [aDecoder decodeObjectOfClass:[UIImageView class]
+ forKey:MDCChipSelectedImageViewKey];
+ _titleLabel = [aDecoder decodeObjectOfClass:[UILabel class] forKey:MDCChipTitleLabelKey];
+ _accessoryView = [aDecoder decodeObjectOfClass:[UIView class] forKey:MDCChipAccessoryViewKey];
_contentPadding = [aDecoder decodeUIEdgeInsetsForKey:MDCChipContentPaddingKey];
_imagePadding = [aDecoder decodeUIEdgeInsetsForKey:MDCChipImagePaddingKey];
_titlePadding = [aDecoder decodeUIEdgeInsetsForKey:MDCChipTitlePaddingKey];
_accessoryPadding = [aDecoder decodeUIEdgeInsetsForKey:MDCChipAccessoryPaddingKey];
- _inkView = [aDecoder decodeObjectForKey:MDCChipInkViewKey];
-
- _backgroundColors = [aDecoder decodeObjectForKey:MDCChipBackgroundColorsKey];
- _borderColors = [aDecoder decodeObjectForKey:MDCChipBorderColorsKey];
- _borderWidths = [aDecoder decodeObjectForKey:MDCChipBorderWidthsKey];
- _elevations = [aDecoder decodeObjectForKey:MDCChipElevationsKey];
- _inkColors = [aDecoder decodeObjectForKey:MDCChipInkColorsKey];
- _shadowColors = [aDecoder decodeObjectForKey:MDCChipShadowColorsKey];
- _titleFont = [aDecoder decodeObjectForKey:MDCChipTitleFontKey];
- _titleColors = [aDecoder decodeObjectForKey:MDCChipTitleColorsKey];
+ _inkView = [aDecoder decodeObjectOfClass:[MDCInkView class] forKey:MDCChipInkViewKey];
+
+ _backgroundColors = [aDecoder decodeObjectOfClass:[NSMutableDictionary class]
+ forKey:MDCChipBackgroundColorsKey];
+ _borderColors = [aDecoder decodeObjectOfClass:[NSMutableDictionary class]
+ forKey:MDCChipBorderColorsKey];
+ _borderWidths = [aDecoder decodeObjectOfClass:[NSMutableDictionary class]
+ forKey:MDCChipBorderWidthsKey];
+ _elevations = [aDecoder decodeObjectOfClass:[NSMutableDictionary class]
+ forKey:MDCChipElevationsKey];
+ _inkColors = [aDecoder decodeObjectOfClass:[NSMutableDictionary class]
+ forKey:MDCChipInkColorsKey];
+ _shadowColors = [aDecoder decodeObjectOfClass:[NSMutableDictionary class]
+ forKey:MDCChipShadowColorsKey];
+ _titleFont = [aDecoder decodeObjectOfClass:[UIFont class] forKey:MDCChipTitleFontKey];
+ _titleColors = [aDecoder decodeObjectOfClass:[NSMutableDictionary class]
+ forKey:MDCChipTitleColorsKey];
self.mdc_adjustsFontForContentSizeCategory =
[aDecoder decodeBoolForKey:MDCChipAdjustsFontForContentSizeKey];

original_message: ChipView class check for encoding. (#2993)


diff:
@@ -70,6 +70,8 @@ static const CGFloat kBottomBarHeight = 44.0f;
}
- (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+
[MDCSnackbarManager setBottomOffset:0];
}

original_message: [SnackbarExmaples] Added required super call (#3005)


diff:
@@ -138,11 +138,11 @@ static CGFloat randomNumber() {
// Make sure that the stroke layer updates accordingly when we set determinate progress.
MDCActivityIndicator *indicator = [[MDCActivityIndicator alloc] init];
indicator.indicatorMode = MDCActivityIndicatorModeDeterminate;
+ [indicator startAnimating];
[indicator setProgress:0.55f animated:YES];
XCTAssertEqual(indicator.strokeLayer.strokeStart, 0.0);
- //TODO(#2923): Stroke is not updated. Wait until the animation is finished?
- //XCTAssertEqual(indicator.strokeLayer.strokeEnd, 0.55f);
+ XCTAssertEqual(indicator.strokeLayer.strokeEnd, 0.55f);
}
#pragma mark - Helpers

original_message: Fixed ActivityIndicatorTests#testSetProgressStrokeAnimated test (#3006)


message:
Update checklist.md
Adding more description for NSSecureCoding.

diff:
@@ -348,7 +348,9 @@ that is sufficient.
Tip: write a unit test for this.
1. Implement `-initWithCoder:`.
+1. For decoding objects always use "decodeObjectOfClass:forKey:" whenever possible.
1. Implement `-encodeWithCoder:`.
+1. Implement NSSecureCoding Protocol if all subclasses support NSSecureCoding. For example UIView and UIViewController do not support NSSecureCoding.
1. If implementing NSSecureCoding, implement `+supportsSecureCoding`.
1. Enter YES or NO


message:
Update checklist.md
Fixed styling.

diff:
@@ -348,7 +348,7 @@ that is sufficient.
Tip: write a unit test for this.
1. Implement `-initWithCoder:`.
-1. For decoding objects always use "decodeObjectOfClass:forKey:" whenever possible.
+1. For decoding objects always use `decodeObjectOfClass:forKey:` whenever possible.
1. Implement `-encodeWithCoder:`.
1. Implement NSSecureCoding Protocol if all subclasses support NSSecureCoding. For example UIView and UIViewController do not support NSSecureCoding.
1. If implementing NSSecureCoding, implement `+supportsSecureCoding`.

original_message:
Update checklist.md

Fixed styling.


message: Always encode/decode CGFloat as double

diff:
@@ -256,9 +256,9 @@ static UITextFieldViewMode _underlineViewModeDefault = UITextFieldViewModeWhileE
[aDecoder decodeObjectOfClass:[UIColor class]
forKey:MDCTextInputControllerBaseTrailingUnderlineLabelTextColor];
_underlineHeightActive =
- [aDecoder decodeFloatForKey:MDCTextInputControllerBaseUnderlineHeightActiveKey];
+ (CGFloat)[aDecoder decodeDoubleForKey:MDCTextInputControllerBaseUnderlineHeightActiveKey];
_underlineHeightNormal =
- [aDecoder decodeFloatForKey:MDCTextInputControllerBaseUnderlineHeightNormalKey];
+ (CGFloat)[aDecoder decodeDoubleForKey:MDCTextInputControllerBaseUnderlineHeightNormalKey];
_underlineViewMode = (UITextFieldViewMode)
[aDecoder decodeIntegerForKey:MDCTextInputControllerBaseUnderlineViewModeKey];
@@ -336,9 +336,9 @@ static UITextFieldViewMode _underlineViewModeDefault = UITextFieldViewModeWhileE
forKey:MDCTextInputControllerBaseTrailingUnderlineLabelFontKey];
[aCoder encodeObject:self.trailingUnderlineLabelTextColor
forKey:MDCTextInputControllerBaseTrailingUnderlineLabelTextColor];
- [aCoder encodeFloat:(float)self.underlineHeightActive
+ [aCoder encodeDouble:(double)self.underlineHeightActive
forKey:MDCTextInputControllerBaseUnderlineHeightActiveKey];
- [aCoder encodeFloat:(float)self.underlineHeightNormal
+ [aCoder encodeDouble:(double)self.underlineHeightNormal
forKey:MDCTextInputControllerBaseUnderlineHeightNormalKey];
[aCoder encodeInteger:self.underlineViewMode
forKey:MDCTextInputControllerBaseUnderlineViewModeKey];

diff:
@@ -248,13 +248,13 @@ static UITextFieldViewMode _underlineViewModeDefault = UITextFieldViewModeWhileE
forKey:MDCTextInputControllerLegacyDefaultTrailingUnderlineLabelTextColor];
if ([aDecoder
containsValueForKey:MDCTextInputControllerLegacyDefaultUnderlineHeightActiveKey]) {
- _underlineHeightActive = (float)[aDecoder
- decodeFloatForKey:MDCTextInputControllerLegacyDefaultUnderlineHeightActiveKey];
+ _underlineHeightActive = (CGFloat)[aDecoder
+ decodeDoubleForKey:MDCTextInputControllerLegacyDefaultUnderlineHeightActiveKey];
}
if ([aDecoder
containsValueForKey:MDCTextInputControllerLegacyDefaultUnderlineHeightNormalKey]) {
- _underlineHeightActive = (float)[aDecoder
- decodeFloatForKey:MDCTextInputControllerLegacyDefaultUnderlineHeightNormalKey];
+ _underlineHeightActive = (CGFloat)[aDecoder
+ decodeDoubleForKey:MDCTextInputControllerLegacyDefaultUnderlineHeightNormalKey];
}
if ([aDecoder containsValueForKey:MDCTextInputControllerLegacyDefaultUnderlineViewModeKey]) {
_underlineViewMode = (UITextFieldViewMode)
@@ -314,9 +314,9 @@ static UITextFieldViewMode _underlineViewModeDefault = UITextFieldViewModeWhileE
forKey:MDCTextInputControllerLegacyDefaultTrailingUnderlineLabelFontKey];
[aCoder encodeObject:self.trailingUnderlineLabelTextColor
forKey:MDCTextInputControllerLegacyDefaultTrailingUnderlineLabelTextColor];
- [aCoder encodeFloat:(float)self.underlineHeightActive
+ [aCoder encodeDouble:(double)self.underlineHeightActive
forKey:MDCTextInputControllerLegacyDefaultUnderlineHeightActiveKey];
- [aCoder encodeFloat:(float)self.underlineHeightNormal
+ [aCoder encodeDouble:(double)self.underlineHeightNormal
forKey:MDCTextInputControllerLegacyDefaultUnderlineHeightNormalKey];
[aCoder encodeInteger:self.underlineViewMode
forKey:MDCTextInputControllerLegacyDefaultUnderlineViewModeKey];

diff:
@@ -57,7 +57,7 @@ static inline UIColor *MDCTextInputUnderlineColor() {
_disabledColor =
[coder decodeObjectOfClass:[UIColor class] forKey:MDCTextInputUnderlineDisabledColorKey];
_enabled = [coder decodeBoolForKey:MDCTextInputUnderlineEnabledKey];
- _lineHeight = (CGFloat)[coder decodeFloatForKey:MDCTextInputUnderlineLineHeightKey];
+ _lineHeight = (CGFloat)[coder decodeDoubleForKey:MDCTextInputUnderlineLineHeightKey];
}
return self;
}
@@ -79,7 +79,7 @@ static inline UIColor *MDCTextInputUnderlineColor() {
[coder encodeObject:self.color forKey:MDCTextInputUnderlineColorKey];
[coder encodeObject:self.disabledColor forKey:MDCTextInputUnderlineDisabledColorKey];
[coder encodeBool:self.enabled forKey:MDCTextInputUnderlineEnabledKey];
- [coder encodeFloat:(float)self.lineHeight forKey:MDCTextInputUnderlineLineHeightKey];
+ [coder encodeDouble:(double)self.lineHeight forKey:MDCTextInputUnderlineLineHeightKey];
}
- (instancetype)copyWithZone:(__unused NSZone *)zone {

diff:
@@ -23,14 +23,14 @@ static NSString *const MDCPaddedLabelHorizontalPaddingKey = @"MDCPaddedLabelHori
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
- _horizontalPadding = (CGFloat)[aDecoder decodeFloatForKey:MDCPaddedLabelHorizontalPaddingKey];
+ _horizontalPadding = (CGFloat)[aDecoder decodeDoubleForKey:MDCPaddedLabelHorizontalPaddingKey];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[super encodeWithCoder:aCoder];
- [aCoder encodeFloat:(float)_horizontalPadding forKey:MDCPaddedLabelHorizontalPaddingKey];
+ [aCoder encodeDouble:(double)_horizontalPadding forKey:MDCPaddedLabelHorizontalPaddingKey];
}
#pragma mark - Setters

original_message: Always encode/decode CGFloat as double (#3033)


diff:
+/*
+ Copyright 2016-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 XCTest
+import MaterialComponents.MaterialTextFields
+
+class CharacterCounter: NSObject, MDCTextInputCharacterCounter, NSSecureCoding {
+ var fixedCount: UInt = 0
+
+ override init() {}
+
+ // MARK: - NSSecureCoding
+
+ static var supportsSecureCoding: Bool = true
+
+ required init?(coder aDecoder: NSCoder) {
+ self.fixedCount = UInt(aDecoder.decodeInt64(forKey: "fixedCount"))
+ }
+
+ func encode(with aCoder: NSCoder) {
+ aCoder.encode(Int64(fixedCount), forKey: "fixedCount")
+ }
+
+ // MARK: - MDCTextInputCharacterCounter
+
+ func characterCount(forTextInput textInput: UIView?) -> UInt {
+ return fixedCount
+ }
+}
+
+class MDCTextInputControllerBaseEncodingTests: XCTestCase {
+
+ func testTextInputControllerBaseEncoding() {
+ // Given
+ let controller = MDCTextInputControllerBase()
+ controller.activeColor = UIColor.cyan
+ controller.borderFillColor = UIColor.magenta
+ controller.characterCountMax = 42
+ controller.characterCountViewMode = .unlessEditing
+ controller.roundedCorners = .bottomLeft
+ controller.errorColor = UIColor.purple
+ controller.floatingPlaceholderNormalColor = UIColor.brown
+ controller.floatingPlaceholderScale = 0.57
+ controller.inlinePlaceholderColor = UIColor.green
+ controller.inlinePlaceholderFont = UIFont.systemFont(ofSize: 33)
+ controller.leadingUnderlineLabelFont = UIFont.systemFont(ofSize: 51)
+ controller.leadingUnderlineLabelTextColor = UIColor.white
+ controller.normalColor = UIColor.orange
+ controller.trailingUnderlineLabelFont = UIFont.systemFont(ofSize: 17)
+ controller.trailingUnderlineLabelTextColor = UIColor.yellow
+
+ // When
+ let data = NSKeyedArchiver.archivedData(withRootObject: controller)
+ let unarchivedController =
+ NSKeyedUnarchiver.unarchiveObject(with: data) as? MDCTextInputControllerBase
+
+ // Then
+ XCTAssertNotNil(unarchivedController)
+ XCTAssertEqual(controller.activeColor, unarchivedController?.activeColor)
+ XCTAssertEqual(controller.borderFillColor, unarchivedController?.borderFillColor)
+ XCTAssertEqual(controller.characterCountMax, unarchivedController?.characterCountMax)
+ XCTAssertEqual(controller.characterCountViewMode, unarchivedController?.characterCountViewMode)
+ XCTAssertEqual(controller.roundedCorners, unarchivedController?.roundedCorners)
+ XCTAssertEqual(controller.errorColor, unarchivedController?.errorColor)
+ XCTAssertEqual(controller.floatingPlaceholderNormalColor,
+ unarchivedController?.floatingPlaceholderNormalColor)
+ XCTAssertEqual(controller.floatingPlaceholderScale,
+ unarchivedController?.floatingPlaceholderScale)
+ XCTAssertEqual(controller.inlinePlaceholderColor, unarchivedController?.inlinePlaceholderColor)
+ XCTAssertEqual(controller.inlinePlaceholderFont, unarchivedController?.inlinePlaceholderFont)
+ XCTAssertEqual(controller.leadingUnderlineLabelFont,
+ unarchivedController?.leadingUnderlineLabelFont)
+ XCTAssertEqual(controller.leadingUnderlineLabelTextColor,
+ unarchivedController?.leadingUnderlineLabelTextColor)
+ XCTAssertEqual(controller.normalColor, unarchivedController?.normalColor)
+ XCTAssertEqual(controller.trailingUnderlineLabelFont,
+ unarchivedController?.trailingUnderlineLabelFont)
+ XCTAssertEqual(controller.trailingUnderlineLabelTextColor,
+ unarchivedController?.trailingUnderlineLabelTextColor)
+ }
+
+ func testTextInputControllerBaseCharacterCounterEncoding() {
+ // Given
+ let characterCounter = CharacterCounter()
+ characterCounter.fixedCount = 6
+ let controller = MDCTextInputControllerBase()
+ controller.characterCounter = characterCounter
+
+ // When
+ let data = NSKeyedArchiver.archivedData(withRootObject: controller)
+ let unarchivedController =
+ NSKeyedUnarchiver.unarchiveObject(with: data) as? MDCTextInputControllerBase
+ let unarchivedCounter = unarchivedController?.characterCounter as? CharacterCounter
+
+ // Then
+ XCTAssertNotNil(unarchivedCounter)
+ XCTAssertEqual(characterCounter.fixedCount, unarchivedCounter?.fixedCount)
+ }
+
+ // TODO: add textInput encoding test
+}

original_message: Added test for MDCTextInputControllerBase (#3036)


diff:
@@ -416,12 +416,12 @@ static UITextFieldViewMode _underlineViewModeDefault = UITextFieldViewModeWhileE
if ([_textInput conformsToProtocol:@protocol(MDCMultilineTextInput)] &&
[_textInput respondsToSelector:@selector(setMinimumLines:)]) {
- ((MDCMultilineTextField *)_textInput).minimumLines = self.minimumLines;
+ ((id<MDCMultilineTextInput>)_textInput).minimumLines = self.minimumLines;
}
if ([_textInput conformsToProtocol:@protocol(MDCMultilineTextInput)] &&
[_textInput respondsToSelector:@selector(setExpandsOnOverflow:)]) {
- ((MDCMultilineTextField *)_textInput).expandsOnOverflow = self.expandsOnOverflow;
+ ((id<MDCMultilineTextInput>)_textInput).expandsOnOverflow = self.expandsOnOverflow;
}
[self subscribeForNotifications];
@@ -998,7 +998,7 @@ static UITextFieldViewMode _underlineViewModeDefault = UITextFieldViewModeWhileE
_expandsOnOverflow = expandsOnOverflow;
if ([_textInput conformsToProtocol:@protocol(MDCMultilineTextInput)] &&
[_textInput respondsToSelector:@selector(setExpandsOnOverflow:)]) {
- ((MDCMultilineTextField *)_textInput).expandsOnOverflow = expandsOnOverflow;
+ ((id<MDCMultilineTextInput>)_textInput).expandsOnOverflow = expandsOnOverflow;
}
}
}
@@ -1190,7 +1190,7 @@ static UITextFieldViewMode _underlineViewModeDefault = UITextFieldViewModeWhileE
_minimumLines = minimumLines;
if ([_textInput conformsToProtocol:@protocol(MDCMultilineTextInput)] &&
[_textInput respondsToSelector:@selector(setMinimumLines:)]) {
- ((MDCMultilineTextField *)_textInput).minimumLines = minimumLines;
+ ((id<MDCMultilineTextInput>)_textInput).minimumLines = minimumLines;
}
}
}

original_message: [TextFields] Cast to a protocol textInput conforms to (#3037)


diff:
@@ -38,6 +38,7 @@ static const CGFloat kSheetBounceBuffer = 150.0f;
@property(nonatomic) MDCSheetBehavior *sheetBehavior;
@property(nonatomic) BOOL isDragging;
@property(nonatomic) CGFloat originalPreferredSheetHeight;
+@property(nonatomic) CGRect previousAnimatedBounds;
@end
@@ -191,6 +192,14 @@ static const CGFloat kSheetBounceBuffer = 150.0f;
#pragma mark - Layout
+- (void)layoutSubviews {
+ [super layoutSubviews];
+ if (!CGRectEqualToRect(self.bounds, self.previousAnimatedBounds) && self.window) {
+ // Adjusts the pane to the correct snap point if we are visible.
+ [self animatePaneWithInitialVelocity:CGPointZero];
+ }
+}
+
- (void)setPreferredSheetHeight:(CGFloat)preferredSheetHeight {
self.originalPreferredSheetHeight = preferredSheetHeight;
@@ -273,6 +282,7 @@ static const CGFloat kSheetBounceBuffer = 150.0f;
#pragma mark - Gesture-driven animation
- (void)animatePaneWithInitialVelocity:(CGPoint)initialVelocity {
+ self.previousAnimatedBounds = self.bounds;
self.sheetBehavior.targetPoint = [self targetPoint];
self.sheetBehavior.velocity = initialVelocity;
__weak MDCSheetContainerView *weakSelf = self;

original_message: Ensure BottomSheet adjusts its target point when its bounds change (#3028)


diff:
@@ -203,10 +203,9 @@ static inline CGPoint CGPointAddedToPoint(CGPoint a, CGPoint b) {
}
- (void)updateTitleFont {
- // If we have a custom font apply it to the label.
- // If not, fall back to the Material specified font.
- if (_titleFont) {
- // If we are automatically adjusting for Dynamic Type resize the font based on the text style
+ if (!_titleFont) {
+ _titleFont = [MDCFeatureHighlightView defaultTitleFont];
+ }
if (_mdc_adjustsFontForContentSizeCategory) {
_titleLabel.font =
[_titleFont mdc_fontSizedForMaterialTextStyle:kTitleTextStyle
@@ -214,32 +213,6 @@ static inline CGPoint CGPointAddedToPoint(CGPoint a, CGPoint b) {
} else {
_titleLabel.font = _titleFont;
}
- } else {
- // TODO(#2709): Migrate to a single source of truth for fonts
- // There is no custom font, so use the default font.
- if (_mdc_adjustsFontForContentSizeCategory) {
- // If we are using the default (system) font loader, retrieve the
- // font from the UIFont preferredFont API.
- if ([MDCTypography.fontLoader isKindOfClass:[MDCSystemFontLoader class]]) {
- _titleLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:kTitleTextStyle];
- } else {
- // There is a custom font loader, retrieve the font and scale it.
- UIFont *customTypographyFont = [MDCTypography titleFont];
- _titleLabel.font =
- [customTypographyFont mdc_fontSizedForMaterialTextStyle:kTitleTextStyle
- scaledForDynamicType:_mdc_adjustsFontForContentSizeCategory];
- }
- } else {
- // If we are using the default (system) font loader, retrieve the
- // font from the UIFont standardFont API.
- if ([MDCTypography.fontLoader isKindOfClass:[MDCSystemFontLoader class]]) {
- _titleLabel.font = [UIFont mdc_standardFontForMaterialTextStyle:kTitleTextStyle];
- } else {
- // There is a custom font loader, retrieve the font from it.
- _titleLabel.font = [MDCTypography titleFont];
- }
- }
- }
[self setNeedsLayout];
}
@@ -257,44 +230,16 @@ static inline CGPoint CGPointAddedToPoint(CGPoint a, CGPoint b) {
}
- (void)updateBodyFont {
- // If we have a custom font apply it to the label.
- // If not, fall back to the Material specified font.
- if (_bodyFont) {
+ if (!_bodyFont) {
+ _bodyFont = [MDCFeatureHighlightView defaultBodyFont];
+ }
if (_mdc_adjustsFontForContentSizeCategory) {
- // If we are automatically adjusting for Dynamic Type resize the font based on the text style
_bodyLabel.font =
[_bodyFont mdc_fontSizedForMaterialTextStyle:kBodyTextStyle
scaledForDynamicType:_mdc_adjustsFontForContentSizeCategory];
} else {
_bodyLabel.font = _bodyFont;
}
- } else {
- // TODO(#2709): Migrate to a single source of truth for fonts
- // There is no custom font, so use the default font.
- if (_mdc_adjustsFontForContentSizeCategory) {
- // If we are using the default (system) font loader, retrieve the
- // font from the UIFont preferredFont API.
- if ([MDCTypography.fontLoader isKindOfClass:[MDCSystemFontLoader class]]) {
- _bodyLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:kBodyTextStyle];
- } else {
- // There is a custom font loader, retrieve the font and scale it.
- UIFont *customTypographyFont = [MDCTypography body1Font];
- _bodyLabel.font =
- [customTypographyFont mdc_fontSizedForMaterialTextStyle:kBodyTextStyle
- scaledForDynamicType:_mdc_adjustsFontForContentSizeCategory];
- }
- } else {
- // If we are using the default (system) font loader, retrieve the
- // font from the UIFont standardFont API.
- if ([MDCTypography.fontLoader isKindOfClass:[MDCSystemFontLoader class]]) {
- _bodyLabel.font = [UIFont mdc_standardFontForMaterialTextStyle:kBodyTextStyle];
- } else {
- // There is a custom font loader, retrieve the font from it.
- _bodyLabel.font = [MDCTypography body1Font];
- }
- }
- }
-
[self setNeedsLayout];
}
@@ -304,6 +249,20 @@ static inline CGPoint CGPointAddedToPoint(CGPoint a, CGPoint b) {
_bodyLabel.textColor = bodyColor;
}
++ (UIFont *)defaultBodyFont {
+ if ([MDCTypography.fontLoader isKindOfClass:[MDCSystemFontLoader class]]) {
+ return [UIFont mdc_standardFontForMaterialTextStyle:kBodyTextStyle];
+ }
+ return [MDCTypography body1Font];
+}
+
++ (UIFont *)defaultTitleFont {
+ if ([MDCTypography.fontLoader isKindOfClass:[MDCSystemFontLoader class]]) {
+ return [UIFont mdc_standardFontForMaterialTextStyle:kTitleTextStyle];
+ }
+ return [MDCTypography titleFont];
+}
+
- (void)setInnerHighlightColor:(UIColor *)innerHighlightColor {
if (!innerHighlightColor) {
innerHighlightColor = [self MDCFeatureHighlightDefaultInnerHighlightColor];

original_message: cleaning up dynamic type support for feature highlight by defining the default. (#3269)


diff:
@@ -192,6 +192,22 @@ static const CGFloat kMDCFeatureHighlightPulseAnimationInterval = 1.5f;
self.view.bodyColor = bodyColor;
}
+- (void)setTitleFont:(UIFont *)titleFont {
+ self.view.titleFont = titleFont;
+}
+
+- (UIFont *)titleFont {
+ return self.view.titleFont;
+}
+
+- (void)setBodyFont:(UIFont *)bodyFont {
+ self.view.bodyFont = bodyFont;
+}
+
+- (UIFont *)bodyFont {
+ return self.view.bodyFont;
+}
+
- (void)acceptFeature {
[self dismiss:YES];
}

original_message: exposing title and body font for FeatureHighlightViewController. (#3274)


message:
Update Activity Indicator accessibility label and value
The generated files were created with generate_string_tables.py
internally, then exported manually to the external
material-components-ios repo

diff:
@@ -974,19 +974,29 @@ static const CGFloat kSingleCycleRotation =
}
- (NSString *)accessibilityLabel {
+ MaterialActivityIndicatorStringId keyIndex = kStr_MaterialActivityIndicatorAccessibilityLabel;
+ NSString *key = kMaterialActivityIndicatorStringTable[keyIndex];
+ return NSLocalizedStringFromTableInBundle(key,
+ kMaterialActivityIndicatorStringsTableName,
+ [[self class] bundle],
+ @"Activity Indicator");
+}
+- (NSString *)accessibilityValue {
if (self.isAnimating) {
if (self.indicatorMode == MDCActivityIndicatorModeIndeterminate) {
- NSString *key =
- kMaterialActivityIndicatorStringTable[kStr_MaterialActivityIndicatorInProgressAccessibilityLabel];
+ MaterialActivityIndicatorStringId keyIndex =
+ kStr_MaterialActivityIndicatorInProgressAccessibilityValue;
+ NSString *key = kMaterialActivityIndicatorStringTable[keyIndex];
return NSLocalizedStringFromTableInBundle(key,
kMaterialActivityIndicatorStringsTableName,
[[self class] bundle],
@"In Progress");
} else {
NSUInteger percentage = (int)(self.progress * 100);
- NSString *key =
- kMaterialActivityIndicatorStringTable[kStr_MaterialActivityIndicatorProgressCompletedAccessibilityLabel];
+ MaterialActivityIndicatorStringId keyIndex =
+ kStr_MaterialActivityIndicatorProgressCompletedAccessibilityValue;
+ NSString *key = kMaterialActivityIndicatorStringTable[keyIndex];
NSString *localizedString = NSLocalizedStringFromTableInBundle(key,
kMaterialActivityIndicatorStringsTableName,
[[self class] bundle],
@@ -994,8 +1004,9 @@ static const CGFloat kSingleCycleRotation =
return [NSString localizedStringWithFormat:localizedString, percentage];
}
} else {
- NSString *key =
- kMaterialActivityIndicatorStringTable[kStr_MaterialActivityIndicatorProgressHaltedAccessibilityLabel];
+ MaterialActivityIndicatorStringId keyIndex =
+ kStr_MaterialActivityIndicatorProgressHaltedAccessibilityValue;
+ NSString *key = kMaterialActivityIndicatorStringTable[keyIndex];
return NSLocalizedStringFromTableInBundle(key,
kMaterialActivityIndicatorStringsTableName,
[[self class] bundle],
@@ -1007,14 +1018,6 @@ static const CGFloat kSingleCycleRotation =
return UIAccessibilityTraitUpdatesFrequently;
}
-- (NSString *)accessibilityValue {
- if (self.isAnimating) {
- return [NSNumberFormatter localizedStringFromNumber:@1 numberStyle:NSNumberFormatterNoStyle];
- } else {
- return [NSNumberFormatter localizedStringFromNumber:@0 numberStyle:NSNumberFormatterNoStyle];
- }
-}
-
@end
@implementation MDCActivityIndicatorTransition

diff:
-/* Accessibility label for indeterminate activity indicator in progress */
-"MaterialActivityIndicatorInProgressAccessibilityLabel" = "In Progress";
+/* Accessibility label for activity indicator. */
+"MaterialActivityIndicatorAccessibilityLabel" = "Activity Indicator";
-/* Accessibility label for indeterminate activity indicator in progress */
-"MaterialActivityIndicatorProgressCompletedAccessibilityLabel" = "%ld Percent Complete";
+/* Accessibility value for indeterminate activity indicator in progress. */
+"MaterialActivityIndicatorInProgressAccessibilityValue" = "In Progress";
-/* Accessibility label for activity indicator progress halted */
-"MaterialActivityIndicatorProgressHaltedAccessibilityLabel" = "Progress Halted";
+/* Accessibility value for determinate activity indicator in progress. */
+"MaterialActivityIndicatorProgressCompletedAccessibilityValue" = "%ld Percent Complete";
+
+/* Accessibility value for activity indicator progress halted. */
+"MaterialActivityIndicatorProgressHaltedAccessibilityValue" = "Progress Halted";

diff:
// GENERATED BY: generate_string_tables.py
typedef enum {
- kStr_MaterialActivityIndicatorInProgressAccessibilityLabel = 0,
- kStr_MaterialActivityIndicatorProgressHaltedAccessibilityLabel = 1,
- kStr_MaterialActivityIndicatorProgressCompletedAccessibilityLabel = 2,
+ kStr_MaterialActivityIndicatorInProgressAccessibilityValue = 0,
+ kStr_MaterialActivityIndicatorAccessibilityLabel = 1,
+ kStr_MaterialActivityIndicatorProgressHaltedAccessibilityValue = 2,
+ kStr_MaterialActivityIndicatorProgressCompletedAccessibilityValue = 3,
} MaterialActivityIndicatorStringId;

diff:
// This table is to be indexed using the generated enum.
static NSString *const kMaterialActivityIndicatorStringTable[] = {
- @"MaterialActivityIndicatorInProgressAccessibilityLabel", // In Progress
- @"MaterialActivityIndicatorProgressHaltedAccessibilityLabel", // Progress Halted
- @"MaterialActivityIndicatorProgressCompletedAccessibilityLabel", // %ld Percent Complete
+ @"MaterialActivityIndicatorInProgressAccessibilityValue", // In Progress
+ @"MaterialActivityIndicatorAccessibilityLabel", // Activity Indicator
+ @"MaterialActivityIndicatorProgressHaltedAccessibilityValue", // Progress Halted
+ @"MaterialActivityIndicatorProgressCompletedAccessibilityValue", // %ld Percent Complete
};
-#define kNumMaterialActivityIndicatorStrings 3
+#define kNumMaterialActivityIndicatorStrings 4
#define kMaterialActivityIndicatorStringsOffset 0
#define kMaterialActivityIndicatorStringsEnd 10000
static NSString *const kMaterialActivityIndicatorStringsTableName = @"MaterialActivityIndicator";

original_message:
Update Activity Indicator accessibility label and value (#3261)

The generated files were created with generate_string_tables.py
internally, then exported manually to the external
material-components-ios repo


message: Update ActivityIndicator Color Themer

diff:
@@ -56,7 +56,7 @@ Pod::Spec.new do |mdc|
extension.source_files = "components/ActivityIndicator/src/#{extension.base_name}/*.{h,m}"
extension.dependency "MaterialComponents/ActivityIndicator"
- extension.dependency "MaterialComponents/Themes"
+ extension.dependency "MaterialComponents/schemes/Color"
end
end

old_path: components/ActivityIndicator/BUILD

new_path: components/ActivityIndicator/BUILD

diff:
@@ -58,7 +58,7 @@ mdc_objc_library(
],
deps = [
":ActivityIndicator",
- "//components/Themes",
+ "//components/Schemes/Color",
],
visibility = ["//visibility:public"],
)

diff:
limitations under the License.
*/
-#import "MaterialThemes.h"
+#import "MaterialColorScheme.h"
#import "MaterialActivityIndicator.h"
/**
*/
@interface MDCActivityIndicatorColorThemer : NSObject
+/**
+ Applies a color scheme's properties to an MDCActivityIndicator.
+
+ @param colorScheme The color scheme to apply to MDCActivityIndicator.
+ @param activityIndicator An MDCActivityIndicator instance to which the color scheme should be
+ applied.
+ */
++ (void)applySemanticColorScheme:(nonnull id<MDCColorScheming>)colorScheme
+ toActivityIndicator:(nonnull MDCActivityIndicator *)activityIndicator;
+
+#pragma mark - Soon to be deprecated
+
/**
Applies a color scheme to theme a MDCActivityIndicator. Use a UIAppearance proxy to apply a color
scheme to all instances of MDCActivityIndicator.
+ This method will soon be deprecated. Consider using +applySemanticColorScheme:toActivityIndicator:
+ instead.
+
@param colorScheme The color scheme to apply to MDCActivityIndicator.
@param activityIndicator A MDCActivityIndicator instance to apply a color scheme.
*/

diff:
@implementation MDCActivityIndicatorColorThemer
++ (void)applySemanticColorScheme:(nonnull id<MDCColorScheming>)colorScheme
+ toActivityIndicator:(nonnull MDCActivityIndicator *)activityIndicator {
+ activityIndicator.cycleColors = @[ colorScheme.primaryColor ];
+}
+
+ (void)applyColorScheme:(id<MDCColorScheme>)colorScheme
toActivityIndicator:(MDCActivityIndicator *)activityIndicator {
activityIndicator.cycleColors = @[ colorScheme.primaryColor ];

diff:
+/*
+ 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 XCTest
+import MaterialComponents.MaterialActivityIndicator
+import MaterialComponents.MDCActivityIndicatorColorThemer
+
+class ActivityIndicatorColorThemerTests: XCTestCase {
+
+ func testColorThemerChangesTheBackgroundColor() {
+ // Given
+ let colorScheme = MDCSemanticColorScheme()
+ let activityIndicator = MDCActivityIndicator()
+ colorScheme.primaryColor = .red
+ activityIndicator.cycleColors = [ .white ]
+
+ // When
+ MDCActivityIndicatorColorThemer.applySemanticColorScheme(colorScheme, to: activityIndicator)
+
+ // Then
+ XCTAssertEqual(activityIndicator.cycleColors, [ colorScheme.primaryColor ])
+ }
+}

original_message: Update ActivityIndicator Color Themer (#3259)


message:
[NavigationBar] typography implementation.
* Navigation Bar Typography Themer implementation.
Tests and example added.
* fixing merge conflict mistake and tests.

diff:
@@ -460,6 +460,14 @@ Pod::Spec.new do |mdc|
extension.dependency "MaterialComponents/NavigationBar"
extension.dependency "MaterialComponents/schemes/Color"
end
+ component.subspec "TypographyThemer" do |extension|
+ extension.ios.deployment_target = '8.0'
+ extension.public_header_files = "components/NavigationBar/src/#{extension.base_name}/*.h"
+ extension.source_files = "components/NavigationBar/src/#{extension.base_name}/*.{h,m}"
+
+ extension.dependency "MaterialComponents/NavigationBar"
+ extension.dependency "MaterialComponents/schemes/Typography"
+ end
end
mdc.subspec "OverlayWindow" do |component|

old_path: components/NavigationBar/BUILD

new_path: components/NavigationBar/BUILD

diff:
@@ -47,6 +47,18 @@ mdc_objc_library(
visibility = ["//visibility:public"],
)
+mdc_objc_library(
+ name = "TypographyThemer",
+ srcs = native.glob(["src/TypographyThemer/*.m"]),
+ hdrs = native.glob(["src/TypographyThemer/*.h"]),
+ includes = ["src/TypographyThemer"],
+ deps = [
+ ":NavigationBar",
+ "//components/schemes/Typography",
+ ],
+ visibility = ["//visibility:public"],
+)
+
mdc_objc_library(
name = "unit_test_sources",
testonly = 1,
@@ -61,6 +73,7 @@ mdc_objc_library(
deps = [
":NavigationBar",
":ColorThemer",
+ ":TypographyThemer",
"@material_text_accessibility_ios//:MDFTextAccessibility",
],
visibility = ["//visibility:private"],

diff:
#import "MaterialIcons+ic_reorder.h"
#import "MaterialNavigationBar.h"
#import "MDCNavigationBarColorThemer.h"
+#import "MDCNavigationBarTypographyThemer.h"
#import "supplemental/NavigationBarTypicalUseExampleSupplemental.h"
@interface NavigationBarIconsExample ()
self.navigationBar = [[MDCNavigationBar alloc] initWithFrame:CGRectZero];
self.navigationBar.translatesAutoresizingMaskIntoConstraints = NO;
[self.navigationBar observeNavigationItem:self.navigationItem];
+ MDCTypographyScheme *typographyScheme = [[MDCTypographyScheme alloc] init];
+ [MDCNavigationBarTypographyThemer applyTypographyScheme:typographyScheme
+ toNavigationBar:self.navigationBar];
[self.view addSubview:self.navigationBar];
id<MDCColorScheming> colorScheme = [[MDCSemanticColorScheme alloc] init];

diff:
+/*
+ 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 "MaterialNavigationBar.h"
+#import "MaterialTypographyScheme.h"
+
+/**
+ Used to apply a typography scheme to theme MDCNavigationBar.
+ */
+@interface MDCNavigationBarTypographyThemer : NSObject
+
+/**
+ Applies a typography scheme to theme a MDCNavigationBar.
+
+ @param typographyScheme The typography scheme to apply to MDCNavigationBar.
+ @param navigationBar A MDCNavigationBar instance to apply a typography scheme.
+ */
++ (void)applyTypographyScheme:(nonnull id<MDCTypographyScheming>)typographyScheme
+ toNavigationBar:(nonnull MDCNavigationBar *)navigationBar;
+
+@end

diff:
+/*
+ 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 "MDCNavigationBarTypographyThemer.h"
+
+@implementation MDCNavigationBarTypographyThemer
+
++ (void)applyTypographyScheme:(id<MDCTypographyScheming>)typographyScheme
+ toNavigationBar:(MDCNavigationBar *)navigationBar {
+ navigationBar.titleFont = typographyScheme.headline6;
+}
+
+@end

diff:
#import "MaterialButtonBar.h"
#import "MaterialNavigationBar.h"
+#import "MDCNavigationBarTypographyThemer.h"
static const CGFloat kEpsilonAccuracy = 0.001f;
@@ -293,6 +294,28 @@ static const CGFloat kEpsilonAccuracy = 0.001f;
}
}
+#pragma mark - Typography
+
+- (void)testTypographyThemer {
+ MDCNavigationBar *navBar = [[MDCNavigationBar alloc] init];
+ MDCTypographyScheme *scheme = [[MDCTypographyScheme alloc] init];
+ [MDCNavigationBarTypographyThemer applyTypographyScheme:scheme toNavigationBar:navBar];
+
+ // To enforce 20 point size we are using fontWithName:size: and for some reason even though the
+ // printout looks idential comparing the fonts returns false. (Using fontWithSize: did not work
+ // for system font medium, instead it returned a regular font).
+ UIFont *titleFont = navBar.titleLabel.font;
+ XCTAssertEqualObjects(titleFont.fontName, scheme.headline6.fontName);
+ XCTAssertEqual(titleFont.pointSize, scheme.headline6.pointSize);
+
+ // Weight for Fonts was not introduced on iOS 8
+ // TODO: remove this when we drop iOS 8 support.
+#if defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0
+ XCTAssertEqual([NavigationBarTests weightForFont:titleFont],
+ [NavigationBarTests weightForFont:scheme.headline6]);
+#endif
+}
+
// I really don't like doing this but just to make sure the font has the right weight for the test
// I had to do this. Couldn't find any other way around it. When Apple support FontWithSize:
// properly for all fonts we can get rid of this.

original_message:
[NavigationBar] typography implementation. (#3304)

* Navigation Bar Typography Themer implementation.
Tests and example added.

* fixing merge conflict mistake and tests.


message:
BottomNavigationBar Typography Implementation,
Tests and example added.

diff:
@@ -142,6 +142,13 @@ Pod::Spec.new do |mdc|
extension.dependency "MaterialComponents/BottomNavigation"
extension.dependency "MaterialComponents/Themes"
end
+ component.subspec "TypographyThemer" do |extension|
+ extension.ios.deployment_target = '8.0'
+ extension.public_header_files = "components/BottomNavigation/src/TypographyThemer/*.h"
+ extension.source_files = "components/BottomNavigation/src/TypographyThemer/*.{h,m}"
+ extension.dependency "MaterialComponents/BottomNavigation"
+ extension.dependency "MaterialComponents/schemes/Typography"
+ end
end
mdc.subspec "BottomSheet" do |component|

old_path: components/BottomNavigation/BUILD

new_path: components/BottomNavigation/BUILD

diff:
@@ -63,6 +63,22 @@ mdc_objc_library(
visibility = ["//visibility:public"],
)
+
+mdc_objc_library(
+ name = "TypographyThemer",
+ srcs = native.glob(["src/TypographyThemer/*.m"]),
+ hdrs = native.glob(["src/TypographyThemer/*.h"]),
+ includes = ["src/TypographyThemer"],
+ sdk_frameworks = [
+ "Foundation",
+ ],
+ deps = [
+ ":BottomNavigation",
+ "//components/schemes/Typography",
+ ],
+ visibility = ["//visibility:public"],
+)
+
mdc_objc_library(
name = "private",
hdrs = native.glob(["src/private/*.h"]),
@@ -84,6 +100,7 @@ mdc_objc_library(
deps = [
":BottomNavigation",
":ColorThemer",
+ ":TypographyThemer",
":private",
],
visibility = ["//visibility:private"],

diff:
#import "MaterialPalettes.h"
#import "MaterialThemes.h"
#import "MDCBottomNavigationBarColorThemer.h"
+#import "MDCBottomNavigationBarTypographyThemer.h"
@interface BottomNavigationTypicalUseExample () <MDCBottomNavigationBarDelegate>
_bottomNavBar.titleVisibility = MDCBottomNavigationBarTitleVisibilitySelected;
_bottomNavBar.alignment = MDCBottomNavigationBarAlignmentJustifiedAdjacentTitles;
_bottomNavBar.delegate = self;
+ MDCTypographyScheme *typographyScheme = [[MDCTypographyScheme alloc] init];
+ [MDCBottomNavigationBarTypographyThemer applyTypographyScheme:typographyScheme
+ toBottomNavigationBar:_bottomNavBar];
[self.view addSubview:_bottomNavBar];
UITabBarItem *tabBarItem1 =

diff:
+/*
+ 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 "MaterialBottomNavigation.h"
+#import "MaterialTypographyScheme.h"
+
+
+/**
+ Applies a Typography scheme to an MDCBottomNavigationBar.
+ */
+@interface MDCBottomNavigationBarTypographyThemer : NSObject
+
+/**
+ Applies a typography scheme to theme an MDCBottomNavigationBar.
+
+ @param typographyScheme The typography scheme to apply to an MDCBottomNavigationBar.
+ @param bottomNavigationBar An MDCBottomNavigationBar instance to apply a typography scheme to.
+ */
++ (void)applyTypographyScheme:(nonnull id<MDCTypographyScheming>)typographyScheme
+ toBottomNavigationBar:(nonnull MDCBottomNavigationBar *)bottomNavigationBar;
+
+@end

diff:
+/*
+ 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 "MDCBottomNavigationBarTypographyThemer.h"
+
+@implementation MDCBottomNavigationBarTypographyThemer
+
++ (void)applyTypographyScheme:(nonnull id<MDCTypographyScheming>)typographyScheme
+ toBottomNavigationBar:(nonnull MDCBottomNavigationBar *)bottomNavigationBar {
+ bottomNavigationBar.itemTitleFont = typographyScheme.caption;
+}
+
+@end

diff:
+/*
+ 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 <XCTest/XCTest.h>
+#import "MDCBottomNavigationBarTypographyThemer.h"
+#import "MaterialBottomNavigation.h"
+
+@interface BottomNavigationTypographyThemerTests : XCTestCase
+
+@end
+
+@implementation BottomNavigationTypographyThemerTests
+
+- (void)testTypogrpahyThemer {
+ MDCTypographyScheme *typographyScheme = [[MDCTypographyScheme alloc] init];
+ MDCBottomNavigationBar *bottomBar = [[MDCBottomNavigationBar alloc] initWithFrame:CGRectZero];
+ UITabBarItem *item1 = [[UITabBarItem alloc] initWithTitle:@"1" image:nil tag:0];
+ UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:@"2" image:nil tag:0];
+ bottomBar.itemTitleFont = [UIFont systemFontOfSize:31];
+ bottomBar.items = @[item1, item2];
+
+ [MDCBottomNavigationBarTypographyThemer applyTypographyScheme:typographyScheme
+ toBottomNavigationBar:bottomBar];
+
+ XCTAssertEqual(bottomBar.itemTitleFont, typographyScheme.caption);
+}
+
+@end

original_message:
BottomNavigationBar Typography Implementation, (#3311)

Tests and example added.


diff:
@@ -32,7 +32,7 @@ import UIKit
class MDCCatalogComponentsController: UICollectionViewController, MDCInkTouchControllerDelegate {
fileprivate struct Constants {
- static let headerScrollThreshold: CGFloat = 50
+ static let headerScrollThreshold: CGFloat = 20
static let inset: CGFloat = 16
static let logoTitleVerticalSpacing: CGFloat = 32
static let logoWidthHeight: CGFloat = 40
@@ -411,7 +411,13 @@ class MDCCatalogComponentsController: UICollectionViewController, MDCInkTouchCon
func adjustLogoForScrollView(_ scrollView: UIScrollView) {
let offset = scrollView.contentOffset.y
- let inset = scrollView.contentInset.top
+ var inset = scrollView.contentInset.top
+// On the iPhone X, we need to use the offset which might take into account the safe area.
+#if swift(>=3.2)
+ if #available(iOS 11, *) {
+ inset = scrollView.adjustedContentInset.top
+ }
+#endif
let relativeOffset = inset + offset
logo.alpha = 1 - (relativeOffset / Constants.headerScrollThreshold)

original_message: Ensure the mdc icon fades out before crossing status bar (#3257)