Navigation Menu

Skip to content

Commit

Permalink
[ProgressView] Add support for gradient progress bar.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 310977753
  • Loading branch information
wenyuzhang666 authored and galiak11 committed May 12, 2020
1 parent 39e9475 commit 9c480c2
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 8 deletions.
28 changes: 27 additions & 1 deletion components/ProgressView/examples/ProgressViewExample.m
Expand Up @@ -14,9 +14,9 @@

#import <UIKit/UIKit.h>

#import "MaterialColorScheme.h"
#import "MaterialPalettes.h"
#import "MaterialProgressView.h"
#import "MaterialColorScheme.h"
#import "MaterialTypographyScheme.h"

static const CGFloat MDCProgressViewAnimationDuration = 1;
Expand All @@ -34,6 +34,9 @@ @interface ProgressViewExample : UIViewController
@property(nonatomic, strong) MDCProgressView *fullyColoredProgressView;
@property(nonatomic, strong) UILabel *fullyColoredProgressLabel;

@property(nonatomic, strong) MDCProgressView *gradientColoredProgressView;
@property(nonatomic, strong) UILabel *gradientColoredProgressLabel;

@property(nonatomic, strong) MDCProgressView *backwardProgressResetView;
@property(nonatomic, strong) UILabel *backwardProgressResetLabel;

Expand Down Expand Up @@ -71,6 +74,16 @@ - (void)setupProgressViews {
// Hide the progress view at setup time.
_fullyColoredProgressView.hidden = YES;

_gradientColoredProgressView = [[MDCProgressView alloc] init];
_gradientColoredProgressView.translatesAutoresizingMaskIntoConstraints = NO;
[self.container addSubview:_gradientColoredProgressView];
_gradientColoredProgressView.progressTintColors = @[
(id)MDCPalette.greenPalette.tint500.CGColor, (id)MDCPalette.bluePalette.tint500.CGColor,
(id)MDCPalette.redPalette.tint500.CGColor
];
_gradientColoredProgressView.trackTintColor = MDCPalette.yellowPalette.tint500;
_gradientColoredProgressView.progress = 0.33f;

_backwardProgressResetView = [[MDCProgressView alloc] init];
_backwardProgressResetView.translatesAutoresizingMaskIntoConstraints = NO;
[self.container addSubview:_backwardProgressResetView];
Expand Down Expand Up @@ -164,6 +177,13 @@ - (void)setupLabels {
_fullyColoredProgressLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.container addSubview:_fullyColoredProgressLabel];

_gradientColoredProgressLabel = [[UILabel alloc] init];
_gradientColoredProgressLabel.text = @"Progress with gradient colors";
_gradientColoredProgressLabel.font = self.typographyScheme.caption;
_gradientColoredProgressLabel.textColor = self.colorScheme.onBackgroundColor;
_gradientColoredProgressLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.container addSubview:_gradientColoredProgressLabel];

