Merge branch 'mbruce/bugfixes' into 'develop'

updated version / release notes for typopgraphy update

See merge request BPHV_MIPS/vds_ios!102
This commit is contained in:
Bruce, Matt R 2023-08-10 20:50:28 +00:00
commit 309a74196b
6 changed files with 160 additions and 85 deletions

View File

@ -1167,7 +1167,7 @@
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 37;
CURRENT_PROJECT_VERSION = 39;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
@ -1204,7 +1204,7 @@
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 37;
CURRENT_PROJECT_VERSION = 39;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;

View File

@ -165,7 +165,10 @@ open class BadgeIndicator: View {
/// Character that is always at the begging. Accepts any character and if unaffected by maximumDigits.
open var leadingCharacter: String? { didSet { setNeedsUpdate() }}
/// Accepts any text or character. It is unaffected by maximumDigits.
open var trailingText: String? { didSet { setNeedsUpdate() }}
/// Determines the size of the Badge Indicator as well as the textStyle and padding used.
open var size: Size = .xxlarge { didSet { setNeedsUpdate() }}
@ -359,10 +362,23 @@ open class BadgeIndicator: View {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
text = formatter.string(from: .init(integerLiteral: maxBadgetCount))!
if let leadingCharacter {
//leading
if let leadingCharacter, !leadingCharacter.isEmpty {
text = "\(leadingCharacter)\(text)"
}
//maximumDigits
if maximumDigits.value < "\(badgeCount)".count {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
text = "\(text)+"
}
//trailing
if let trailingText, !trailingText.isEmpty {
text = "\(text) \(trailingText)"
}
}
return text
}

View File

@ -20,7 +20,11 @@ extension Tabs {
open var index: Int = 0
///label to write out the text
open var label: Label = Label().with { $0.isUserInteractionEnabled = false }
open var label: Label = Label().with {
$0.isUserInteractionEnabled = false
$0.setContentCompressionResistancePriority(.required, for: .horizontal)
$0.setContentHuggingPriority(.required, for: .horizontal)
}
///orientation of the tabs
open var orientation: Tabs.Orientation = .horizontal { didSet { setNeedsUpdate() } }
@ -38,7 +42,7 @@ extension Tabs {
open var width: CGFloat? { didSet { setNeedsUpdate() } }
///The text label of the tab.
open var text: String = "" { didSet { setNeedsUpdate() } }
open var text: String = "Tab" { didSet { setNeedsUpdate() } }
///Minimum width for the tab
open var minWidth: CGFloat = 44.0 { didSet { setNeedsUpdate() } }
@ -88,12 +92,14 @@ extension Tabs {
return VDSLayout.Spacing.space2X.value
}
}
private let layoutGuide = UILayoutGuide()
private var widthConstraint: NSLayoutConstraint {
private var widthConstraint: NSLayoutConstraint? {
if let width, orientation == .vertical {
return label.widthAnchor.constraint(equalToConstant: width)
return layoutGuide.widthAnchor.constraint(equalToConstant: width)
} else {
return label.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidth)
return layoutGuide.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidth)
}
}
@ -115,35 +121,30 @@ extension Tabs {
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
open override func setup() {
super.setup()
addLayoutGuide(layoutGuide)
addSubview(label)
accessibilityTraits = .button
isAccessibilityElement = true
label.translatesAutoresizingMaskIntoConstraints = false
label.pinTrailing()
labelTopConstraint = label.topAnchor.constraint(equalTo: topAnchor)
labelTopConstraint?.isActive = true
labelBottomConstraint = label.bottomAnchor.constraint(equalTo: bottomAnchor)
labelBottomConstraint?.isActive = true
labelLeadingConstraint = label.leadingAnchor.constraint(equalTo: leadingAnchor)
labelLeadingConstraint?.isActive = true
let layoutGuide = UILayoutGuide()
addLayoutGuide(layoutGuide)
labelWidthConstraint = layoutGuide.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidth)
labelWidthConstraint?.isActive = true
//activate the constraints
NSLayoutConstraint.activate([layoutGuide.topAnchor.constraint(equalTo: topAnchor),
layoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor),
layoutGuide.leadingAnchor.constraint(equalTo: leadingAnchor),
layoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor)])
label.pinTrailing(layoutGuide.trailingAnchor)
labelTopConstraint = label.topAnchor.constraint(equalTo: layoutGuide.topAnchor)
labelTopConstraint?.isActive = true
labelBottomConstraint = label.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor)
labelBottomConstraint?.isActive = true
labelLeadingConstraint = label.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor)
labelLeadingConstraint?.isActive = true
}
/// Function used to make changes to the View based off a change events or from local properties.
@ -151,12 +152,8 @@ extension Tabs {
super.updateView()
guard !text.isEmpty else { return }
//label properties
label.text = text
label.textStyle = textStyle
label.textPosition = textPosition
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
accessibilityIdentifier = "VDSTab:\(text)"
//constaints
labelWidthConstraint?.isActive = false
@ -165,8 +162,17 @@ extension Tabs {
labelLeadingConstraint?.constant = leadingSpace
labelTopConstraint?.constant = otherSpace
labelBottomConstraint?.constant = -otherSpace
//label properties
label.text = text
label.surface = surface
label.textStyle = textStyle
label.textPosition = textPosition
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
setNeedsLayout()
layoutIfNeeded()
}
open override func updateAccessibility() {
@ -176,7 +182,7 @@ extension Tabs {
open override func layoutSubviews() {
super.layoutSubviews()
removeBorders()
if isSelected {
@ -185,5 +191,3 @@ extension Tabs {
}
}
}

View File

@ -36,7 +36,7 @@ open class Tabs: View {
}
}
}
//Type of behavior for Scrolling
public enum Overflow: String, CaseIterable {
case scroll
@ -48,7 +48,7 @@ open class Tabs: View {
case medium
case large
}
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
@ -57,13 +57,13 @@ open class Tabs: View {
open var onTabChange: ((Int) -> Void)?
//Determines the layout of the Tabs, defaults to horizontal
open var orientation: Orientation = .horizontal { didSet { if oldValue != orientation { updateTabItems() } } }
open var orientation: Orientation = .horizontal { didSet { if oldValue != orientation { setNeedsUpdate() } } }
///When true, Tabs will have border line. If false is passed then the border line won't be visible.
open var borderLine: Bool = true { didSet { setNeedsUpdate() } }
///It will fill the Tabs to the width of the compoent and all Tabs will be in equal width when orientation is horizontal. This is recommended when there are no more than 2-3 tabs.
open var fillContainer: Bool = false { didSet { updateTabItems() } }
open var fillContainer: Bool = false { didSet { setNeedsUpdate() } }
///When true, Tabs will be sticky to top of page, when orientation is vertical.
open var indicatorFillTab: Bool = false { didSet { setNeedsUpdate() } }
@ -75,22 +75,22 @@ open class Tabs: View {
open var minWidth: CGFloat = 44.0 { didSet { setNeedsUpdate() } }
///If set to 'scroll', Tabs can be overflow and scrollable. With 'none', tabs will not overflow and labels will be wrapped to multiple lines if the label text is long.
open var overflow: Overflow = .scroll { didSet { updateTabItems() } }
open var overflow: Overflow = .scroll { didSet { setNeedsUpdate() } }
///The initial Selected Tab's index and is set once a Tab is clicked
open var selectedIndex: Int = 0 { didSet { setNeedsUpdate() } }
///Determines the size of the Tabs TextStyle
open var size: Size = .medium { didSet { updateTabItems() } }
open var size: Size = .medium { didSet { setNeedsUpdate() } }
///When true, Tabs will be sticky to top of page, when orientation is vertical.
open var sticky: Bool = false { didSet { setNeedsUpdate() } }
///Model of the Tabs you are wanting to show.
open var tabModels: [TabModel] = [] { didSet { updateTabItems() } }
open var tabViews: [Tab] = []
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
@ -107,7 +107,7 @@ open class Tabs: View {
private var borderlineViewHeightConstraint: NSLayoutConstraint?
private var borderlineViewWidthConstraint: NSLayoutConstraint?
private var contentViewWidthConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Configuration Properties
//--------------------------------------------------
@ -123,7 +123,7 @@ open class Tabs: View {
if orientation == .horizontal && fillContainer {
return .fillEqually
} else {
return orientation == .horizontal ? .fillProportionally : .fill
return .fill //orientation == .horizontal ? .fillProportionally : .fill
}
}
@ -150,15 +150,15 @@ open class Tabs: View {
public override init(frame: CGRect) {
super.init(frame: frame)
}
public convenience required init() {
self.init(frame: .zero)
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
}
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
@ -169,7 +169,7 @@ open class Tabs: View {
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
addSubview(scrollView)
contentView = View()
contentView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(contentView)
@ -180,10 +180,11 @@ open class Tabs: View {
tabStackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(borderlineView)
contentView.addSubview(tabStackView)
scrollView.pinToSuperView()
contentView.pinToSuperView()
tabStackView.pinToSuperView()
contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
borderlineViewWidthConstraint = borderlineView.widthAnchor.constraint(equalToConstant: 0)
@ -193,21 +194,32 @@ open class Tabs: View {
borderlineViewTrailingConstraint = borderlineView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
borderlineViewTopConstraint = borderlineView.topAnchor.constraint(equalTo: contentView.topAnchor)
borderlineViewBottomConstraint = borderlineView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
}
/// Function used to make changes to the View based off a change events or from local properties.
open override func updateView() {
super.updateView()
updateStackView()
updateTabs()
updateContentView()
updateBorderline()
}
//--------------------------------------------------
// MARK: - Private Methods
//--------------------------------------------------
/// Removes all of the Tab Views and creates new ones from the Tab Models property.
private func updateTabItems() {
updateTabItems(with: tabModels)
}
private func updateTabItems(with models: [TabModel]) {
// Clear existing tab items
for tabItem in tabViews {
tabItem.removeFromSuperview()
}
tabViews.removeAll()
// Create new tab items from the models
for model in models {
for model in tabModels {
let tabItem = Tab()
tabItem.size = size
tabItem.text = model.text
@ -224,25 +236,28 @@ open class Tabs: View {
setNeedsUpdate()
scrollToSelectedIndex(animated: false)
}
/// Scrolls to the selected Tab by the selectedIndex.
/// - Parameter animated: If there is animation of the scrolling to the selectedIndex.
private func scrollToSelectedIndex(animated: Bool) {
if orientation == .horizontal && self.overflow == .scroll, selectedIndex < tabViews.count {
let selectedTab = tabViews[selectedIndex]
scrollView.scrollRectToVisible(selectedTab.frame, animated: animated)
}
}
/// Function used to make changes to the View based off a change events or from local properties.
open override func updateView() {
super.updateView()
// Update the stackview properties
/// Updates the StackView from local properties.
private func updateStackView() {
tabStackView.distribution = stackViewDistribution
tabStackView.axis = stackViewAxis
tabStackView.alignment = stackViewAlignment
tabStackView.spacing = stackViewSpacing
// Update tab appearance based on properties
}
/// Updates the Tab individual views from local properties.
private func updateTabs() {
for (index, tabItem) in tabViews.enumerated() {
tabItem.size = size
tabItem.isSelected = selectedIndex == index
@ -254,14 +269,9 @@ open class Tabs: View {
tabItem.indicatorPosition = indicatorPosition
tabItem.accessibilityValue = "\(index+1) of \(tabViews.count) Tabs"
}
//update the width based on rules
updateContentView()
setNeedsLayout()
layoutIfNeeded()
}
// Update the ContentView and ScrollView ContentSize from local properties.
private func updateContentView() {
// Deactivate old constraint
contentViewWidthConstraint?.isActive = false
@ -269,10 +279,10 @@ open class Tabs: View {
// Apply overflow
if orientation == .horizontal && overflow == .scroll && !fillContainer {
let contentWidth = tabStackView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).width
contentViewWidthConstraint = contentView.widthAnchor.constraint(equalToConstant: contentWidth)
contentViewWidthConstraint = nil
scrollView.contentSize = CGSize(width: contentWidth, height: scrollView.bounds.height)
} else {
contentViewWidthConstraint = contentView.widthAnchor.constraint(equalTo: widthAnchor)
contentViewWidthConstraint = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
scrollView.contentSize = bounds.size
}
@ -284,9 +294,8 @@ open class Tabs: View {
scrollToSelectedIndex(animated: true)
}
open override func layoutSubviews() {
super.layoutSubviews()
//update layout for borderline
private func updateBorderline() {
//borderLine
if borderLine {
var edge: UIRectEdge = .bottom
@ -302,21 +311,21 @@ open class Tabs: View {
borderlineViewBottomConstraint?.isActive = false
borderlineViewHeightConstraint?.isActive = false
borderlineViewWidthConstraint?.isActive = false
if edge == .left {
borderlineViewWidthConstraint?.constant = borderlineSize
borderlineViewWidthConstraint?.isActive = true
borderlineViewTopConstraint?.isActive = true
borderlineViewLeadingConstraint?.isActive = true
borderlineViewBottomConstraint?.isActive = true
} else if edge == .top {
borderlineViewHeightConstraint?.constant = borderlineSize
borderlineViewHeightConstraint?.isActive = true
borderlineViewTopConstraint?.isActive = true
borderlineViewLeadingConstraint?.isActive = true
borderlineViewTrailingConstraint?.isActive = true
} else {
borderlineViewHeightConstraint?.constant = borderlineSize
borderlineViewHeightConstraint?.isActive = true
@ -330,4 +339,6 @@ open class Tabs: View {
borderlineView.isHidden = true
}
}
}

View File

@ -50,6 +50,10 @@ open class ToggleView: Control, Changeable {
$0.isUserInteractionEnabled = false
}
private let shadowLayer1 = CALayer()
private let shadowLayer2 = CALayer()
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
@ -136,6 +140,25 @@ open class ToggleView: Control, Changeable {
toggleView.setContentHuggingPriority(.required, for: .vertical)
setContentHuggingPriority(.required, for: .horizontal)
setContentHuggingPriority(.required, for: .vertical)
//knobview dropshadow
// Update shadow layers frames to match the view's bounds
knobView.layer.insertSublayer(shadowLayer1, at: 0)
knobView.layer.insertSublayer(shadowLayer2, at: 0)
let shadowColor = VDSColor.paletteBlack.cgColor
shadowLayer1.cornerRadius = knobView.layer.cornerRadius
shadowLayer1.shadowColor = shadowColor
shadowLayer1.shadowOpacity = 0.24
shadowLayer1.shadowOffset = .init(width: 0, height: 1)
shadowLayer1.shadowRadius = 5.0
shadowLayer2.cornerRadius = knobView.layer.cornerRadius
shadowLayer2.shadowColor = shadowColor
shadowLayer2.shadowOpacity = 0.08
shadowLayer2.shadowOffset = .init(width: 0, height: 2)
shadowLayer2.shadowRadius = 2.0
}
/// Resets to default settings.
@ -180,8 +203,8 @@ open class ToggleView: Control, Changeable {
// MARK: - Toggle
//--------------------------------------------------
private func constrainKnob(){
self.knobLeadingConstraint?.isActive = false
self.knobTrailingConstraint?.isActive = false
knobLeadingConstraint?.isActive = false
knobTrailingConstraint?.isActive = false
if isOn {
knobTrailingConstraint = toggleView.trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 2)
knobLeadingConstraint = knobView.leadingAnchor.constraint(greaterThanOrEqualTo: toggleView.leadingAnchor)
@ -191,13 +214,17 @@ open class ToggleView: Control, Changeable {
}
knobTrailingConstraint?.isActive = true
knobLeadingConstraint?.isActive = true
self.layoutIfNeeded()
setNeedsLayout()
layoutIfNeeded()
}
private func updateToggle() {
let toggleColor = toggleColorConfiguration.getColor(self)
let knobColor = knobColorConfiguration.getColor(self)
shadowLayer1.backgroundColor = knobColor.cgColor
shadowLayer2.backgroundColor = knobColor.cgColor
if disabled || !isAnimated {
toggleView.backgroundColor = toggleColor
knobView.backgroundColor = knobColor
@ -213,6 +240,14 @@ open class ToggleView: Control, Changeable {
}, completion: nil)
}
}
open override func layoutSubviews() {
super.layoutSubviews()
shadowLayer1.frame = knobView.bounds
shadowLayer2.frame = knobView.bounds
}
}
// MARK: AppleGuidlinesTouchable

View File

@ -1,3 +1,12 @@
1.0.39
=======
- CXTDT-423141 - Tabs - Selected Tab dark mode text color
- CXTDT-426623 - Toggle - Drop Shadow on Knob
1.0.38
=======
- Fixed bug in Typography TitleLarge Font update for Mobile
1.0.37
=======
- ONEAPP-4684 - Update Accessibility for Tooltip