From 2b5aeb9286b03105b43a43b7ad090ae84e44260e Mon Sep 17 00:00:00 2001 From: Janette James Date: Mon, 22 Jul 2024 16:26:20 -0700 Subject: [PATCH] Delete Animations extension PiperOrigin-RevId: 654934617 --- components/Shadow/README.md | 14 -- .../examples/ShadowAnimationBugExample.swift | 192 ------------------ .../Animations/UIView+MDCShadowAnimations.h | 115 ----------- .../Animations/UIView+MDCShadowAnimations.m | 172 ---------------- 4 files changed, 493 deletions(-) delete mode 100644 components/Shadow/examples/ShadowAnimationBugExample.swift delete mode 100644 components/Shadow/src/Animations/UIView+MDCShadowAnimations.h delete mode 100644 components/Shadow/src/Animations/UIView+MDCShadowAnimations.m diff --git a/components/Shadow/README.md b/components/Shadow/README.md index c6265513567..c08f604e3bb 100644 --- a/components/Shadow/README.md +++ b/components/Shadow/README.md @@ -21,8 +21,6 @@ MDCConfigureShadowForView should be called in the start of the view’s lifecycl MDCConfigureShadowForView should also be called when the elevation is changed for the view i.e. it is set by the client, or there is a state change that also changes the elevation. This is to ensure that the right shadow values for that elevation are set on the layer. Lastly, MDCConfigureShadowForView should be called in layoutSubviews, to ensure that the shadowPath is set using the most up to date bounds and cornerRadius of the view. -UIView+ShadowAnimations is provided as an extension for animations that changes a view's bounds or layer.cornerRadius. Choose from the provided methods based on your use case. See below for import instructions. - ### Importing Shadow Before using Shadow, you'll need to import it: @@ -76,15 +74,3 @@ shadowsCollection = [shadowsBuilder build]; self.shadowColor); } ``` - -### Importing Shadow/Animations - -#### Swift -```swift -import MaterialComponents.Shadow_Animations -``` - -#### Objective-C -```objc -#import "UIView+MDCShadowAnimations.h" -``` \ No newline at end of file diff --git a/components/Shadow/examples/ShadowAnimationBugExample.swift b/components/Shadow/examples/ShadowAnimationBugExample.swift deleted file mode 100644 index 15e31c75c94..00000000000 --- a/components/Shadow/examples/ShadowAnimationBugExample.swift +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2022-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.MaterialShadow_Animations -import MaterialComponents.MaterialShadow -import MaterialComponents.MaterialContainerScheme - -/// Typical use-case for a view with Material Shadows at a fixed elevation. -private final class ShadowedView: UIView { - override init(frame: CGRect) { - super.init(frame: frame) - layer.cornerRadius = 4 - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) is unavailable") - } - - override func layoutSubviews() { - super.layoutSubviews() - MDCConfigureShadow( - for: self, shadow: MDCShadowsCollectionDefault().shadow(forElevation: 12)) - } -} - -@available(iOS 12.0, *) -final class ShadowAnimationBugExample: UIViewController { - private enum Constants { - static let collapsedCornerRadius: CGFloat = 8.0 - static let expandedCornerRadius: CGFloat = 48.0 - - static let collapsedHeight = 100.0 - static let expandedHeight = 200.0 - - static let collapsedWidth: CGFloat = 100.0 - static let expandedWidth: CGFloat = 200.0 - - static let duration = 0.5 - static let timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) - } - - private lazy var typicalView: UIView = { - let result = ShadowedView() - result.translatesAutoresizingMaskIntoConstraints = false - result.backgroundColor = .red - return result - }() - - override func viewDidLoad() { - super.viewDidLoad() - view.addSubview(typicalView) - view.backgroundColor = .white - typicalView.frame = CGRect( - x: 0, y: 0, width: Constants.collapsedWidth, height: Constants.collapsedHeight) - typicalView.center = view.center - typicalView.layer.cornerRadius = Constants.collapsedCornerRadius - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - repeatingViewAnimationWithCenterAndCornerRadius( - view: typicalView, startFrame: typicalView.frame, startRadius: typicalView.layer.cornerRadius, - duration: Constants.duration, timingFunction: Constants.timingFunction) - } - - /// Expansion and contraction of width - func repeatingViewAnimationWithCenter( - view: UIView, startFrame: CGRect, duration: CGFloat, timingFunction: CAMediaTimingFunction - ) { - let endWidth = targetWidth(for: startFrame.size.width) - let endRect = CGRect( - origin: view.frame.origin, size: CGSize(width: endWidth, height: startFrame.height)) - - view.mdc_animateBoundsWithCenter( - to: startFrame, center: view.center, duration: duration, timingFunction: timingFunction - ) { [weak self] didComplete in - if didComplete { - self?.repeatingViewAnimationWithCenter( - view: view, startFrame: endRect, duration: duration, timingFunction: timingFunction) - } - } - } - - /// Expansion and contraction of width and corner radius - func repeatingViewAnimationWithCenterAndCornerRadius( - view: UIView, startFrame: CGRect, startRadius: CGFloat, duration: CGFloat, - timingFunction: CAMediaTimingFunction - ) { - let endWidth = targetWidth(for: startFrame.size.width) - let endRadius = targetCornerRadius(for: view.layer.cornerRadius) - let endRect = CGRect( - origin: view.frame.origin, size: CGSize(width: endWidth, height: startFrame.height)) - - view.mdc_animateBoundsWithCenterAndCornerRadius( - to: endRect, center: view.center, cornerRadius: endRadius, duration: duration, - timingFunction: timingFunction - ) { [weak self] didComplete in - if didComplete { - self?.repeatingViewAnimationWithCenterAndCornerRadius( - view: view, startFrame: endRect, startRadius: endRadius, duration: duration, - timingFunction: timingFunction) - } - } - } - - /// Expansion and contraction of corner radius only - func repeatingCornerRadiusAnimation( - view: UIView, startRadius: CGFloat, duration: CGFloat, timingFunction: CAMediaTimingFunction - ) { - let endRadius = targetCornerRadius(for: view.layer.cornerRadius) - - view.mdc_animateCornerRadius( - toValue: endRadius, duration: duration, timingFunction: timingFunction - ) { [weak self] didComplete in - self?.repeatingCornerRadiusAnimation( - view: view, startRadius: endRadius, duration: duration, timingFunction: timingFunction) - } - } - - /// Expansion and contraction of height, width, and corner radius - func repeatingCenterRadiusHeightWidthAnimation( - view: UIView, startFrame: CGRect, startRadius: CGFloat, duration: CGFloat, - timingFunction: CAMediaTimingFunction - ) { - let endWidth = targetWidth(for: startFrame.size.width) - let endHeight = targetHeight(for: startFrame.size.height) - let endRadius = targetCornerRadius(for: view.layer.cornerRadius) - let endRect = CGRect( - origin: view.frame.origin, size: CGSize(width: endWidth, height: endHeight)) - - view.mdc_animateBoundsWithCenterAndCornerRadius( - to: endRect, center: view.center, cornerRadius: endRadius, duration: duration, - timingFunction: timingFunction - ) { [weak self] didComplete in - if didComplete { - self?.repeatingCenterRadiusHeightWidthAnimation( - view: view, startFrame: endRect, startRadius: endRadius, duration: duration, - timingFunction: timingFunction) - } - } - } -} - -// MARK: Target Value Helpers -extension ShadowAnimationBugExample { - private func targetCornerRadius(for startCornerRadius: CGFloat) -> CGFloat { - return startCornerRadius == Constants.expandedCornerRadius - ? Constants.collapsedCornerRadius : Constants.expandedCornerRadius - } - - private func targetHeight(for startHeight: CGFloat) -> CGFloat { - return startHeight == Constants.expandedHeight - ? Constants.collapsedHeight : Constants.expandedHeight - } - - private func targetWidth(for startWidth: CGFloat) -> CGFloat { - return startWidth == Constants.expandedWidth - ? Constants.collapsedWidth : Constants.expandedWidth - } - -} - -// MARK: Catalog by Convensions -@available(iOS 12.0, *) -extension ShadowAnimationBugExample { - - @objc class func catalogMetadata() -> [String: Any] { - return [ - "breadcrumbs": ["Shadow", "New Shadow animation bug"], - "primaryDemo": true, - "presentable": false, - "debug": false, - "skip_snapshots": true, // There are continuous running animations in this bug. - ] - } - - @objc class func minimumOSVersion() -> OperatingSystemVersion { - return OperatingSystemVersion(majorVersion: 12, minorVersion: 0, patchVersion: 0) - } -} diff --git a/components/Shadow/src/Animations/UIView+MDCShadowAnimations.h b/components/Shadow/src/Animations/UIView+MDCShadowAnimations.h deleted file mode 100644 index 81df168e66f..00000000000 --- a/components/Shadow/src/Animations/UIView+MDCShadowAnimations.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2022-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 - -/** - Allows animation of shadows for changes applied to a view's bounds and layer.cornerRadius. - Use these implementations instead of UIView.animate when modifying these properties. - These implementations do not support the use of a delay parameter. - */ -@interface UIView (MDCShadowAnimations) - -/** - Animates the corner radius of a UIView's layer to a new CGFloat value - Accounts for shadow animation - - @param value The new corner radius that will be applied to the UIView's layer - @param duration The duration of the animation - @param options UIViewAnimatingOptions - @param timingFunction The CAMediaTimingFunction for the animation - @param completion Animation completion handler - */ -- (void)mdc_animateCornerRadiusToValue:(CGFloat)value - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion; - -/** - Animates the bounds of a UIView to a new CGRect value - Accounts for shadow animation - - @param rect The new bounds that will be applied to the UIView - @param duration The duration of the animation - @param options UIViewAnimatingOptions - @param timingFunction The CAMediaTimingFunction for the animation - @param completion Animation completion handler - */ -- (void)mdc_animateBoundsToRect:(CGRect)rect - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion; - -/** - Animates the bounds of a UIView to a new CGRect value - Animates the center of a UIView to a new CGPoint value - Accounts for shadow animation - - @param rect The new bounds that will be applied to the UIView - @param center The new center that will be applied to the UIView - @param duration The duration of the animation - @param options UIViewAnimatingOptions - @param timingFunction The CAMediaTimingFunction for the animation - @param completion Animation completion handler - */ -- (void)mdc_animateBoundsWithCenterToRect:(CGRect)rect - center:(CGPoint)center - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion; - -/** - Animates the bounds of a UIView to a new CGRect value - Animates the corner radius of a UIView's layer to a new CGFloat value - Accounts for shadow animation - - @param rect The new bounds that will be applied to the UIView - @param cornerRadius The new corner radius that will be applied to the UIView's layer - @param duration The duration of the animation - @param options UIViewAnimatingOptions - @param timingFunction The CAMediaTimingFunction for the animation - @param completion Animation completion handler - */ -- (void)mdc_animateBoundsWithCornerRadiusToRect:(CGRect)rect - cornerRadius:(CGFloat)cornerRadius - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion; - -/** - Animates the bounds of a UIView to a new CGRect value - Animates the center of a UIView to a new CGPoint value - Animates the corner radius of a UIView's layer to a new CGFloat value - Accounts for shadow animation - - @param rect The new bounds that will be applied to the UIView - @param center The new center that will be applied to the UIView - @param cornerRadius The new corner radius that will be applied to the UIView's layer - @param duration The duration of the animation - @param options UIViewAnimatingOptions - @param timingFunction The CAMediaTimingFunction for the animation - @param completion Animation completion handler - */ -- (void)mdc_animateBoundsWithCenterAndCornerRadiusToRect:(CGRect)rect - center:(CGPoint)center - cornerRadius:(CGFloat)cornerRadius - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion; -@end diff --git a/components/Shadow/src/Animations/UIView+MDCShadowAnimations.m b/components/Shadow/src/Animations/UIView+MDCShadowAnimations.m deleted file mode 100644 index baf385b18f3..00000000000 --- a/components/Shadow/src/Animations/UIView+MDCShadowAnimations.m +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2022-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 -#import -#import "UIView+MDCShadowAnimations.h" // SubtargetImport - -@implementation UIView (MDCShadowAnimations) - -#pragma mark - Public - -- (void)mdc_animateCornerRadiusToValue:(CGFloat)value - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion { - [self mdc_transactionAnimationWithRect:nil - animationKey:@"shadowAnimation" - centerValue:nil - cornerRadius:@(value) - duration:duration - options:options - pathKey:@"shadowPath" - timingFunction:timingFunction - completion:completion]; -} - -- (void)mdc_animateBoundsToRect:(CGRect)rect - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion { - [self mdc_transactionAnimationWithRect:[NSValue valueWithCGRect:rect] - animationKey:@"shadowAnimation" - centerValue:nil - cornerRadius:nil - duration:duration - options:options - pathKey:@"shadowPath" - timingFunction:timingFunction - completion:completion]; -} - -- (void)mdc_animateBoundsWithCenterToRect:(CGRect)rect - center:(CGPoint)center - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion { - [self mdc_transactionAnimationWithRect:[NSValue valueWithCGRect:rect] - animationKey:@"shadowAnimation" - centerValue:[NSValue valueWithCGPoint:center] - cornerRadius:nil - duration:duration - options:options - pathKey:@"shadowPath" - timingFunction:timingFunction - completion:completion]; -} - -- (void)mdc_animateBoundsWithCornerRadiusToRect:(CGRect)rect - cornerRadius:(CGFloat)cornerRadius - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion { - [self mdc_transactionAnimationWithRect:[NSValue valueWithCGRect:rect] - animationKey:@"shadowAnimation" - centerValue:nil - cornerRadius:@(cornerRadius) - duration:duration - options:options - pathKey:@"shadowPath" - timingFunction:timingFunction - completion:completion]; -} - -- (void)mdc_animateBoundsWithCenterAndCornerRadiusToRect:(CGRect)rect - center:(CGPoint)center - cornerRadius:(CGFloat)cornerRadius - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion { - [self mdc_transactionAnimationWithRect:[NSValue valueWithCGRect:rect] - animationKey:@"shadowAnimation" - centerValue:[NSValue valueWithCGPoint:center] - cornerRadius:@(cornerRadius) - duration:duration - options:options - pathKey:@"shadowPath" - timingFunction:timingFunction - completion:completion]; -} - -#pragma mark - Private - -- (void)mdc_transactionAnimationWithRect:(nullable NSValue *)rectValue - animationKey:(NSString *)animationKey - centerValue:(nullable NSValue *)centerValue - cornerRadius:(nullable NSNumber *)cornerRadiusNumber - duration:(CGFloat)duration - options:(UIViewAnimationOptions)options - pathKey:(NSString *)pathKey - timingFunction:(CAMediaTimingFunction *)timingFunction - completion:(void (^)(BOOL finished))completion { - CABasicAnimation *shadowAnimation = [CABasicAnimation animationWithKeyPath:pathKey]; - - CGFloat targetCornerRadius = - cornerRadiusNumber ? [cornerRadiusNumber floatValue] : self.layer.cornerRadius; - CGRect targetRect = rectValue ? rectValue.CGRectValue : self.bounds; - CGPoint targetCenter = centerValue ? centerValue.CGPointValue : self.center; - - shadowAnimation.fromValue = [UIBezierPath bezierPathWithRoundedRect:self.bounds - cornerRadius:self.layer.cornerRadius]; - - shadowAnimation.toValue = [UIBezierPath bezierPathWithRoundedRect:targetRect - cornerRadius:targetCornerRadius]; - - [CATransaction begin]; - [CATransaction setAnimationDuration:duration]; - [CATransaction setAnimationTimingFunction:timingFunction]; - - /// delay must be 0 for this CATransaction implementation to work. - [UIView animateWithDuration:duration - delay:0.0 - options:options - animations:^{ - if (cornerRadiusNumber) { - self.layer.cornerRadius = targetCornerRadius; - } - - if (rectValue) { - self.bounds = targetRect; - } - - /// self.center cannot be used to check against whether or not the center - /// should change. Optional center parameter must be passed in, as self.center - /// could potentially change while animating. - if (centerValue) { - self.center = targetCenter; - } - - /// If no rect value is passed, manually call setNeedsLayout. - /// This is needed for a corner radius change when size is not changed. - /// setNeedsLayout is otherwise called in MDCShadowLayer's setBounds. - if (!rectValue) { - [self setNeedsLayout]; - [self layoutIfNeeded]; - } - } - completion:completion]; - - /// Update the animation associated with the layer. - /// Since there is only one animation per key, this does not result in multiple shadow animations. - [self.layer addAnimation:shadowAnimation forKey:animationKey]; - - [CATransaction commit]; -} - -@end