_backwardProgressResetLabel = [[UILabel alloc] init];
_backwardProgressResetLabel.text = @"Backward progress (reset)";
_backwardProgressResetLabel.font = self.typographyScheme.caption;
Expand All @@ -188,6 +208,8 @@ - (void)setupConstraints {
@"tintedLabel" : _tintedProgressLabel,
@"coloredView" : _fullyColoredProgressView,
@"coloredLabel" : _fullyColoredProgressLabel,
@"gradientView" : _gradientColoredProgressView,
@"gradientLabel" : _gradientColoredProgressLabel,
@"backwardResetView" : _backwardProgressResetView,
@"backwardResetLabel" : _backwardProgressResetLabel,
@"backwardAnimateView" : _backwardProgressAnimateView,
Expand All @@ -205,6 +227,7 @@ - (void)setupConstraints {
"[stockView(==h)]-(p)-[stockLabel]-(s)-"
"[tintedView(==h)]-(p)-[tintedLabel]-(s)-"
"[coloredView(==h)]-(p)-[coloredLabel]-(s)-"
"[gradientView(==h)]-(p)-[gradientLabel]-(s)-"
"[backwardResetView(==h)]-(p)-[backwardResetLabel]-(s)-"
"[backwardAnimateView(==h)]-(p)-[backwardAnimateLabel]"
options:0
Expand All @@ -217,11 +240,13 @@ - (void)setupConstraints {
@"H:|-(p)-[stockView]-(p)-|",
@"H:|-(p)-[tintedView]-(p)-|",
@"H:|-(p)-[coloredView]-(p)-|",
@"H:|-(p)-[gradientView]-(p)-|",
@"H:|-(p)-[backwardResetView]-(p)-|",
@"H:|-(p)-[backwardAnimateView]-(p)-|",
@"H:|-(p)-[stockLabel]-(p)-|",
@"H:|-(p)-[tintedLabel]-(p)-|",
@"H:|-(p)-[coloredLabel]-(p)-|",
@"H:|-(p)-[gradientLabel]-(p)-|",
@"H:|-(p)-[backwardResetLabel]-(p)-|",
@"H:|-(p)-[backwardAnimateLabel]-(p)-|",
];
Expand All @@ -240,6 +265,7 @@ - (void)didPressAnimateButton:(UIButton *)sender {
[self animateStep1:_stockProgressView];
[self animateStep1:_tintedProgressView];
[self animateStep1:_fullyColoredProgressView];
[self animateStep1:_gradientColoredProgressView];
[self animateBackwardProgressResetViewWithCountdown:4];
[self animateBackwardProgressAnimateViewWithCountdown:4
completion:^(BOOL ignored) {
Expand Down
10 changes: 10 additions & 0 deletions components/ProgressView/src/MDCProgressView.h
Expand Up @@ -39,6 +39,16 @@ IB_DESIGNABLE
*/
@property(nonatomic, strong, nullable) UIColor *progressTintColor UI_APPEARANCE_SELECTOR;

/**
An array of CGColorRef objects used to defining the color of each gradient stop.
All colors are spread uniformly across the range.
Setting @c progressTintColor resets this property to @c nil.
The default is nil.
*/
@property(nonatomic, copy, nullable) NSArray *progressTintColors;

/**
The color shown for the portion of the progress view that is not filled.
Expand Down
30 changes: 23 additions & 7 deletions components/ProgressView/src/MDCProgressView.m
Expand Up @@ -17,6 +17,7 @@
#include <tgmath.h>

#import "MaterialPalettes.h"
#import "MDCProgressGradientView.h"
#import "MaterialProgressViewStrings.h"
#import "MaterialProgressViewStrings_table.h"
#import "MaterialMath.h"
Expand All @@ -35,7 +36,7 @@
static NSString *const kBundle = @"MaterialProgressView.bundle";

@interface MDCProgressView ()
@property(nonatomic, strong) UIView *progressView;
@property(nonatomic, strong) MDCProgressGradientView *progressView;
@property(nonatomic, strong) UIView *trackView;
@property(nonatomic) BOOL animatingHide;
// A UIProgressView to return the same format for the accessibility value. For example, when
Expand Down Expand Up @@ -74,10 +75,12 @@ - (void)commonMDCProgressViewInit {
_trackView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self addSubview:_trackView];

_progressView = [[UIView alloc] initWithFrame:CGRectZero];
_progressView = [[MDCProgressGradientView alloc] initWithFrame:CGRectZero];
[self addSubview:_progressView];

_progressView.backgroundColor = MDCProgressViewDefaultTintColor();
_progressView.colors = @[
(id)MDCProgressViewDefaultTintColor().CGColor, (id)MDCProgressViewDefaultTintColor().CGColor
];
_trackView.backgroundColor =
[[self class] defaultTrackTintColorForProgressTintColor:MDCProgressViewDefaultTintColor()];
}
Expand All @@ -100,17 +103,30 @@ - (void)layoutSubviews {
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];

if (self.progressTintColor) {
self.progressView.colors =
@[ (id)self.progressTintColor.CGColor, (id)self.progressTintColor.CGColor ];
}

if (self.traitCollectionDidChangeBlock) {
self.traitCollectionDidChangeBlock(self, previousTraitCollection);
}
}

- (UIColor *)progressTintColor {
return self.progressView.backgroundColor;
- (void)setProgressTintColor:(UIColor *)progressTintColor {
_progressTintColor = progressTintColor;
_progressTintColors = nil;
if (progressTintColor != nil) {
self.progressView.colors = @[ (id)progressTintColor.CGColor, (id)progressTintColor.CGColor ];
} else {
self.progressView.colors = nil;
}
}

- (void)setProgressTintColor:(UIColor *)progressTintColor {
self.progressView.backgroundColor = progressTintColor;
- (void)setProgressTintColors:(NSArray *)progressTintColors {
_progressTintColors = [progressTintColors copy];
_progressTintColor = nil;
self.progressView.colors = _progressTintColors;
}

- (UIColor *)trackTintColor {
Expand Down
29 changes: 29 additions & 0 deletions components/ProgressView/src/private/MDCProgressGradientView.h
@@ -0,0 +1,29 @@
// Copyright 2020-present the Material Components for iOS authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#import <UIKit/UIKit.h>

/**
A gradient view used for an MDCProgressView's progress bar.
*/
__attribute__((objc_subclassing_restricted)) @interface MDCProgressGradientView : UIView

/**
An array of CGColorRef objects defining the color of each gradient stop
Defaults to nil.
*/
@property(nonatomic, nullable, copy) NSArray *colors;

@end
64 changes: 64 additions & 0 deletions components/ProgressView/src/private/MDCProgressGradientView.m
@@ -0,0 +1,64 @@
// 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 "MDCProgressGradientView.h"

@interface MDCProgressGradientView ()

@property(nonatomic, readonly) CAGradientLayer *gradientLayer;

@end

@implementation MDCProgressGradientView

- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonMDCProgressGradientViewInit];
}
return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self commonMDCProgressGradientViewInit];
}
return self;
}

