From f00dc00f0cf9d0e7623062dc8773a62dc3ffddb2 Mon Sep 17 00:00:00 2001 From: Anthony Tulai Date: Mon, 21 Nov 2022 13:06:26 -0500 Subject: [PATCH 1/3] [AT] add horizontal gradient capability --- TTSegmentedControl.playground/Contents.swift | 35 ++++-- .../Sources/TTSegmentedControl.swift | 111 +++++++++++------- .../timeline.xctimeline | 6 + TTSegmentedControl/TTSegmentedControl.swift | 22 +++- 4 files changed, 120 insertions(+), 54 deletions(-) create mode 100644 TTSegmentedControl.playground/timeline.xctimeline diff --git a/TTSegmentedControl.playground/Contents.swift b/TTSegmentedControl.playground/Contents.swift index e017fd8..d984d8e 100644 --- a/TTSegmentedControl.playground/Contents.swift +++ b/TTSegmentedControl.playground/Contents.swift @@ -7,7 +7,7 @@ import PlaygroundSupport let mainView = UIView(frame: CGRect(x: 0, y: 0, width: 350, height: 667)) mainView.backgroundColor = UIColor.white - +var segmentedC5: TTSegmentedControl = TTSegmentedControl() var segmentedC4: TTSegmentedControl = TTSegmentedControl() var segmentedC3: TTSegmentedControl = TTSegmentedControl() var segmentedC2: TTSegmentedControl = TTSegmentedControl() @@ -17,8 +17,7 @@ segmentedC1.frame = CGRect(x: 14, y: 73, width: 322, height: 76) segmentedC2.frame = CGRect(x: 14, y: 186, width: 322, height: 47) segmentedC3.frame = CGRect(x: 14, y: 299, width: 322, height: 47) segmentedC4.frame = CGRect(x: 14, y: 417, width: 133, height: 35) - - +segmentedC5.frame = CGRect(x: 14, y: 500, width: 322, height: 47) //SegmentedControl 1 @@ -27,7 +26,8 @@ segmentedC1.allowChangeThumbWidth = false segmentedC1.selectedTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight(0.3)) segmentedC1.defaultTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight(0.01)) segmentedC1.cornerRadius = 5 -segmentedC1.useGradient = false +segmentedC1.useVerticalGradient = false +segmentedC1.useHorizontalGradient = true segmentedC1.useShadow = false segmentedC1.thumbColor = TTSegmentedControl.UIColorFromRGB(0xD9D72B) @@ -40,7 +40,8 @@ segmentedC2.selectedTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weig segmentedC2.defaultTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight(0.01)) segmentedC2.cornerRadius = 0 segmentedC2.useShadow = false -segmentedC2.useGradient = true +segmentedC2.useVerticalGradient = true +segmentedC1.useHorizontalGradient = false segmentedC2.thumbGradientColors = [ TTSegmentedControl.UIColorFromRGB(0xFE2C5A), TTSegmentedControl.UIColorFromRGB(0xF10EAE)] @@ -50,7 +51,8 @@ segmentedC3.itemTitles = ["XS","S","M","L","XL"] segmentedC3.allowChangeThumbWidth = false segmentedC3.selectedTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight(0.3)) segmentedC3.defaultTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight(0.01)) -segmentedC3.useGradient = true +segmentedC3.useVerticalGradient = true +segmentedC3.useHorizontalGradient = false segmentedC3.useShadow = true segmentedC3.thumbShadowColor = TTSegmentedControl.UIColorFromRGB(0x22C6E7) segmentedC3.thumbGradientColors = [ TTSegmentedControl.UIColorFromRGB(0x25D0EC), TTSegmentedControl.UIColorFromRGB(0x1EA3D8)] @@ -64,17 +66,34 @@ segmentedC3.didSelectItemWith = { index, title in segmentedC4.itemTitles = ["OFF","ON"] segmentedC4.selectedTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight(0.3)) segmentedC4.defaultTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight(0.01)) -segmentedC4.useGradient = false +segmentedC4.useVerticalGradient = false +segmentedC4.useHorizontalGradient = false segmentedC4.thumbColor = TTSegmentedControl.UIColorFromRGB(0x1FDB58) segmentedC4.useShadow = true segmentedC4.thumbShadowColor = TTSegmentedControl.UIColorFromRGB(0x56D37C) segmentedC4.allowChangeThumbWidth = false + +//SegmentedControl 5 + +segmentedC5.itemTitles = ["XS","S","M","L","XL"] +segmentedC5.allowChangeThumbWidth = false +segmentedC5.selectedTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight(0.3)) +segmentedC5.defaultTextFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight(0.01)) +segmentedC5.useVerticalGradient = false +segmentedC5.useHorizontalGradient = true +segmentedC5.useShadow = true +segmentedC5.thumbShadowColor = TTSegmentedControl.UIColorFromRGB(0x22C6E7) +segmentedC5.thumbGradientColors = [ TTSegmentedControl.UIColorFromRGB(0x25D0EC), TTSegmentedControl.UIColorFromRGB(0x1EA3D8)] +segmentedC5.didSelectItemWith = { index, title in + print(index) +} + mainView.addSubview(segmentedC1) mainView.addSubview(segmentedC2) mainView.addSubview(segmentedC3) mainView.addSubview(segmentedC4) - +mainView.addSubview(segmentedC5) PlaygroundPage.current.liveView = mainView diff --git a/TTSegmentedControl.playground/Sources/TTSegmentedControl.swift b/TTSegmentedControl.playground/Sources/TTSegmentedControl.swift index b677cb2..65bcd18 100644 --- a/TTSegmentedControl.playground/Sources/TTSegmentedControl.swift +++ b/TTSegmentedControl.playground/Sources/TTSegmentedControl.swift @@ -8,16 +8,30 @@ import UIKit - @IBDesignable open class TTSegmentedControl: UIView { + //Version: 0.4.10 //Configure the options to for a custom design @IBInspectable open var defaultTextFont: UIFont = UIFont.helveticaNeueLight(12) @IBInspectable open var selectedTextFont: UIFont = UIFont.helveticaNeueLight(12) @IBInspectable open var defaultTextColor: UIColor = UIColor.black @IBInspectable open var selectedTextColor: UIColor = UIColor.white - @IBInspectable open var useGradient: Bool = true + @IBInspectable open var useHorizontalGradient: Bool = false { + didSet { + if useHorizontalGradient { + useVerticalGradient = false + } + } + } + + @IBInspectable open var useVerticalGradient: Bool = true { + didSet { + if useVerticalGradient { + useHorizontalGradient = false + } + } + } @IBInspectable open var containerBackgroundColor: UIColor = TTSegmentedControl.UIColorFromRGB(0xF4F4F4) @IBInspectable open var thumbColor: UIColor = UIColor.clear @@ -65,7 +79,7 @@ open class TTSegmentedControl: UIView { fileprivate var thumbView = UIView() fileprivate var selectedLabelsView = UIView() - fileprivate var isConfigurated = false + fileprivate var isConfigured = false fileprivate var lastPointX: CGFloat = 0 fileprivate var originalCenter = CGPoint.zero fileprivate var lastSelectedViewWidth: CGFloat = 0 @@ -79,7 +93,11 @@ open class TTSegmentedControl: UIView { fileprivate var allowToChangeThumb = false fileprivate var allowMove = true fileprivate var selectInitialItem = 0 - fileprivate var currentSelectedIndex = 0 + fileprivate var _currentIndex: Int = 0 + + open var currentIndex: Int { + return _currentIndex + } open var noItemSelected:Bool = false { didSet { @@ -100,32 +118,48 @@ open class TTSegmentedControl: UIView { super.init(coder: aDecoder) } + open func reconfigure() { + self.isConfigured = false + allItemLabels = [] + allSelectedItemLabels = [] + self.containerView.removeFromSuperview() + self.thumbContainerView.removeFromSuperview() + self.thumbView.removeFromSuperview() + self.selectedLabelsView.removeFromSuperview() + + self.thumbContainerView = UIView() + self.thumbView = UIView() + self.selectedLabelsView = UIView() + self.containerView = UIView() + self.layoutSubviews() + } open override func layoutSubviews() { super.layoutSubviews() - if !isConfigurated { + if !isConfigured { configureItemsConent() configureViewBounds() - configureContainerView() configureItems() configureSelectedView() configureSelectedLabelsView() configureSelectedLabelItems() - - isConfigurated = true + isConfigured = true } containerView.frame = bounds containerView.layer.cornerRadius = cornerRadius < 0 ? 0.5 * containerView.frame.size.height : cornerRadius selectedLabelsView.frame = containerView.bounds - updateFrameForLables(allItemLabels) - updateFrameForLables(allSelectedItemLabels) + updateFrameForLabels(allItemLabels) + updateFrameForLabels(allSelectedItemLabels) updateSelectedViewFrame() - selectItemAt(index:currentSelectedIndex) + if !noItemSelected { + selectItemAt(index: _currentIndex) + } + _ = self.subviews.map({$0.isExclusiveTouch = true}) } @@ -150,9 +184,7 @@ open class TTSegmentedControl: UIView { return 100 } - fileprivate var isSwitch: Bool { - return attributedDefaultTitles.count == 2 - } + open var isSwitch: Bool = false //MARK: - Helpers static public func UIColorFromRGB(_ rgbValue: UInt) -> UIColor { @@ -226,9 +258,9 @@ extension TTSegmentedControl { thumbContainerView.layer.insertSublayer(shadowLayer, at: 0) } - if thumbGradientColors != nil && self.useGradient { - gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0) - gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0) + if thumbGradientColors != nil && (useHorizontalGradient || useVerticalGradient) { + gradientLayer.startPoint = useVerticalGradient ? CGPoint(x: 0.5, y: 0.0) : CGPoint(x: 0.0, y: 0.5) + gradientLayer.endPoint = useVerticalGradient ? CGPoint(x: 0.5, y: 1.0) : CGPoint(x: 1.0, y: 0.5) gradientLayer.backgroundColor = thumbColor.cgColor gradientLayer.colors = thumbGradientColors!.map({$0.cgColor}) thumbView.backgroundColor = UIColor.clear @@ -326,7 +358,7 @@ extension TTSegmentedControl { } } - fileprivate func updateFrameForLables(_ allLabels: [UILabel]) { + fileprivate func updateFrameForLabels(_ allLabels: [UILabel]) { let itemWidth = sectionWidth var totalLabelWidth: CGFloat = 0 for label in allLabels { @@ -433,7 +465,7 @@ extension TTSegmentedControl { let index = label.tag let title = label.text - self.currentSelectedIndex = index + self._currentIndex = index didSelectItemWith?(index, title) if title == nil { @@ -479,10 +511,8 @@ extension TTSegmentedControl { } fileprivate func changeThumbFrameForPoint(_ point: CGPoint, animated: Bool) { - - selectedLabelsView.isHidden = false - thumbView.isHidden = false - + noItemSelected = false + lastPointX = point.x let label = labelForPoint(point) let center = label.center @@ -638,27 +668,24 @@ extension TTSegmentedControl { extension TTSegmentedControl { - open var currentIndex: Int { - if !isConfigurated { - return 0 - } - let label = labelForPoint(thumbContainerView.center) - let index = allItemLabels.firstIndex(of: label) - return index ?? 0 - } - public func selectItemAt(index: Int, animated: Bool = false) { - if !isConfigurated { - currentSelectedIndex = index + guard (index >= 0 && index < itemTitles.count) else { + print("[TTSegmentedControl]: Index \(index) is out of range.") return } - let label = allItemLabels[min(index, attributedDefaultTitles.count)] - selectedLabelsView.isHidden = noItemSelected + + _currentIndex = index + + guard isConfigured else { + return + } + + let label = allItemLabels[index] changeThumbFrameForPoint(label.center, animated: animated) } open func changeTitle(_ title: String, atIndex: Int) { - if !isConfigurated { + if !isConfigured { return } @@ -691,7 +718,7 @@ extension TTSegmentedControl { } open func changeAttributedTitle(_ title: NSAttributedString, selectedTile: NSAttributedString?, atIndex: Int) { - if !isConfigurated { + if !isConfigured { return } @@ -724,7 +751,7 @@ extension TTSegmentedControl { } open func titleForItemAtIndex(_ index: Int) -> String { - if !isConfigurated { + if !isConfigured { return "" } @@ -736,7 +763,7 @@ extension TTSegmentedControl { } open func changeThumbShadowColor(_ color: UIColor) { - if !isConfigurated { + if !isConfigured { return } thumbShadowColor = color @@ -744,7 +771,7 @@ extension TTSegmentedControl { } open func changeThumbColor(_ color: UIColor) { - if !isConfigurated { + if !isConfigured { return } thumbColor = color @@ -752,7 +779,7 @@ extension TTSegmentedControl { } open func changeBackgroundColor(_ color: UIColor) { - if !isConfigurated { + if !isConfigured { return } containerBackgroundColor = color diff --git a/TTSegmentedControl.playground/timeline.xctimeline b/TTSegmentedControl.playground/timeline.xctimeline new file mode 100644 index 0000000..bf468af --- /dev/null +++ b/TTSegmentedControl.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/TTSegmentedControl/TTSegmentedControl.swift b/TTSegmentedControl/TTSegmentedControl.swift index 41260bd..18debbc 100644 --- a/TTSegmentedControl/TTSegmentedControl.swift +++ b/TTSegmentedControl/TTSegmentedControl.swift @@ -18,7 +18,21 @@ open class TTSegmentedControl: UIView { @IBInspectable open var selectedTextFont: UIFont = UIFont.helveticaNeueLight(12) @IBInspectable open var defaultTextColor: UIColor = UIColor.black @IBInspectable open var selectedTextColor: UIColor = UIColor.white - @IBInspectable open var useGradient: Bool = true + @IBInspectable open var useHorizontalGradient: Bool = false { + didSet { + if useHorizontalGradient { + useVerticalGradient = false + } + } + } + + @IBInspectable open var useVerticalGradient: Bool = true { + didSet { + if useVerticalGradient { + useHorizontalGradient = false + } + } + } @IBInspectable open var containerBackgroundColor: UIColor = TTSegmentedControl.UIColorFromRGB(0xF4F4F4) @IBInspectable open var thumbColor: UIColor = UIColor.clear @@ -245,9 +259,9 @@ extension TTSegmentedControl { thumbContainerView.layer.insertSublayer(shadowLayer, at: 0) } - if thumbGradientColors != nil && self.useGradient { - gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0) - gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0) + if thumbGradientColors != nil && (useHorizontalGradient || useVerticalGradient) { + gradientLayer.startPoint = useVerticalGradient ? CGPoint(x: 0.5, y: 0.0) : CGPoint(x: 0.0, y: 0.5) + gradientLayer.endPoint = useVerticalGradient ? CGPoint(x: 0.5, y: 1.0) : CGPoint(x: 1.0, y: 0.5) gradientLayer.backgroundColor = thumbColor.cgColor gradientLayer.colors = thumbGradientColors!.map({$0.cgColor}) thumbView.backgroundColor = UIColor.clear From 9f1687f367b30eedb4785b66917297497fe5d82f Mon Sep 17 00:00:00 2001 From: Anthony Tulai Date: Thu, 8 Jun 2023 13:28:47 -0400 Subject: [PATCH 2/3] Fix middle segment thumb showing much smaller than other segment thumbs when using three thumbs --- TTSegmentedControl/TTSegmentedControl.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TTSegmentedControl/TTSegmentedControl.swift b/TTSegmentedControl/TTSegmentedControl.swift index 18debbc..e9900d0 100644 --- a/TTSegmentedControl/TTSegmentedControl.swift +++ b/TTSegmentedControl/TTSegmentedControl.swift @@ -371,7 +371,7 @@ extension TTSegmentedControl { for label in allLabels { label.frame.origin.y = 0 - label.frame.size.width = min(label.frame.size.width, itemWidth) + label.frame.size.width = itemWidth label.frame.size.height = self.frame.size.height label.frame.origin.x = (sectionWidth - label.frame.size.width)/2 + i * itemWidth i += 1 From 769522fdc8f8229b2910ecdaf606366a881c788c Mon Sep 17 00:00:00 2001 From: Anthony Tulai Date: Wed, 14 Jun 2023 16:43:54 -0400 Subject: [PATCH 3/3] update target to iOS 15 --- TTSegmentedControl.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TTSegmentedControl.podspec b/TTSegmentedControl.podspec index 6f30864..c4bc9ac 100644 --- a/TTSegmentedControl.podspec +++ b/TTSegmentedControl.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |s| # 1 s.platform = :ios -s.ios.deployment_target = '8.0' +s.ios.deployment_target = '15.0' s.license = 'MIT' s.name = "TTSegmentedControl" s.summary = "An elegant, animated and customizable segmented control for iOS."