mirror of
https://github.com/material-components/material-components-ios.git
synced 2026-02-20 08:27:32 +08:00
* [Themes] Remove unnecessary imports. * [TextFields] Remove unnecessary imports. * [Typography] Do not use an umbrella header inside of a component. * [Snackbar] Do not use self umbrella header. * [ActivityIndicator] Do not use self umbrella header. * [AppBar] Use umbrella headers. * [AppBar] Remove self import header. * [ButtonBar] Removed self umbrella header imports. * [Buttons] Removed self umbrella header imports. * [Collections] Update imports. * [Dialogs] Moved import into an m file. * [Collections] Fixed imports. * [FeatureHighlight] Removed self umbrealla imports. * [HeaderStackView] Reordered imports. * [Ink] Replaced imports with forward declarations. * [Slider] Replaced self umbrella import use. * [Snackbar] Removed self umbrella header import. * [Tabs] Changed math import. Replaced self umbrella header import. * [Icons] Removed unnecessary imports. * [Overlay] Replaced umbrella header import. * [ShapeLibrary] Replace Shapes imports with an umbrella header. * [Shapes] Replaced imports with forward declarations. * [AppBar] Replace import with a forward declaration. * [Examples] Updated imports. * Fixed conflicting imports * Added space between different import categories
221 lines
7.9 KiB
Objective-C
221 lines
7.9 KiB
Objective-C
/*
|
|
Copyright 2015-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 "MaterialFlexibleHeader.h"
|
|
#import "supplemental/FlexibleHeaderConfiguratorSupplemental.h"
|
|
|
|
@interface FlexibleHeaderConfiguratorExample () <MDCFlexibleHeaderViewLayoutDelegate>
|
|
@property(nonatomic) BOOL overrideStatusBarHidden;
|
|
@end
|
|
|
|
@implementation FlexibleHeaderConfiguratorExample
|
|
|
|
// Invoked when the user has changed a control's value.
|
|
- (void)field:(FlexibleHeaderConfiguratorField)field didChangeValue:(NSNumber *)value {
|
|
MDCFlexibleHeaderView *headerView = self.fhvc.headerView;
|
|
switch (field) {
|
|
// Basic behavior
|
|
|
|
case FlexibleHeaderConfiguratorFieldCanOverExtend:
|
|
headerView.canOverExtend = [value boolValue];
|
|
break;
|
|
|
|
case FlexibleHeaderConfiguratorFieldInFrontOfInfiniteContent:
|
|
headerView.inFrontOfInfiniteContent = [value boolValue];
|
|
break;
|
|
|
|
case FlexibleHeaderConfiguratorFieldHideStatusBar: {
|
|
self.overrideStatusBarHidden = [value boolValue];
|
|
|
|
BOOL statusBarCanBeVisible = !self.overrideStatusBarHidden;
|
|
headerView.statusBarHintCanOverlapHeader = statusBarCanBeVisible;
|
|
|
|
[UIView animateWithDuration:0.4
|
|
animations:^{
|
|
[self setNeedsStatusBarAppearanceUpdate];
|
|
}];
|
|
break;
|
|
}
|
|
|
|
// Shift behavior
|
|
|
|
case FlexibleHeaderConfiguratorFieldShiftBehaviorEnabled: {
|
|
BOOL isOn = [value boolValue];
|
|
if (!isOn) {
|
|
headerView.shiftBehavior = MDCFlexibleHeaderShiftBehaviorDisabled;
|
|
[self
|
|
didChangeValueForField:FlexibleHeaderConfiguratorFieldShiftBehaviorEnabledWithStatusBar
|
|
animated:YES];
|
|
} else {
|
|
headerView.shiftBehavior = MDCFlexibleHeaderShiftBehaviorEnabled;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FlexibleHeaderConfiguratorFieldShiftBehaviorEnabledWithStatusBar: {
|
|
BOOL isOn = [value boolValue];
|
|
if (!isOn) {
|
|
headerView.shiftBehavior = MDCFlexibleHeaderShiftBehaviorEnabled;
|
|
} else {
|
|
headerView.shiftBehavior = MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar;
|
|
[self didChangeValueForField:FlexibleHeaderConfiguratorFieldShiftBehaviorEnabled
|
|
animated:YES];
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FlexibleHeaderConfiguratorFieldContentImportance:
|
|
headerView.headerContentImportance =
|
|
([value boolValue] ? MDCFlexibleHeaderContentImportanceHigh
|
|
: MDCFlexibleHeaderContentImportanceDefault);
|
|
break;
|
|
|
|
// Header height
|
|
|
|
case FlexibleHeaderConfiguratorFieldMinimumHeight:
|
|
headerView.minimumHeight = [self heightDenormalized:[value floatValue]];
|
|
break;
|
|
|
|
case FlexibleHeaderConfiguratorFieldMaximumHeight:
|
|
headerView.maximumHeight = [self heightDenormalized:[value floatValue]];
|
|
break;
|
|
|
|
case FlexibleHeaderConfiguratorFieldMinMaxHeightIncludeSafeArea:
|
|
headerView.minMaxHeightIncludesSafeArea = [value boolValue];
|
|
break;
|
|
}
|
|
}
|
|
|
|
#pragma mark - Typical Flexible Header implementations
|
|
|
|
// Required for shiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar.
|
|
- (BOOL)prefersStatusBarHidden {
|
|
return _overrideStatusBarHidden || self.fhvc.prefersStatusBarHidden;
|
|
}
|
|
|
|
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
|
|
return UIStatusBarAnimationSlide;
|
|
}
|
|
|
|
#pragma mark - UIScrollViewDelegate
|
|
|
|
// Note that, unlike the Typical Use example, we are explicitly forwarding the UIScrollViewDelegate
|
|
// methods to the header view. This is because this example controller also needs to handle other
|
|
// UITableViewDelegate events.
|
|
|
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
|
|
if (scrollView == self.fhvc.headerView.trackingScrollView) {
|
|
[self.fhvc.headerView trackingScrollViewDidScroll];
|
|
}
|
|
}
|
|
|
|
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
|
|
if (scrollView == self.fhvc.headerView.trackingScrollView) {
|
|
[self.fhvc.headerView trackingScrollViewDidEndDecelerating];
|
|
}
|
|
}
|
|
|
|
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
|
|
MDCFlexibleHeaderView *headerView = self.fhvc.headerView;
|
|
if (scrollView == headerView.trackingScrollView) {
|
|
[headerView trackingScrollViewDidEndDraggingWillDecelerate:decelerate];
|
|
}
|
|
}
|
|
|
|
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
|
|
withVelocity:(CGPoint)velocity
|
|
targetContentOffset:(inout CGPoint *)targetContentOffset {
|
|
MDCFlexibleHeaderView *headerView = self.fhvc.headerView;
|
|
if (scrollView == headerView.trackingScrollView) {
|
|
[headerView trackingScrollViewWillEndDraggingWithVelocity:velocity
|
|
targetContentOffset:targetContentOffset];
|
|
}
|
|
}
|
|
|
|
#pragma mark - MDCFlexibleHeaderViewLayoutDelegate
|
|
|
|
- (void)flexibleHeaderViewController:
|
|
(nonnull MDCFlexibleHeaderViewController *)flexibleHeaderViewController
|
|
flexibleHeaderViewFrameDidChange:(nonnull MDCFlexibleHeaderView *)flexibleHeaderView {
|
|
CGFloat headerContentAlpha;
|
|
switch (flexibleHeaderView.scrollPhase) {
|
|
case MDCFlexibleHeaderScrollPhaseCollapsing:
|
|
case MDCFlexibleHeaderScrollPhaseOverExtending:
|
|
headerContentAlpha = 1;
|
|
break;
|
|
case MDCFlexibleHeaderScrollPhaseShifting:
|
|
headerContentAlpha = 1 - flexibleHeaderView.scrollPhasePercentage;
|
|
break;
|
|
}
|
|
for (UIView *subview in self.fhvc.headerView.subviews) {
|
|
subview.alpha = headerContentAlpha;
|
|
}
|
|
}
|
|
|
|
#pragma mark - Field data manipulation
|
|
|
|
static const CGFloat kHeightScalar = 300;
|
|
|
|
- (CGFloat)normalizedHeight:(CGFloat)height {
|
|
return (height - self.minimumHeaderHeight) / (kHeightScalar - self.minimumHeaderHeight);
|
|
}
|
|
|
|
- (CGFloat)heightDenormalized:(CGFloat)normalized {
|
|
return normalized * (kHeightScalar - self.minimumHeaderHeight) + self.minimumHeaderHeight;
|
|
}
|
|
|
|
- (NSNumber *)valueForField:(FlexibleHeaderConfiguratorField)field {
|
|
switch (field) {
|
|
case FlexibleHeaderConfiguratorFieldCanOverExtend:
|
|
return @(self.fhvc.headerView.canOverExtend);
|
|
|
|
case FlexibleHeaderConfiguratorFieldContentImportance:
|
|
return @(
|
|
(self.fhvc.headerView.headerContentImportance == MDCFlexibleHeaderContentImportanceHigh));
|
|
|
|
case FlexibleHeaderConfiguratorFieldHideStatusBar:
|
|
return @(self.overrideStatusBarHidden);
|
|
|
|
case FlexibleHeaderConfiguratorFieldShiftBehaviorEnabled: {
|
|
MDCFlexibleHeaderShiftBehavior behavior = self.fhvc.headerView.shiftBehavior;
|
|
BOOL enabled = (behavior == MDCFlexibleHeaderShiftBehaviorEnabled ||
|
|
behavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar);
|
|
return @(enabled);
|
|
}
|
|
|
|
case FlexibleHeaderConfiguratorFieldShiftBehaviorEnabledWithStatusBar: {
|
|
MDCFlexibleHeaderShiftBehavior behavior = self.fhvc.headerView.shiftBehavior;
|
|
BOOL enabled = (behavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar);
|
|
return @(enabled);
|
|
}
|
|
|
|
case FlexibleHeaderConfiguratorFieldInFrontOfInfiniteContent:
|
|
return @(self.fhvc.headerView.inFrontOfInfiniteContent);
|
|
|
|
case FlexibleHeaderConfiguratorFieldMinimumHeight:
|
|
return @([self normalizedHeight:self.fhvc.headerView.minimumHeight]);
|
|
|
|
case FlexibleHeaderConfiguratorFieldMaximumHeight:
|
|
return @([self normalizedHeight:self.fhvc.headerView.maximumHeight]);
|
|
case FlexibleHeaderConfiguratorFieldMinMaxHeightIncludeSafeArea:
|
|
return @(self.fhvc.headerView.minMaxHeightIncludesSafeArea);
|
|
}
|
|
}
|
|
|
|
@end
|