Skip to content

Commit e3c7d22

Browse files
author
Junius Gunaratne
committed
[FlexibleHeader] Add contentView and custom shadow layers, bringing in changes from GOOFlexibleHeader
Summary: Add contentView and custom shadow layers, bringing in changes from GOOFlexibleHeader Reviewers: ajsecord, iangordon, #material_components_ios_owners, lpromero Reviewed By: iangordon, #material_components_ios_owners Projects: #material_components_ios Differential Revision: http://codereview.cc/D125
1 parent 5b7b36a commit e3c7d22

File tree

2 files changed

+83
-6
lines changed

2 files changed

+83
-6
lines changed

components/FlexibleHeader/src/MDCFlexibleHeaderView.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ typedef NS_ENUM(NSInteger, MDCFlexibleHeaderScrollPhase) {
6464
*/
6565
@interface MDCFlexibleHeaderView : UIView
6666

67+
#pragma mark Custom shadow
68+
69+
/**
70+
* Custom shadow shown under flexible header content.
71+
*/
72+
@property(nonatomic, retain, nullable) CALayer *shadowLayer;
73+
74+
#pragma mark Accessing the header's views
75+
76+
/**
77+
* Content for the flexible header should be added to the content view.
78+
*/
79+
@property(nonatomic, retain, nullable) UIView *contentView;
80+
6781
#pragma mark UIScrollViewDelegate events
6882

6983
/**
@@ -232,6 +246,13 @@ typedef NS_ENUM(NSInteger, MDCFlexibleHeaderScrollPhase) {
232246
*/
233247
@property(nonatomic, readonly) CGFloat scrollPhasePercentage;
234248

249+
/**
250+
* The intensity strength of the shadow being displayed under the flexible header. Use this property
251+
* to check what the intensity of a custom shadow should be depending on a scroll position. Valid
252+
* values range from 0 to 1. Where 0 is no shadow is visible and 1 is the shadow is fully visible.
253+
*/
254+
@property(nonatomic, readonly) CGFloat shadowIntensity;
255+
235256
#pragma mark Bounding Dimensions
236257

237258
@property(nonatomic) CGFloat minimumHeight; ///< The minimum height that this header can shrink to.

components/FlexibleHeader/src/MDCFlexibleHeaderView.m

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ @implementation MDCFlexibleHeaderView {
9696

9797
MDCStatusBarShifter *_statusBarShifter;
9898

99+
// Layers for header shadows.
100+
CALayer *_defaultShadowLayer;
101+
CALayer *_customShadowLayer;
102+
99103
#if DEBUG
100104
// Keeps track of whether the client called ...WillEndDraggingWithVelocity:...
101105
BOOL _didAdjustTargetContentOffset;
@@ -147,7 +151,27 @@ - (instancetype)initWithFrame:(CGRect)frame {
147151
_visibleShadowOpacity = kDefaultVisibleShadowOpacity;
148152
_canOverExtend = YES;
149153

154+
_defaultShadowLayer = [CALayer layer];
155+
_defaultShadowLayer.shadowColor = [[UIColor blackColor] CGColor];
156+
_defaultShadowLayer.shadowOffset = CGSizeMake(0, 1.f);
157+
_defaultShadowLayer.shadowRadius = 4.f;
158+
_defaultShadowLayer.shadowOpacity = 0;
159+
_defaultShadowLayer.hidden = YES;
160+
[self.layer addSublayer:_defaultShadowLayer];
161+
162+
// Allow for custom shadows to be used.
163+
_customShadowLayer = [CALayer layer];
164+
_customShadowLayer.hidden = YES;
165+
[self.layer addSublayer:_customShadowLayer];
166+
167+
_contentView = [[UIView alloc] initWithFrame:self.bounds];
168+
_contentView.autoresizingMask =
169+
(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
170+
[super addSubview:_contentView];
171+
150172
self.backgroundColor = [UIColor lightGrayColor];
173+
_defaultShadowLayer.backgroundColor = self.backgroundColor.CGColor;
174+
151175
self.layer.shadowColor = [[UIColor blackColor] CGColor];
152176
self.layer.shadowOffset = CGSizeMake(0, 1);
153177
self.layer.shadowRadius = 4.f;
@@ -161,6 +185,27 @@ - (void)setVisibleShadowOpacity:(float)visibleShadowOpacity {
161185
[self fhv_accumulatorDidChange];
162186
}
163187

188+
- (void)setShadowLayer:(CALayer *)shadowLayer {
189+
// If there is a custom shadow make sure the shadow on self.layer is not visible.
190+
self.layer.shadowOpacity = 0;
191+
CALayer *oldShadowLayer = _shadowLayer;
192+
if (shadowLayer == _shadowLayer) {
193+
return;
194+
}
195+
_shadowLayer = shadowLayer;
196+
[oldShadowLayer removeFromSuperlayer];
197+
if (shadowLayer) {
198+
// When a custom shadow is being used hide the default shadow.
199+
_defaultShadowLayer.hidden = YES;
200+
_customShadowLayer.hidden = NO;
201+
[_customShadowLayer addSublayer:_shadowLayer];
202+
} else {
203+
_defaultShadowLayer.hidden = NO;
204+
_customShadowLayer.hidden = YES;
205+
_shadowLayer = nil;
206+
}
207+
}
208+
164209
#pragma mark - UIView
165210

166211
- (CGSize)sizeThatFits:(CGSize)size {
@@ -171,6 +216,12 @@ - (void)layoutSubviews {
171216
[super layoutSubviews];
172217

173218
[self fhv_updateShadowPath];
219+
BOOL disableActions = [CATransaction disableActions];
220+
[CATransaction setDisableActions:YES];
221+
_defaultShadowLayer.frame = self.bounds;
222+
_customShadowLayer.frame = self.bounds;
223+
_shadowLayer.frame = self.bounds;
224+
[CATransaction setDisableActions:disableActions];
174225
}
175226

176227
- (void)willMoveToSuperview:(UIView *)newSuperview {
@@ -424,7 +475,7 @@ - (void)fhv_accumulatorDidChange {
424475

425476
CGFloat boundedAccumulator = MIN([self fhv_accumulatorMax], _shiftOffscreenAccumulator);
426477

427-
float shadowScale;
478+
float shadowIntensity;
428479
if (self.hidesStatusBarWhenCollapsed) {
429480
// Calculate the desired shadow strength for the offset & accumulator and then take the
430481
// weakest strength.
@@ -433,22 +484,27 @@ - (void)fhv_accumulatorDidChange {
433484
if (self.isInFrontOfInfiniteContent) {
434485
// When in front of infinite content we only care to hide the shadow when our header is
435486
// off-screen.
436-
shadowScale = MAX(0, MIN(1, accumulator / kShadowScaleLength));
487+
shadowIntensity = MAX(0, MIN(1, accumulator / kShadowScaleLength));
437488

438489
} else {
439490
// When over non-infinite content we also want to hide the shadow when we're anchored to the
440491
// top of our content.
441-
shadowScale = MAX(0, MIN(1, MIN(accumulator, frameBottomEdge) / kShadowScaleLength));
492+
shadowIntensity = MAX(0, MIN(1, MIN(accumulator, frameBottomEdge) / kShadowScaleLength));
442493
}
443494

444495
} else if (self.isInFrontOfInfiniteContent) {
445-
shadowScale = 1;
496+
shadowIntensity = 1;
446497

447498
} else {
448499
// Adjust the opacity as the bottom edge of the header increasingly overlaps the contents
449-
shadowScale = frameBottomEdge / kShadowScaleLength;
500+
shadowIntensity = frameBottomEdge / kShadowScaleLength;
501+
}
502+
if (_defaultShadowLayer.hidden && _customShadowLayer.hidden) {
503+
self.layer.shadowOpacity = _visibleShadowOpacity * shadowIntensity;
504+
} else {
505+
_defaultShadowLayer.shadowOpacity = _visibleShadowOpacity * shadowIntensity;
450506
}
451-
self.layer.shadowOpacity = _visibleShadowOpacity * shadowScale;
507+
_shadowIntensity = shadowIntensity;
452508

453509
[_statusBarShifter setOffset:boundedAccumulator];
454510

0 commit comments

Comments
 (0)