mirror of
https://github.com/material-components/material-components-ios.git
synced 2026-01-22 05:02:22 +08:00
397 lines
16 KiB
Objective-C
397 lines
16 KiB
Objective-C
// 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 "MaterialPalettes.h"
|
|
#import "MaterialProgressView.h"
|
|
#import "MaterialColorScheme.h"
|
|
#import "MaterialTypographyScheme.h"
|
|
|
|
static const CGFloat MDCProgressViewAnimationDuration = 1;
|
|
static const CGFloat MDCProgressViewIndeterminateAnimationDuration = 4;
|
|
|
|
@interface ProgressViewExample : UIViewController
|
|
|
|
@property(nonatomic, strong) UIView *container;
|
|
|
|
@property(nonatomic, strong) MDCProgressView *stockProgressView;
|
|
@property(nonatomic, strong) UILabel *stockProgressLabel;
|
|
|
|
@property(nonatomic, strong) MDCProgressView *tintedProgressView;
|
|
@property(nonatomic, strong) UILabel *tintedProgressLabel;
|
|
|
|
@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;
|
|
|
|
@property(nonatomic, strong) MDCProgressView *backwardProgressAnimateView;
|
|
@property(nonatomic, strong) UILabel *backwardProgressAnimateLabel;
|
|
|
|
@property(nonatomic, strong) MDCProgressView *indeterminateProgressView;
|
|
@property(nonatomic, strong) UILabel *indeterminateProgressLabel;
|
|
|
|
@property(nonatomic, strong) MDCSemanticColorScheme *colorScheme;
|
|
@property(nonatomic, strong) MDCTypographyScheme *typographyScheme;
|
|
|
|
@end
|
|
|
|
@implementation ProgressViewExample
|
|
|
|
- (void)setupProgressViews {
|
|
_stockProgressView = [[MDCProgressView alloc] init];
|
|
_stockProgressView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.container addSubview:_stockProgressView];
|
|
// Hide the progress view at setup time.
|
|
_stockProgressView.hidden = YES;
|
|
|
|
_tintedProgressView = [[MDCProgressView alloc] init];
|
|
_tintedProgressView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.container addSubview:_tintedProgressView];
|
|
_tintedProgressView.progressTintColor = self.colorScheme.primaryColor;
|
|
_tintedProgressView.trackTintColor =
|
|
[self.colorScheme.primaryColor colorWithAlphaComponent:(CGFloat)0.24];
|
|
// Hide the progress view at setup time.
|
|
_tintedProgressView.hidden = YES;
|
|
|
|
_fullyColoredProgressView = [[MDCProgressView alloc] init];
|
|
_fullyColoredProgressView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.container addSubview:_fullyColoredProgressView];
|
|
_fullyColoredProgressView.progressTintColor = MDCPalette.greenPalette.tint500;
|
|
_fullyColoredProgressView.trackTintColor = MDCPalette.yellowPalette.tint500;
|
|
// 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];
|
|
// Have a non-zero progress at setup time.
|
|
_backwardProgressResetView.progress = (float)0.33;
|
|
|
|
_backwardProgressAnimateView = [[MDCProgressView alloc] init];
|
|
_backwardProgressAnimateView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
_backwardProgressAnimateView.backwardProgressAnimationMode =
|
|
MDCProgressViewBackwardAnimationModeAnimate;
|
|
[self.container addSubview:_backwardProgressAnimateView];
|
|
// Have a non-zero progress at setup time.
|
|
_backwardProgressAnimateView.progress = (float)0.33;
|
|
|
|
_indeterminateProgressView = [[MDCProgressView alloc] init];
|
|
_indeterminateProgressView.mode = MDCProgressViewModeIndeterminate;
|
|
_indeterminateProgressView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
_indeterminateProgressView.progressTintColor = self.colorScheme.primaryColor;
|
|
_indeterminateProgressView.trackTintColor =
|
|
[self.colorScheme.primaryColor colorWithAlphaComponent:(CGFloat)0.24];
|
|
[self.container addSubview:_indeterminateProgressView];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation ProgressViewExample (Supplemental)
|
|
|
|
- (void)dealloc {
|
|
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
|
}
|
|
|
|
- (void)viewDidLoad {
|
|
[super viewDidLoad];
|
|
|
|
if (!self.colorScheme) {
|
|
self.colorScheme =
|
|
[[MDCSemanticColorScheme alloc] initWithDefaults:MDCColorSchemeDefaultsMaterial201804];
|
|
}
|
|
if (!self.typographyScheme) {
|
|
self.typographyScheme = [[MDCTypographyScheme alloc] init];
|
|
}
|
|
|
|
self.title = @"Progress View";
|
|
self.view.backgroundColor = self.colorScheme.backgroundColor;
|
|
|
|
[self setupContainer];
|
|
[self setupProgressViews];
|
|
[self setupLabels];
|
|
[self setupConstraints];
|
|
|
|
self.navigationItem.rightBarButtonItem =
|
|
[[UIBarButtonItem alloc] initWithTitle:@"Animate"
|
|
style:UIBarButtonItemStylePlain
|
|
target:self
|
|
action:@selector(didPressAnimateButton:)];
|
|
self.navigationItem.rightBarButtonItem.accessibilityIdentifier = @"animate_button";
|
|
}
|
|
|
|
- (void)viewDidLayoutSubviews {
|
|
[super viewDidLayoutSubviews];
|
|
[self positionContainer];
|
|
}
|
|
|
|
- (void)setupContainer {
|
|
self.container = [[UIView alloc] initWithFrame:self.view.bounds];
|
|
[self.view addSubview:self.container];
|
|
}
|
|
|
|
- (void)positionContainer {
|
|
CGFloat originX = CGRectGetMinX(self.view.bounds) + self.view.layoutMargins.left;
|
|
CGFloat originY = CGRectGetMinY(self.view.bounds) + self.view.layoutMargins.top;
|
|
CGFloat width =
|
|
self.view.bounds.size.width - (self.view.layoutMargins.left + self.view.layoutMargins.right);
|
|
CGFloat height =
|
|
self.view.bounds.size.height - (self.view.layoutMargins.top + self.view.layoutMargins.bottom);
|
|
CGRect frame = CGRectMake(originX, originY, width, height);
|
|
self.container.frame = frame;
|
|
}
|
|
|
|
- (void)setupLabels {
|
|
_stockProgressLabel = [[UILabel alloc] init];
|
|
_stockProgressLabel.text = @"Progress";
|
|
_stockProgressLabel.font = self.typographyScheme.caption;
|
|
_stockProgressLabel.textColor = self.colorScheme.onBackgroundColor;
|
|
_stockProgressLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.container addSubview:_stockProgressLabel];
|
|
|
|
_tintedProgressLabel = [[UILabel alloc] init];
|
|
_tintedProgressLabel.text = @"Progress with progress tint";
|
|
_tintedProgressLabel.font = self.typographyScheme.caption;
|
|
_tintedProgressLabel.textColor = self.colorScheme.onBackgroundColor;
|
|
_tintedProgressLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.container addSubview:_tintedProgressLabel];
|
|
|
|
_fullyColoredProgressLabel = [[UILabel alloc] init];
|
|
_fullyColoredProgressLabel.text = @"Progress with custom colors";
|
|
_fullyColoredProgressLabel.font = self.typographyScheme.caption;
|
|
_fullyColoredProgressLabel.textColor = self.colorScheme.onBackgroundColor;
|
|
_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;
|
|
_backwardProgressResetLabel.textColor = self.colorScheme.onBackgroundColor;
|
|
_backwardProgressResetLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.container addSubview:_backwardProgressResetLabel];
|
|
|
|
_backwardProgressAnimateLabel = [[UILabel alloc] init];
|
|
_backwardProgressAnimateLabel.text = @"Backward progress (animate)";
|
|
_backwardProgressAnimateLabel.font = self.typographyScheme.caption;
|
|
_backwardProgressAnimateLabel.textColor = self.colorScheme.onBackgroundColor;
|
|
_backwardProgressAnimateLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.container addSubview:_backwardProgressAnimateLabel];
|
|
|
|
_indeterminateProgressLabel = [[UILabel alloc] init];
|
|
_indeterminateProgressLabel.text = @"Indeterminate progress";
|
|
_indeterminateProgressLabel.font = self.typographyScheme.caption;
|
|
_indeterminateProgressLabel.textColor = self.colorScheme.onBackgroundColor;
|
|
_indeterminateProgressLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self.container addSubview:_indeterminateProgressLabel];
|
|
}
|
|
|
|
- (void)setupConstraints {
|
|
NSDictionary *views = @{
|
|
@"container" : _container,
|
|
@"stockView" : _stockProgressView,
|
|
@"stockLabel" : _stockProgressLabel,
|
|
@"tintedView" : _tintedProgressView,
|
|
@"tintedLabel" : _tintedProgressLabel,
|
|
@"coloredView" : _fullyColoredProgressView,
|
|
@"coloredLabel" : _fullyColoredProgressLabel,
|
|
@"gradientView" : _gradientColoredProgressView,
|
|
@"gradientLabel" : _gradientColoredProgressLabel,
|
|
@"backwardResetView" : _backwardProgressResetView,
|
|
@"backwardResetLabel" : _backwardProgressResetLabel,
|
|
@"backwardAnimateView" : _backwardProgressAnimateView,
|
|
@"backwardAnimateLabel" : _backwardProgressAnimateLabel,
|
|
@"indeterminateView" : _indeterminateProgressView,
|
|
@"indeterminateLabel" : _indeterminateProgressLabel,
|
|
};
|
|
NSDictionary *metrics = @{
|
|
@"t" : @20,
|
|
@"p" : @0,
|
|
@"s" : @40,
|
|
@"h" : @2,
|
|
};
|
|
|
|
NSArray *verticalConstraints = [NSLayoutConstraint
|
|
constraintsWithVisualFormat:@"V:|-(t)-"
|
|
"[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]-(s)-"
|
|
"[indeterminateView(==h)]-(p)-[indeterminateLabel]"
|
|
options:0
|
|
metrics:metrics
|
|
views:views];
|
|
[self.view addConstraints:verticalConstraints];
|
|
|
|
NSMutableArray *horizontalConstraints = [NSMutableArray array];
|
|
NSArray *horizontalVisualFormats = @[
|
|
@"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)-[indeterminateView]-(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)-|",
|
|
@"H:|-(p)-[indeterminateLabel]-(p)-|",
|
|
];
|
|
for (NSString *format in horizontalVisualFormats) {
|
|
[horizontalConstraints
|
|
addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:format
|
|
options:0
|
|
metrics:metrics
|
|
views:views]];
|
|
}
|
|
[self.view addConstraints:horizontalConstraints];
|
|
}
|
|
|
|
- (void)didPressAnimateButton:(UIButton *)sender {
|
|
sender.enabled = NO;
|
|
[self animateStep1:_stockProgressView];
|
|
[self animateStep1:_tintedProgressView];
|
|
[self animateStep1:_fullyColoredProgressView];
|
|
[self animateStep1:_gradientColoredProgressView];
|
|
[self animateBackwardProgressResetViewWithCountdown:4];
|
|
[self animateBackwardProgressAnimateViewWithCountdown:4
|
|
completion:^(BOOL ignored) {
|
|
sender.enabled = YES;
|
|
}];
|
|
[self animateIndeterminateProgressBarWithCountdown:1];
|
|
}
|
|
|
|
- (void)animateStep1:(MDCProgressView *)progressView {
|
|
progressView.progress = 0;
|
|
__weak MDCProgressView *weakProgressView = progressView;
|
|
[progressView setHidden:NO
|
|
animated:YES
|
|
completion:^(BOOL finished) {
|
|
[self performSelector:@selector(animateStep2:)
|
|
withObject:weakProgressView
|
|
afterDelay:MDCProgressViewAnimationDuration];
|
|
}];
|
|
}
|
|
|
|
- (void)animateStep2:(MDCProgressView *)progressView {
|
|
[progressView setProgress:0.5 animated:YES completion:nil];
|
|
[self performSelector:@selector(animateStep3:)
|
|
withObject:progressView
|
|
afterDelay:MDCProgressViewAnimationDuration];
|
|
}
|
|
|
|
- (void)animateStep3:(MDCProgressView *)progressView {
|
|
[progressView setProgress:1 animated:YES completion:nil];
|
|
[self performSelector:@selector(animateStep4:)
|
|
withObject:progressView
|
|
afterDelay:MDCProgressViewAnimationDuration];
|
|
}
|
|
|
|
- (void)animateStep4:(MDCProgressView *)progressView {
|
|
[progressView setHidden:YES animated:YES completion:nil];
|
|
}
|
|
|
|
- (void)animateBackwardProgressResetViewWithCountdown:(NSInteger)remainingCounts {
|
|
--remainingCounts;
|
|
__weak ProgressViewExample *weakSelf = self;
|
|
|
|
[_backwardProgressResetView setProgress:1 - _backwardProgressResetView.progress
|
|
animated:YES
|
|
completion:nil];
|
|
if (remainingCounts > 0) {
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
|
|
(int64_t)(MDCProgressViewAnimationDuration * NSEC_PER_SEC)),
|
|
dispatch_get_main_queue(), ^{
|
|
[weakSelf animateBackwardProgressResetViewWithCountdown:remainingCounts];
|
|
});
|
|
}
|
|
}
|
|
|
|
- (void)animateBackwardProgressAnimateViewWithCountdown:(NSInteger)remainingCounts
|
|
completion:(void (^)(BOOL))completion {
|
|
--remainingCounts;
|
|
__weak ProgressViewExample *weakSelf = self;
|
|
|
|
[_backwardProgressAnimateView setProgress:1 - _backwardProgressAnimateView.progress
|
|
animated:YES
|
|
completion:remainingCounts == 0 ? completion : nil];
|
|
if (remainingCounts) {
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
|
|
(int64_t)(MDCProgressViewAnimationDuration * NSEC_PER_SEC)),
|
|
dispatch_get_main_queue(), ^{
|
|
[weakSelf animateBackwardProgressAnimateViewWithCountdown:remainingCounts
|
|
completion:completion];
|
|
});
|
|
}
|
|
}
|
|
|
|
- (void)animateIndeterminateProgressBarWithCountdown:(NSInteger)remainingCounts {
|
|
__weak ProgressViewExample *weakSelf = self;
|
|
|
|
if (!_indeterminateProgressView.animating) {
|
|
[_indeterminateProgressView startAnimating];
|
|
}
|
|
|
|
if (remainingCounts > 0) {
|
|
dispatch_after(
|
|
dispatch_time(DISPATCH_TIME_NOW,
|
|
(int64_t)(MDCProgressViewIndeterminateAnimationDuration * NSEC_PER_SEC)),
|
|
dispatch_get_main_queue(), ^{
|
|
[weakSelf animateIndeterminateProgressBarWithCountdown:remainingCounts - 1];
|
|
});
|
|
} else {
|
|
[_indeterminateProgressView stopAnimating];
|
|
}
|
|
}
|
|
|
|
#pragma mark - CatalogByConvention
|
|
|
|
+ (NSDictionary *)catalogMetadata {
|
|
return @{
|
|
@"breadcrumbs" : @[ @"Progress View", @"Progress View" ],
|
|
@"description" : @"Progress indicators display the length of a process or express an "
|
|
@"unspecified wait time.",
|
|
@"primaryDemo" : @YES,
|
|
@"presentable" : @YES,
|
|
};
|
|
}
|
|
|
|
@end
|