This change consists of two related portions:
1. Extraction of badge and dot badge appearance-related APIs into corresponding Appearance objects and updating the MDC examples to reflect this new API format.
2. Updated bottom navigation to make use of the new appearance APIs.
Also added an example of using the appearance's "system tint" default behavior for nil, which is aligned with how UIKit handles similar APIs.
PiperOrigin-RevId: 417902876
The properties' declarations, documentation, and organizational structure now mirrors the underlying badge view that houses the data.
PiperOrigin-RevId: 415342823
Now that BottomNavigation restricts subclassing, this removes any need for the badge storage to be kept as a property and allows us to drop unnecessary method implementations, further reducing binary footprint.
PiperOrigin-RevId: 415331970
Allows clients to set a custom badge background and text colors for all
badges. On iOS 10+, the `UITabBarItem badgeColor` API allows customizing
individual items' badge background colors as well. Setting the badge
background and text color will allow clients using badges on Bottom Navigation
to better-support Dark Mode.
Closes#2833
When the `selectedImage` or `image` values were changed on
MDCBottomNavigationItemView, it was accidentally updating the view's
UIImageView regardless of its current selection state. By checking the
current state and only updating as-needed, changes to the icons don't
show up incorrectly.
Fixes#6846
Uses the [layout specifications from the Material Guidelines
article](https://material.io/design/components/bottom-navigation.html#specs)
to correctly lay out the item view. Of notable import, the label will
now be clipped if it would otherwise extend outside of the view's frame.
This allows the inter-item spacing to be preserved in
MDCBottomNavigationBar.
The previous layout of the Item View was incorrect. Rather than using
the entire view bounds efficiently, it was placing the icon at 20% from
the leading edge of the view, then placing the bounds (potentially)
outside the frame of the view.
Part of #6520
The `itemsContentInsets` API behaves unintuitively and is not used by
any internal clients. Since the Material Guidelines article for Bottom
Navigation does not allow customization of the positioning of the item
views within a Bottom Navigation, it's simply extra maintenance effort
without any clear value.
Resolves#6556
The MDCBottomNavigationItemView did not implement sizeThatFits: and so it was
not possible for the MDCBottomNavigationBar to interrogate the view for its
appropriate size during layout.
Part of #6520
When changing the value of `selectedItemTintColor`, we should confirm that
both selected and unselected items receive the same ink color.
Follow-up for #4937
Replacing all non-integral, single-precision floating point literals with double-precision values explicitly cast to CGFloat. For example, `0.1f` should become `(CGFloat)0.1`.
Regex used:
```
([0-9]*\.)([0-9]*?)([1-9]+)([0-9]*?)[fF]
```
PiperOrigin-RevId: 220683126
<h4>
```diff
- Warning - This may break screenshot testing -
```
</h4>
### Context
Currently the badge is centered on the top of the `iconImageView`. The `iconImageView`'s `origin.y` is at 8.883 in MDC because we vertically center the _content_ in the MDCBottomNavigationItemView. We get the _content_ height by:
_contentHeight_ = icon.height + label.height + contentVerticalMargin
_contentVerticalMargin_ is the spacing between the icon and label.
The **_badge_** is 14dp tall. Centering the badge on the `iconImageView`'s `origin.y` puts the badge at 1.883.
### The problem
The badge is too high in relation to the top of the bottom navigation bar and doesn't match internal guidance.
### The fix
Make the badge and iconImageView have the same origin y, giving users more separation between the top of the navigation bar and the top of the badge.
### Related PR
Closes#4731
### Screenshots
| Before | After |
| - | - |
|||
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.
```
All items should share the same (ink) ripple color, based on the
`selectedItemTintColor`. For currently-unselected items, the ripple color
would only be updated if the `unselectedItemTintColor` property was set.
The problem was caused by earlier behavior where the ripple color would be
derived from the current state of the button. If an unselected item were
pressed, its ripple color would be based on the `unselectedItemTintColor`.
That behavior was changed so that the `selectedItemTintColor` was used for the
ripple color in all states, but the logic was not moved outside of the
state-based conditional logic.
||Animated Screenshot|
|--|--|
|Before | |
|After | |
Closes#4937