This logical unit will house all logic related to the shift behavior. It is being extracted as a distinct logical unit so that it can be better unit tested and validated in terms of behavior. This change introduces an initial test for the basic skeletal object accordingly.
In subsequent changes, we will move logic from MDCFlexibleHeaderView into this new object.
PiperOrigin-RevId: 311203197
Prior to this change, the FlexibleHeader's hairline APIs were not backed by storage until the FlexibleHeader's view was loaded. This meant that settings on these properties would effectively get lost.
After this change, the FlexibleHeader initializes the hairline storage immediately on initialization so that the public hairline properties are consistently backed by storage.
Closes https://github.com/material-components/material-components-ios/issues/9863
Problem statement: Attached banner on MDCFlexibleHeaderView are not intractable. Gestures on attached banner are not received, but rather goes through to view underneath the MDCFlexibleHeaderView.
Cause and Fix: MDCFlexibleHeaderView, after shifted to the top, with minimumHeaderViewHeight enabled, is shorter than intended. This was because fhv_accumulatorMax did not take minimumHeaderViewHeight into calculation. This corrects header view height after shifting.
This change introduces two new APIs on MDCFlexibleHeaderViewController: `showsHairline` and `hairlineColor`. Enabling `showsHairline` will show a view fully colored with `hairlineColor` at the bottom of the flexible header view.
This hairline view can be hidden and shown at will, enabling behaviors such as hiding the hairline when the header view's elevation changes (via the setShadowLayer:intensityDidChangeBlock: API on MDCFlexibleHeaderView).
PiperOrigin-RevId: 293140791
Add new flag to allow use of inferTopSafeAreaInsetFromViewController with topLayoutGuideAdjustmentEnabled
Without this change, using both of these properties will sometimes crash.
This new shift behavior mode enables the flexible header to mimic the behavior of UINavigationController's setNavigationBarHidden:. When the shift behavior is set to this new value, the flexible header can be hidden or shown using the shiftHeaderOnScreenAnimated: and shiftHeaderOffScreenAnimated: APIs, but user interactions will not affect the header's visibility.
Added an example to the configurator to demonstrate the behavior.
Part of https://github.com/material-components/material-components-ios/issues/5185
These tests validate the behavior of the flexible header when the shift behavior is disabled.
Notably, these tests reveal a bug in the implementation of isShiftedOffscreen which can occur with the following repro steps:
1. Set the flexible header's shift behavior to disabled and that it has a tracking scroll view with a content size greater than its bounds by at least the height of the header (in order to allow the scroll view to be dragged).
2. Hide the flexible header with shiftHeaderOffScreenAnimated:
3. Drag the flexible header's tracking scroll view up and then down, revealing the flexible header.
4. Inspect the state of isShiftedOffscreen.
Expected value: false
Actual value: true
This is due to the fact that shiftHeaderOffScreenAnimated: sets an internal bit that indicates that the flexible header *wants* to be hidden, and this bit is not reset once the user starts interacting with the flexible header. The likely fix is to clear the "wants to be hidden" flag when the user starts interacting with the flexible header again. I've filed https://github.com/material-components/material-components-ios/issues/9022 to track this bug.
Discovered as part of https://github.com/material-components/material-components-ios/issues/5185
This property makes it possible to evaluate whether the flexible header has been intentionally hidden or not. This property will be used in a subsequent PR to implement navigationBarHidden in MDCAppBarNavigationController.
Pre-work for https://github.com/material-components/material-components-ios/issues/5185
Add elevation property and elevationDidChange block to `MDCFlexibleHeaderView`. Elevation will be set in an upcoming PR by `MDCAppBarViewController`.
Closes#8018
The Flexible needs an API so clients can hook-in to trait collection changes. This additionally passes the flexibleHeader as a parameter so clients can modify the flexible header within the block.
Closes#7849
The Flexible needs an API so clients can hook-in to trait collection changes. This additionally passes the flexibleHeader as a parameter so clients can modify the flexible header within the block.
The Flexible needs an API so clients can hook-in to trait collection changes. This additionally passes the flexibleHeader as a parameter so clients can modify the flexible header within the block.
This changes exposes an API for shadowColor to MDCFlexibleHeader so that if clients set their shadowLayer to a custom class then can also set the shadowColor to a dynamic color that will be applied in layoutSubviews.
Closes#7916
MDCFlexibleHeader currently doesn't have any tests related to the shadow layer. This adds tests for that property. Since there are no general flexible header tests I added this within it's own file as all other test files seem specific to other tests.
Changes shepherded from [cl/234843277](http://cl/234843277). From CL:
Add a configuration to allow safe areas to be calculated based on parent.
Prior to this CL, inferTopSafeAreaInsetFromViewController set to YES assumed
the header was embedded into a VC heirarchy at the top, so the most
ancestor VC is the only one that would know the safe areas. That's fine
if the header is always at the top of the screen, but breaks when the
header has something above it.
parentIsAncestorForTopSafeAreaInset instead sets the parent's safe area
as the safe area the header should respect.
This is the second attempt at https://github.com/material-components/material-components-ios/pull/5594
This second attempt reduces the amount of change in behavior by replacing some invocations of the min/max height setters with ivar assignment to more closely match the original code.
The original change description is below:
---
This work is part of https://github.com/material-components/material-components-ios/issues/5060
This change pulls the minimumHeight and maximumHeight logic out to a separate, private class within the FlexibleHeader component. All of the associated state and APIs have been moved as well, and the existing MDCFlexibleHeaderView public APIs now pass-through to this internal object.
The intent of this change, like b8090cb before it, is to break the MDCFlexibleHeaderView implementation into smaller, more testable units of code.
The new MDCFlexibleHeaderMinMaxHeight object implements two paths of logic: the legacy, pre-iPhone X behavior, and the modern aware-of-safe-areas behavior. minMaxHeightIncludesSafeArea is the flag that governs which path of logic we'll use and we intend to deprecate it as part of https://github.com/material-components/material-components-ios/issues/4764. There are now two separate unit test class for each of the possible states of minMaxHeightIncludesSafeArea.
This work is part of https://github.com/material-components/material-components-ios/issues/5060
This change pulls the minimumHeight and maximumHeight logic out to a separate, private class within the FlexibleHeader component. All of the associated state and APIs have been moved as well, and the existing MDCFlexibleHeaderView public APIs now pass-through to this internal object.
The intent of this change, like b8090cb before it, is to break the MDCFlexibleHeaderView implementation into smaller, more testable units of code.
The new MDCFlexibleHeaderMinMaxHeight object implements two paths of logic: the legacy, pre-iPhone X behavior, and the modern aware-of-safe-areas behavior. minMaxHeightIncludesSafeArea is the flag that governs which path of logic we'll use and we intend to deprecate it as part of https://github.com/material-components/material-components-ios/issues/4764. There are now two separate unit test class for each of the possible states of minMaxHeightIncludesSafeArea.
[MDC Swift] Add guards for Swift 4.2+
On Xcode 10, using Tulsi, the unit test target cannot be built because much of the Swift code does
not have the correct syntax for Swift 4.2+. Adding pragmas to allow continued support for Xcode
9.4.2 and Xcode 10.
PiperOrigin-RevId: 220399935
See docs for test_spec here: https://blog.cocoapods.org/CocoaPods-1.3.0/
test_spec is an official CocoaPods mechanism for associating tests with a component. tests_spec has several advantages over our prior "tests as a podspec" hack:
- We can finally run individual tests from Xcode's inline green "test" button that shows up alongside each test in the editor.
- Tests can import private header files from components from .h files in the test target (because tests are no longer treated as frameworks). We were not previously able to do this, making it impossible to create .h/.m files that were shared across multiple test .m files.
- We no longer need MDCUnitTests - everything lives in the MDCCatalog target.
- The tests/ folder now appears as a sub-group for each component in the MaterialComponents development pod group. This will have a big impact on day-to-day workflow. Previously our tests lived in a sibling group to our components, making it somewhat difficult to navigate back-and-forth in Xcode.
- pod lib lint is now able to run our unit tests.
- Our tests can now explicitly declare their dependencies.
Some caveats:
- Each component now needs a test_spec subspec definition. This is a minor detail and one that doesn't add much extra work when creating a new component (we continue to just copy the existing templates).
- When adding a new test_spec, we also need to add the test_spec to our MDCCatalog Podfile under the `:testspecs` list. This is a bit annoying, but only happens when new components are created (very infrequent). This is a good case of the cost here being outweighed by the benefits above (which affect our daily workflow).
## Screenshot
<img width="405" alt="screen shot 2018-09-22 at 9 40 17 pm" src="https://user-images.githubusercontent.com/45670/45920647-33f4c180-beb0-11e8-94bc-88f3450c9e0a.png">
There is a new private `MDCFlexibleHeaderTopSafeArea` object. This object contains all of the logic related to top safe area insets. As part of this extraction, many of the internal ivars from MDCFlexibleHeaderView have been moved to the new object.
This change does not intentionally introduce any functional or behavioral changes.
This change includes tests for this new object, along with updating the MDCFlexibleHeaderView.m logic to use the new object.
Part of https://github.com/material-components/material-components-ios/issues/5060
Removes the need to copy-paste stanzas from other files anymore as we'll rely on #4478 to generate the correct stanza for us instead.
This was an automated change generated by running a find-and-replace regular expression:
```
/\*
Copyright ([0-9]+)-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\.
\*/
```
```
/\*
Copyright ([0-9]+)-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\.
\*/
```
```
/\*
Copyright ([0-9]+)-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\.
\*/
```
```
// Copyright $1-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.
```