Drop support for iOS 14 and remove availability checks (#1357)
* Update FluentUI project
* Update FluentUI xcconfig
* Update FluentUI.Demo project
* Update MicrosoftFluentUI.podspec
* Clean up Button
* Clean up CommandBarButton
* Clean up CommandBarButtonGroupView
* Clean up LargeContentViewerModifier
* Clean up Drawer
* Clean up NavigationBar
* Clean up BadgeLabelButton
* Clean up PillButton
* Clean up PillButtonBar
* Clean up SegmentedPillButton
* Clean up SideTabBar
* Clean up TabBarView
* Clean up PillButton v2
* Clean up PillButton v3
* Revert "Update FluentUI project"
This reverts commit 1c97631bcd
.
* Update README.md
* Update Package.swift
This commit is contained in:
Родитель
43c3a8037f
Коммит
4fad398e51
|
@ -12,7 +12,7 @@ Pod::Spec.new do |s|
|
||||||
|
|
||||||
# iOS
|
# iOS
|
||||||
|
|
||||||
s.ios.deployment_target = "14.0"
|
s.ios.deployment_target = "15.0"
|
||||||
|
|
||||||
s.subspec 'Avatar_ios' do |avatar_ios|
|
s.subspec 'Avatar_ios' do |avatar_ios|
|
||||||
avatar_ios.platform = :ios
|
avatar_ios.platform = :ios
|
||||||
|
|
|
@ -6,7 +6,7 @@ let package = Package(
|
||||||
name: "FluentUI",
|
name: "FluentUI",
|
||||||
defaultLocalization: "en",
|
defaultLocalization: "en",
|
||||||
platforms: [
|
platforms: [
|
||||||
.iOS(.v14),
|
.iOS(.v15),
|
||||||
.macOS(.v10_15),
|
.macOS(.v10_15),
|
||||||
],
|
],
|
||||||
products: [
|
products: [
|
||||||
|
|
|
@ -14,7 +14,7 @@ Fluent UI Apple contains native UIKit and AppKit controls aligned with [Microsof
|
||||||
|
|
||||||
#### Requirements
|
#### Requirements
|
||||||
|
|
||||||
- iOS 14+ or macOS 10.15+
|
- iOS 15+ or macOS 10.15+
|
||||||
- Xcode 14+
|
- Xcode 14+
|
||||||
- Swift 5.7+
|
- Swift 5.7+
|
||||||
|
|
||||||
|
|
|
@ -662,7 +662,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DOGFOOD;
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DOGFOOD;
|
||||||
|
@ -757,7 +757,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -815,7 +815,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
|
|
@ -162,22 +162,9 @@ open class Button: UIButton {
|
||||||
adjustCustomContentEdgeInsetsForImage()
|
adjustCustomContentEdgeInsetsForImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
var configuration = self.configuration ?? UIButton.Configuration.plain()
|
||||||
var configuration = self.configuration ?? UIButton.Configuration.plain()
|
configuration.contentInsets = edgeInsets
|
||||||
configuration.contentInsets = edgeInsets
|
self.configuration = configuration
|
||||||
self.configuration = configuration
|
|
||||||
} else {
|
|
||||||
let left: CGFloat
|
|
||||||
let right: CGFloat
|
|
||||||
if effectiveUserInterfaceLayoutDirection == .leftToRight {
|
|
||||||
left = edgeInsets.leading
|
|
||||||
right = edgeInsets.trailing
|
|
||||||
} else {
|
|
||||||
left = edgeInsets.trailing
|
|
||||||
right = edgeInsets.leading
|
|
||||||
}
|
|
||||||
contentEdgeInsets = UIEdgeInsets(top: edgeInsets.top, left: left, bottom: edgeInsets.bottom, right: right)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,41 +175,15 @@ open class Button: UIButton {
|
||||||
|
|
||||||
if let image = image(for: .normal) {
|
if let image = image(for: .normal) {
|
||||||
size.width += image.size.width
|
size.width += image.size.width
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
size.width += style.titleImagePadding
|
|
||||||
}
|
|
||||||
|
|
||||||
if titleLabel?.text?.count ?? 0 == 0 {
|
if titleLabel?.text?.count ?? 0 > 0 {
|
||||||
size.width -= style.titleImagePadding
|
size.width += style.titleImagePadding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
|
|
||||||
var rect = CGRect.zero
|
|
||||||
if #available(iOS 15, *) {
|
|
||||||
assertionFailure("imageRect(forContentRect: ) has been deprecated in iOS 15.0")
|
|
||||||
} else {
|
|
||||||
rect = super.imageRect(forContentRect: contentRect)
|
|
||||||
|
|
||||||
if let image = image {
|
|
||||||
let imageHeight = image.size.height
|
|
||||||
|
|
||||||
// If the entire image doesn't fit in the default rect, increase the rect's height
|
|
||||||
// to fit the entire image and reposition the origin to keep the image centered.
|
|
||||||
if imageHeight > rect.size.height {
|
|
||||||
rect.origin.y -= round((imageHeight - rect.size.height) / 2.0)
|
|
||||||
rect.size.height = imageHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
rect.size.width = image.size.width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rect
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc public init(style: ButtonStyle = .secondaryOutline) {
|
@objc public init(style: ButtonStyle = .secondaryOutline) {
|
||||||
self.style = style
|
self.style = style
|
||||||
super.init(frame: .zero)
|
super.init(frame: .zero)
|
||||||
|
@ -246,11 +207,10 @@ open class Button: UIButton {
|
||||||
titleLabel?.font = style.titleFont
|
titleLabel?.font = style.titleFont
|
||||||
titleLabel?.adjustsFontForContentSizeCategory = true
|
titleLabel?.adjustsFontForContentSizeCategory = true
|
||||||
|
|
||||||
if #available(iOS 15, *) {
|
var configuration = UIButton.Configuration.plain()
|
||||||
var configuration = UIButton.Configuration.plain()
|
configuration.contentInsets = edgeInsets
|
||||||
configuration.contentInsets = edgeInsets
|
self.configuration = configuration
|
||||||
self.configuration = configuration
|
|
||||||
}
|
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,21 +375,10 @@ open class Button: UIButton {
|
||||||
spacing = -spacing
|
spacing = -spacing
|
||||||
}
|
}
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
var configuration = self.configuration ?? UIButton.Configuration.plain()
|
||||||
var configuration = self.configuration ?? UIButton.Configuration.plain()
|
configuration.contentInsets = edgeInsets
|
||||||
configuration.contentInsets = edgeInsets
|
configuration.imagePadding = spacing
|
||||||
configuration.imagePadding = spacing
|
self.configuration = configuration
|
||||||
self.configuration = configuration
|
|
||||||
} else {
|
|
||||||
edgeInsets.trailing += spacing
|
|
||||||
if effectiveUserInterfaceLayoutDirection == .leftToRight {
|
|
||||||
titleEdgeInsets.left += spacing
|
|
||||||
titleEdgeInsets.right -= spacing
|
|
||||||
} else {
|
|
||||||
titleEdgeInsets.right += spacing
|
|
||||||
titleEdgeInsets.left -= spacing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isAdjustingCustomContentEdgeInsetsForImage = false
|
isAdjustingCustomContentEdgeInsetsForImage = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,16 +44,11 @@ class CommandBarButton: UIButton {
|
||||||
/// Disable accessiblity for the button so that the custom view can provide itself or its subviews as the accessilbity element(s)
|
/// Disable accessiblity for the button so that the custom view can provide itself or its subviews as the accessilbity element(s)
|
||||||
isAccessibilityElement = false
|
isAccessibilityElement = false
|
||||||
} else {
|
} else {
|
||||||
if #available(iOS 15.0, *) {
|
var buttonConfiguration = UIButton.Configuration.plain()
|
||||||
var buttonConfiguration = UIButton.Configuration.plain()
|
buttonConfiguration.image = item.iconImage
|
||||||
buttonConfiguration.image = item.iconImage
|
buttonConfiguration.contentInsets = LayoutConstants.contentInsets
|
||||||
buttonConfiguration.contentInsets = LayoutConstants.contentInsets
|
buttonConfiguration.background.cornerRadius = 0
|
||||||
buttonConfiguration.background.cornerRadius = 0
|
configuration = buttonConfiguration
|
||||||
configuration = buttonConfiguration
|
|
||||||
} else {
|
|
||||||
setImage(item.iconImage, for: .normal)
|
|
||||||
contentEdgeInsets = LayoutConstants.contentEdgeInsets
|
|
||||||
}
|
|
||||||
|
|
||||||
let accessibilityDescription = item.accessibilityLabel
|
let accessibilityDescription = item.accessibilityLabel
|
||||||
accessibilityLabel = (accessibilityDescription != nil) ? accessibilityDescription : item.title
|
accessibilityLabel = (accessibilityDescription != nil) ? accessibilityDescription : item.title
|
||||||
|
@ -94,18 +89,12 @@ class CommandBarButton: UIButton {
|
||||||
let title = item.title
|
let title = item.title
|
||||||
let accessibilityDescription = item.accessibilityLabel
|
let accessibilityDescription = item.accessibilityLabel
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
configuration?.image = iconImage
|
||||||
configuration?.image = iconImage
|
configuration?.title = iconImage != nil ? nil : title
|
||||||
configuration?.title = iconImage != nil ? nil : title
|
|
||||||
|
|
||||||
if let font = item.titleFont {
|
if let font = item.titleFont {
|
||||||
let attributeContainer = AttributeContainer([NSAttributedString.Key.font: font])
|
let attributeContainer = AttributeContainer([NSAttributedString.Key.font: font])
|
||||||
configuration?.attributedTitle?.setAttributes(attributeContainer)
|
configuration?.attributedTitle?.setAttributes(attributeContainer)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setImage(iconImage, for: .normal)
|
|
||||||
setTitle(iconImage != nil ? nil : title, for: .normal)
|
|
||||||
titleLabel?.font = item.titleFont
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAccentImage(item.accentImage)
|
updateAccentImage(item.accentImage)
|
||||||
|
@ -171,10 +160,9 @@ class CommandBarButton: UIButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateStyle() {
|
private func updateStyle() {
|
||||||
// TODO: Once iOS 14 support is dropped, this should be converted to a constant (let) that will be initialized by the logic below.
|
|
||||||
var resolvedBackgroundColor: UIColor = .clear
|
|
||||||
let resolvedTintColor: UIColor = isSelected ? selectedTintColor : ColorConstants.normalTintColor
|
let resolvedTintColor: UIColor = isSelected ? selectedTintColor : ColorConstants.normalTintColor
|
||||||
|
|
||||||
|
let resolvedBackgroundColor: UIColor
|
||||||
if isPersistSelection {
|
if isPersistSelection {
|
||||||
if isSelected {
|
if isSelected {
|
||||||
resolvedBackgroundColor = selectedBackgroundColor
|
resolvedBackgroundColor = selectedBackgroundColor
|
||||||
|
@ -183,16 +171,12 @@ class CommandBarButton: UIButton {
|
||||||
} else {
|
} else {
|
||||||
resolvedBackgroundColor = ColorConstants.normalBackgroundColor
|
resolvedBackgroundColor = ColorConstants.normalBackgroundColor
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
resolvedBackgroundColor = .clear
|
||||||
}
|
}
|
||||||
|
|
||||||
tintColor = resolvedTintColor
|
configuration?.baseForegroundColor = resolvedTintColor
|
||||||
if #available(iOS 15.0, *) {
|
configuration?.background.backgroundColor = resolvedBackgroundColor
|
||||||
configuration?.baseForegroundColor = resolvedTintColor
|
|
||||||
configuration?.background.backgroundColor = resolvedBackgroundColor
|
|
||||||
} else {
|
|
||||||
backgroundColor = resolvedBackgroundColor
|
|
||||||
setTitleColor(tintColor, for: .normal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addCustomView(_ view: UIView) {
|
private func addCustomView(_ view: UIView) {
|
||||||
|
|
|
@ -61,13 +61,8 @@ class CommandBarButtonGroupView: UIView {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func applyInsets() {
|
private func applyInsets() {
|
||||||
if #available(iOS 15.0, *) {
|
buttons.first?.configuration?.contentInsets.leading += LayoutConstants.leftRightBuffer
|
||||||
buttons.first?.configuration?.contentInsets.leading += LayoutConstants.leftRightBuffer
|
buttons.last?.configuration?.contentInsets.trailing += LayoutConstants.leftRightBuffer
|
||||||
buttons.last?.configuration?.contentInsets.trailing += LayoutConstants.leftRightBuffer
|
|
||||||
} else {
|
|
||||||
buttons.first?.contentEdgeInsets.left += LayoutConstants.leftRightBuffer
|
|
||||||
buttons.last?.contentEdgeInsets.right += LayoutConstants.leftRightBuffer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct LayoutConstants {
|
private struct LayoutConstants {
|
||||||
|
|
|
@ -77,21 +77,17 @@ struct LargeContentViewerModifier: ViewModifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
if #available(iOS 15.0, *) {
|
if text != nil || image != nil {
|
||||||
if text != nil || image != nil {
|
content.accessibilityShowsLargeContentViewer({
|
||||||
content.accessibilityShowsLargeContentViewer({
|
if let image = image {
|
||||||
if let image = image {
|
Image(uiImage: image)
|
||||||
Image(uiImage: image)
|
}
|
||||||
}
|
if let text = text {
|
||||||
if let text = text {
|
Text(text)
|
||||||
Text(text)
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
} else {
|
|
||||||
content.accessibilityShowsLargeContentViewer()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
content
|
content.accessibilityShowsLargeContentViewer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -293,24 +293,6 @@ class DrawerPresentationController: UIPresentationController {
|
||||||
|
|
||||||
if let presentedView = presentedView {
|
if let presentedView = presentedView {
|
||||||
let presentedViewFrame = frameForPresentedViewController(in: presentedView.superview == containerView ? contentView.frame : contentView.bounds)
|
let presentedViewFrame = frameForPresentedViewController(in: presentedView.superview == containerView ? contentView.frame : contentView.bounds)
|
||||||
|
|
||||||
// On iOS 13 and iOS 14 the safeAreaInsets are not applied when the presentedView is not entirely within the screen bounds.
|
|
||||||
// As a workaround, additional safe area insets need to be set to compensate.
|
|
||||||
if #available(iOS 15.0, *) {} else {
|
|
||||||
let isVerticallyPresentedViewPartiallyOffScreen: Bool = {
|
|
||||||
// Calculates the origin of the presentedView frame in relation to the device screen.
|
|
||||||
guard let origin = presentedView.superview?.convert(presentedViewFrame.origin, to: nil), let window = sourceViewController.view.window else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let screenHeight = window.screen.bounds.height
|
|
||||||
return (presentationDirection == .down && origin.y < 0) ||
|
|
||||||
(presentationDirection == .up && (origin.y + presentedViewFrame.height - screenHeight) > 0)
|
|
||||||
}()
|
|
||||||
|
|
||||||
presentedViewController.additionalSafeAreaInsets = isVerticallyPresentedViewPartiallyOffScreen ? contentView.safeAreaInsets : .zero
|
|
||||||
}
|
|
||||||
|
|
||||||
presentedView.frame = presentedViewFrame
|
presentedView.frame = presentedViewFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,7 @@ class BadgeLabelButton: UIButton {
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
configuration = UIButton.Configuration.plain()
|
||||||
configuration = UIButton.Configuration.plain()
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self,
|
NotificationCenter.default.addObserver(self,
|
||||||
selector: #selector(badgeValueDidChange),
|
selector: #selector(badgeValueDidChange),
|
||||||
|
@ -69,15 +67,9 @@ class BadgeLabelButton: UIButton {
|
||||||
|
|
||||||
private var badgeFrameOriginX: CGFloat {
|
private var badgeFrameOriginX: CGFloat {
|
||||||
let xOrigin: CGFloat = {
|
let xOrigin: CGFloat = {
|
||||||
if #available(iOS 15.0, *) {
|
return isLeftToRightUserInterfaceLayoutDirection ?
|
||||||
return isLeftToRightUserInterfaceLayoutDirection ?
|
frame.size.width - (configuration?.contentInsets.leading ?? 0) :
|
||||||
frame.size.width - (configuration?.contentInsets.leading ?? 0) :
|
configuration?.contentInsets.trailing ?? 0
|
||||||
configuration?.contentInsets.trailing ?? 0
|
|
||||||
} else {
|
|
||||||
return isLeftToRightUserInterfaceLayoutDirection ?
|
|
||||||
frame.size.width - contentEdgeInsets.left :
|
|
||||||
contentEdgeInsets.left
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return (xOrigin - badgeWidth / 2)
|
return (xOrigin - badgeWidth / 2)
|
||||||
|
@ -128,13 +120,8 @@ class BadgeLabelButton: UIButton {
|
||||||
landscapeImage = landscapeImage?.withRenderingMode(.alwaysTemplate)
|
landscapeImage = landscapeImage?.withRenderingMode(.alwaysTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
configuration?.image = traitCollection.verticalSizeClass == .regular ? portraitImage : landscapeImage
|
||||||
configuration?.image = traitCollection.verticalSizeClass == .regular ? portraitImage : landscapeImage
|
configuration?.title = item.title
|
||||||
configuration?.title = item.title
|
|
||||||
} else {
|
|
||||||
setImage(traitCollection.verticalSizeClass == .regular ? portraitImage : landscapeImage, for: .normal)
|
|
||||||
setTitle(item.title, for: .normal)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let action = item.action {
|
if let action = item.action {
|
||||||
addTarget(item.target, action: action, for: .touchUpInside)
|
addTarget(item.target, action: action, for: .touchUpInside)
|
||||||
|
|
|
@ -586,36 +586,21 @@ open class NavigationBar: UINavigationBar {
|
||||||
button.item = item
|
button.item = item
|
||||||
button.shouldUseWindowColorInBadge = style != .system
|
button.shouldUseWindowColorInBadge = style != .system
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
let insets: NSDirectionalEdgeInsets
|
||||||
let insets: NSDirectionalEdgeInsets
|
if isLeftItem {
|
||||||
if isLeftItem {
|
insets = NSDirectionalEdgeInsets(top: 0,
|
||||||
insets = NSDirectionalEdgeInsets(top: 0,
|
leading: Constants.leftBarButtonItemLeadingMargin,
|
||||||
leading: Constants.leftBarButtonItemLeadingMargin,
|
bottom: 0,
|
||||||
bottom: 0,
|
trailing: 0)
|
||||||
trailing: 0)
|
|
||||||
} else {
|
|
||||||
insets = NSDirectionalEdgeInsets(top: 0,
|
|
||||||
leading: Constants.rightBarButtonItemHorizontalPadding,
|
|
||||||
bottom: 0,
|
|
||||||
trailing: Constants.rightBarButtonItemHorizontalPadding)
|
|
||||||
}
|
|
||||||
|
|
||||||
button.configuration?.contentInsets = insets
|
|
||||||
} else {
|
} else {
|
||||||
if isLeftItem {
|
insets = NSDirectionalEdgeInsets(top: 0,
|
||||||
let isRTL = effectiveUserInterfaceLayoutDirection == .rightToLeft
|
leading: Constants.rightBarButtonItemHorizontalPadding,
|
||||||
button.contentEdgeInsets = UIEdgeInsets(top: 0,
|
bottom: 0,
|
||||||
left: isRTL ? 0 : Constants.leftBarButtonItemLeadingMargin,
|
trailing: Constants.rightBarButtonItemHorizontalPadding)
|
||||||
bottom: 0,
|
|
||||||
right: isRTL ? Constants.leftBarButtonItemLeadingMargin : 0)
|
|
||||||
} else {
|
|
||||||
button.contentEdgeInsets = UIEdgeInsets(top: 0,
|
|
||||||
left: Constants.rightBarButtonItemHorizontalPadding,
|
|
||||||
bottom: 0,
|
|
||||||
right: Constants.rightBarButtonItemHorizontalPadding)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.configuration?.contentInsets = insets
|
||||||
|
|
||||||
return button
|
return button
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,29 +111,19 @@ open class PillButton: UIButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupView() {
|
private func setupView() {
|
||||||
if #available(iOS 15.0, *) {
|
var configuration = UIButton.Configuration.plain()
|
||||||
var configuration = UIButton.Configuration.plain()
|
configuration.contentInsets = NSDirectionalEdgeInsets(top: Constants.topInset,
|
||||||
configuration.contentInsets = NSDirectionalEdgeInsets(top: Constants.topInset,
|
leading: Constants.horizontalInset,
|
||||||
leading: Constants.horizontalInset,
|
bottom: Constants.bottomInset,
|
||||||
bottom: Constants.bottomInset,
|
trailing: Constants.horizontalInset)
|
||||||
trailing: Constants.horizontalInset)
|
self.configuration = configuration
|
||||||
self.configuration = configuration
|
|
||||||
|
|
||||||
// This updates the attributed title stored in self.configuration,
|
// This updates the attributed title stored in self.configuration,
|
||||||
// so it needs to be called after we set the configuration.
|
// so it needs to be called after we set the configuration.
|
||||||
updateAttributedTitle()
|
updateAttributedTitle()
|
||||||
|
|
||||||
configurationUpdateHandler = { [weak self] _ in
|
configurationUpdateHandler = { [weak self] _ in
|
||||||
self?.updateAppearance()
|
self?.updateAppearance()
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setTitle(pillBarItem.title, for: .normal)
|
|
||||||
titleLabel?.font = Constants.font
|
|
||||||
|
|
||||||
contentEdgeInsets = UIEdgeInsets(top: Constants.topInset,
|
|
||||||
left: Constants.horizontalInset,
|
|
||||||
bottom: Constants.bottomInset,
|
|
||||||
right: Constants.horizontalInset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.cornerRadius = PillButton.cornerRadius
|
layer.cornerRadius = PillButton.cornerRadius
|
||||||
|
@ -183,14 +173,9 @@ open class PillButton: UIButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func titleValueDidChange() {
|
@objc private func titleValueDidChange() {
|
||||||
if #available(iOS 15.0, *) {
|
updateAttributedTitle()
|
||||||
updateAttributedTitle()
|
|
||||||
} else {
|
|
||||||
setTitle(pillBarItem.title, for: .normal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 15, *)
|
|
||||||
private func updateAttributedTitle() {
|
private func updateAttributedTitle() {
|
||||||
let itemTitle = pillBarItem.title
|
let itemTitle = pillBarItem.title
|
||||||
var attributedTitle = AttributedString(itemTitle)
|
var attributedTitle = AttributedString(itemTitle)
|
||||||
|
@ -224,39 +209,22 @@ open class PillButton: UIButton {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Once iOS 14 support is dropped, these should be converted to constants (let) that will be initialized by the logic below.
|
let resolvedBackgroundColor: UIColor
|
||||||
var resolvedBackgroundColor: UIColor = .clear
|
let resolvedTitleColor: UIColor
|
||||||
var resolvedTitleColor: UIColor = .clear
|
|
||||||
|
|
||||||
if isSelected {
|
if isSelected {
|
||||||
if isEnabled {
|
if isEnabled {
|
||||||
resolvedBackgroundColor = customSelectedBackgroundColor ?? (isHighlighted
|
resolvedBackgroundColor = customSelectedBackgroundColor ?? (isHighlighted
|
||||||
? PillButton.selectedHighlightedBackgroundColor(for: window, for: style)
|
? PillButton.selectedHighlightedBackgroundColor(for: window, for: style)
|
||||||
: PillButton.selectedBackgroundColor(for: window, for: style))
|
: PillButton.selectedBackgroundColor(for: window, for: style))
|
||||||
if #available(iOS 15.0, *) {
|
resolvedTitleColor = customSelectedTextColor ?? (isHighlighted ? PillButton.selectedHighlightedTitleColor(for: window,
|
||||||
resolvedTitleColor = customSelectedTextColor ?? (isHighlighted ? PillButton.selectedHighlightedTitleColor(for: window,
|
for: style)
|
||||||
for: style)
|
: PillButton.selectedTitleColor(for: window,
|
||||||
: PillButton.selectedTitleColor(for: window,
|
for: style))
|
||||||
for: style))
|
|
||||||
} else {
|
|
||||||
setTitleColor(customSelectedTextColor ?? PillButton.selectedTitleColor(for: window,
|
|
||||||
for: style),
|
|
||||||
for: .normal)
|
|
||||||
setTitleColor(customSelectedTextColor ?? PillButton.selectedHighlightedTitleColor(for: window,
|
|
||||||
for: style),
|
|
||||||
for: .highlighted)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
resolvedBackgroundColor = PillButton.selectedDisabledBackgroundColor(for: window,
|
resolvedBackgroundColor = PillButton.selectedDisabledBackgroundColor(for: window,
|
||||||
for: style)
|
for: style)
|
||||||
if #available(iOS 15.0, *) {
|
resolvedTitleColor = PillButton.selectedDisabledTitleColor(for: window,
|
||||||
resolvedTitleColor = PillButton.selectedDisabledTitleColor(for: window,
|
for: style)
|
||||||
for: style)
|
|
||||||
} else {
|
|
||||||
setTitleColor(PillButton.selectedDisabledTitleColor(for: window,
|
|
||||||
for: style),
|
|
||||||
for: .normal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if isEnabled {
|
if isEnabled {
|
||||||
|
@ -267,46 +235,30 @@ open class PillButton: UIButton {
|
||||||
for: style)
|
for: style)
|
||||||
: PillButton.normalBackgroundColor(for: window,
|
: PillButton.normalBackgroundColor(for: window,
|
||||||
for: style))
|
for: style))
|
||||||
if #available(iOS 15.0, *) {
|
resolvedTitleColor = {
|
||||||
resolvedTitleColor = {
|
guard let customTextColor = customTextColor else {
|
||||||
guard let customTextColor = customTextColor else {
|
if isHighlighted {
|
||||||
if isHighlighted {
|
return PillButton.highlightedTitleColor(for: window,
|
||||||
return PillButton.highlightedTitleColor(for: window,
|
for: style)
|
||||||
for: style)
|
|
||||||
}
|
|
||||||
|
|
||||||
return PillButton.titleColor(for: style)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return customTextColor
|
return PillButton.titleColor(for: style)
|
||||||
}()
|
}
|
||||||
} else {
|
|
||||||
setTitleColor(customTextColor ?? PillButton.titleColor(for: style),
|
return customTextColor
|
||||||
for: .normal)
|
}()
|
||||||
setTitleColor(customTextColor ?? PillButton.highlightedTitleColor(for: window,
|
|
||||||
for: style),
|
|
||||||
for: .highlighted)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
unreadDotColor = customUnreadDotColor ?? PillButton.disabledUnreadDotColor(for: window,
|
unreadDotColor = customUnreadDotColor ?? PillButton.disabledUnreadDotColor(for: window,
|
||||||
for: style)
|
for: style)
|
||||||
resolvedBackgroundColor = customBackgroundColor ?? PillButton.disabledBackgroundColor(for: window,
|
resolvedBackgroundColor = customBackgroundColor ?? PillButton.disabledBackgroundColor(for: window,
|
||||||
for: style)
|
for: style)
|
||||||
if #available(iOS 15.0, *) {
|
resolvedTitleColor = PillButton.disabledTitleColor(for: window,
|
||||||
resolvedTitleColor = PillButton.disabledTitleColor(for: window,
|
for: style)
|
||||||
for: style)
|
|
||||||
} else {
|
|
||||||
setTitleColor(PillButton.disabledTitleColor(for: window, for: style), for: .disabled)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
configuration?.background.backgroundColor = resolvedBackgroundColor
|
||||||
configuration?.background.backgroundColor = resolvedBackgroundColor
|
configuration?.attributedTitle?.foregroundColor = resolvedTitleColor
|
||||||
configuration?.attributedTitle?.foregroundColor = resolvedTitleColor
|
|
||||||
} else {
|
|
||||||
backgroundColor = resolvedBackgroundColor
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct Constants {
|
private struct Constants {
|
||||||
|
|
|
@ -325,14 +325,7 @@ open class PillButtonBar: UIScrollView {
|
||||||
buttons.append(button)
|
buttons.append(button)
|
||||||
stackView.addArrangedSubview(button)
|
stackView.addArrangedSubview(button)
|
||||||
|
|
||||||
var shouldAddAccessibilityHint: Bool = true
|
if !self.accessibilityTraits.contains(.tabBar) {
|
||||||
if #available(iOS 14.6, *) {
|
|
||||||
// in case pillbuttonbar is used as .tabbar, adding our own index would be repetitive
|
|
||||||
// However, iOS 14.0 - 14.5 `.tabBar` accessibilityTrait does not read out the index automatically
|
|
||||||
shouldAddAccessibilityHint = !self.accessibilityTraits.contains(.tabBar)
|
|
||||||
}
|
|
||||||
|
|
||||||
if shouldAddAccessibilityHint {
|
|
||||||
button.accessibilityHint = String.localizedStringWithFormat("Accessibility.MSPillButtonBar.Hint".localized, index + 1, items.count)
|
button.accessibilityHint = String.localizedStringWithFormat("Accessibility.MSPillButtonBar.Hint".localized, index + 1, items.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,13 +417,8 @@ open class PillButtonBar: UIScrollView {
|
||||||
for button in buttons {
|
for button in buttons {
|
||||||
button.layoutIfNeeded()
|
button.layoutIfNeeded()
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
button.configuration?.contentInsets.leading += buttonExtraSidePadding
|
||||||
button.configuration?.contentInsets.leading += buttonExtraSidePadding
|
button.configuration?.contentInsets.trailing += buttonExtraSidePadding
|
||||||
button.configuration?.contentInsets.trailing += buttonExtraSidePadding
|
|
||||||
} else {
|
|
||||||
button.contentEdgeInsets.right += buttonExtraSidePadding
|
|
||||||
button.contentEdgeInsets.left += buttonExtraSidePadding
|
|
||||||
}
|
|
||||||
|
|
||||||
button.layoutIfNeeded()
|
button.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
@ -473,13 +461,8 @@ open class PillButtonBar: UIScrollView {
|
||||||
if buttonWidth > 0, buttonWidth < Constants.minButtonWidth {
|
if buttonWidth > 0, buttonWidth < Constants.minButtonWidth {
|
||||||
let extraInset = floor((Constants.minButtonWidth - button.frame.width) / 2)
|
let extraInset = floor((Constants.minButtonWidth - button.frame.width) / 2)
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
button.configuration?.contentInsets.leading += extraInset
|
||||||
button.configuration?.contentInsets.leading += extraInset
|
button.configuration?.contentInsets.trailing = button.configuration?.contentInsets.leading ?? extraInset
|
||||||
button.configuration?.contentInsets.trailing = button.configuration?.contentInsets.leading ?? extraInset
|
|
||||||
} else {
|
|
||||||
button.contentEdgeInsets.left += extraInset
|
|
||||||
button.contentEdgeInsets.right = button.contentEdgeInsets.left
|
|
||||||
}
|
|
||||||
|
|
||||||
button.layoutIfNeeded()
|
button.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,24 +43,16 @@ class SegmentPillButton: UIButton {
|
||||||
}
|
}
|
||||||
self.showsLargeContentViewer = true
|
self.showsLargeContentViewer = true
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
var configuration = UIButton.Configuration.plain()
|
||||||
var configuration = UIButton.Configuration.plain()
|
configuration.contentInsets = Constants.insets
|
||||||
configuration.contentInsets = Constants.insets
|
configuration.background.backgroundColor = .clear
|
||||||
configuration.background.backgroundColor = .clear
|
let titleTransformer = UIConfigurationTextAttributesTransformer { incoming in
|
||||||
let titleTransformer = UIConfigurationTextAttributesTransformer { incoming in
|
var outgoing = incoming
|
||||||
var outgoing = incoming
|
outgoing.font = UIFont.systemFont(ofSize: Constants.fontSize)
|
||||||
outgoing.font = UIFont.systemFont(ofSize: Constants.fontSize)
|
return outgoing
|
||||||
return outgoing
|
|
||||||
}
|
|
||||||
configuration.titleTextAttributesTransformer = titleTransformer
|
|
||||||
self.configuration = configuration
|
|
||||||
} else {
|
|
||||||
self.titleLabel?.font = UIFont.systemFont(ofSize: Constants.fontSize)
|
|
||||||
self.contentEdgeInsets = UIEdgeInsets(top: Constants.insets.top,
|
|
||||||
left: Constants.insets.leading,
|
|
||||||
bottom: Constants.insets.bottom,
|
|
||||||
right: Constants.insets.trailing)
|
|
||||||
}
|
}
|
||||||
|
configuration.titleTextAttributesTransformer = titleTransformer
|
||||||
|
self.configuration = configuration
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self,
|
NotificationCenter.default.addObserver(self,
|
||||||
selector: #selector(isUnreadValueDidChange),
|
selector: #selector(isUnreadValueDidChange),
|
||||||
|
|
|
@ -57,7 +57,6 @@ open class SideTabBar: UIView {
|
||||||
avatarView.addGestureRecognizer(avatarViewGestureRecognizer)
|
avatarView.addGestureRecognizer(avatarViewGestureRecognizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAccessibilityIndex()
|
|
||||||
setupLayoutConstraints()
|
setupLayoutConstraints()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,37 +258,9 @@ open class SideTabBar: UIView {
|
||||||
selectedTopItem = allItems.first
|
selectedTopItem = allItems.first
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAccessibilityIndex()
|
|
||||||
setupLayoutConstraints()
|
setupLayoutConstraints()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateAccessibilityIndex() {
|
|
||||||
// iOS 14.0 - 14.5 `.tabBar` accessibilityTrait does not read out the index automatically
|
|
||||||
if #available(iOS 14.6, *) {} else {
|
|
||||||
var totalCount: Int = 0
|
|
||||||
for section in Section.allCases {
|
|
||||||
let currentStackView = stackView(in: section)
|
|
||||||
totalCount += currentStackView.arrangedSubviews.count
|
|
||||||
}
|
|
||||||
|
|
||||||
var previousSectionCount: Int = 0
|
|
||||||
if let avatar = avatar, !avatar.isHidden {
|
|
||||||
totalCount += 1
|
|
||||||
previousSectionCount += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
for section in Section.allCases {
|
|
||||||
let currentStackView = stackView(in: section)
|
|
||||||
|
|
||||||
for (index, itemView) in currentStackView.arrangedSubviews.enumerated() {
|
|
||||||
let accessibilityIndex = index + 1 + previousSectionCount
|
|
||||||
itemView.accessibilityHint = String.localizedStringWithFormat( "Accessibility.TabBarItemView.Hint".localized, accessibilityIndex, totalCount)
|
|
||||||
}
|
|
||||||
previousSectionCount += currentStackView.arrangedSubviews.count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func items(in section: Section) -> [TabBarItem] {
|
private func items(in section: Section) -> [TabBarItem] {
|
||||||
switch section {
|
switch section {
|
||||||
case .top:
|
case .top:
|
||||||
|
|
|
@ -34,15 +34,11 @@ open class TabBarView: UIView {
|
||||||
preconditionFailure("tab bar items can't be more than \(Constants.maxTabCount)")
|
preconditionFailure("tab bar items can't be more than \(Constants.maxTabCount)")
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, item) in items.enumerated() {
|
for item in items {
|
||||||
let tabBarItemView = TabBarItemView(item: item, showsTitle: showsItemTitles)
|
let tabBarItemView = TabBarItemView(item: item, showsTitle: showsItemTitles)
|
||||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTabBarItemTapped(_:)))
|
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTabBarItemTapped(_:)))
|
||||||
tabBarItemView.addGestureRecognizer(tapGesture)
|
tabBarItemView.addGestureRecognizer(tapGesture)
|
||||||
|
|
||||||
// iOS 14.0 - 14.5 `.tabBar` accessibilityTrait does not read out the index automatically
|
|
||||||
if #available(iOS 14.6, *) { } else {
|
|
||||||
tabBarItemView.accessibilityHint = String.localizedStringWithFormat( "Accessibility.TabBarItemView.Hint".localized, index + 1, numberOfItems)
|
|
||||||
}
|
|
||||||
stackView.addArrangedSubview(tabBarItemView)
|
stackView.addArrangedSubview(tabBarItemView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ GCC_WARN_UNDECLARED_SELECTOR = YES
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES
|
GCC_WARN_UNUSED_FUNCTION = YES
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES
|
GCC_WARN_UNUSED_VARIABLE = YES
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0
|
||||||
SDKROOT = iphoneos
|
SDKROOT = iphoneos
|
||||||
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES
|
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES
|
||||||
TARGETED_DEVICE_FAMILY = 1,2
|
TARGETED_DEVICE_FAMILY = 1,2
|
||||||
|
|
Загрузка…
Ссылка в новой задаче