- (void)commonMDCProgressGradientViewInit {
self.gradientLayer.startPoint = CGPointMake(0.0f, 0.5f);
self.gradientLayer.endPoint = CGPointMake(1.0f, 0.5f);
}

- (void)setColors:(NSArray *)colors {
self.gradientLayer.colors = colors;
}

- (NSArray *)colors {
return self.gradientLayer.colors;
}

+ (Class)layerClass {
return [CAGradientLayer class];
}

#pragma mark - Private Helpers

- (CAGradientLayer *)gradientLayer {
return (CAGradientLayer *)self.layer;
}

@end
Expand Up @@ -134,4 +134,85 @@ - (void)testProgress100RTL {
[self generateSnapshotAndVerifyForView:self.progressView];
}

- (void)testGradientProgress000LTR {
// Given
self.progressView.progressTintColors = @[
(id)UIColor.greenColor.CGColor, (id)UIColor.blueColor.CGColor, (id)UIColor.redColor.CGColor
];

// When
self.progressView.progress = 0;

// Then
[self generateSnapshotAndVerifyForView:self.progressView];
}

- (void)testGradientProgress050LTR {
// Given
self.progressView.progressTintColors = @[
(id)UIColor.greenColor.CGColor, (id)UIColor.blueColor.CGColor, (id)UIColor.redColor.CGColor
];

// When
self.progressView.progress = 0.5f;

// Then
[self generateSnapshotAndVerifyForView:self.progressView];
}

- (void)testGradientProgress100LTR {
// Given
self.progressView.progressTintColors = @[
(id)UIColor.greenColor.CGColor, (id)UIColor.blueColor.CGColor, (id)UIColor.redColor.CGColor
];

// When
self.progressView.progress = 1;

// Then
[self generateSnapshotAndVerifyForView:self.progressView];
}

- (void)testGradientProgress000RTL {
// Given
self.progressView.progressTintColors = @[
(id)UIColor.greenColor.CGColor, (id)UIColor.blueColor.CGColor, (id)UIColor.redColor.CGColor
];

// When
[self changeViewToRTL:self.progressView];
self.progressView.progress = 0;

// Then
[self generateSnapshotAndVerifyForView:self.progressView];
}

- (void)testGradientProgress050RTL {
// Given
self.progressView.progressTintColors = @[
(id)UIColor.greenColor.CGColor, (id)UIColor.blueColor.CGColor, (id)UIColor.redColor.CGColor
];

// When
[self changeViewToRTL:self.progressView];
self.progressView.progress = 0.5f;

// Then
[self generateSnapshotAndVerifyForView:self.progressView];
}

- (void)testGradientProgress100RTL {
// Given
self.progressView.progressTintColors = @[
(id)UIColor.greenColor.CGColor, (id)UIColor.blueColor.CGColor, (id)UIColor.redColor.CGColor
];

// When
[self changeViewToRTL:self.progressView];
self.progressView.progress = 1;

// Then
[self generateSnapshotAndVerifyForView:self.progressView];
}

@end

0 comments on commit 9c480c2

Please sign in to comment.