Skip to content

Commit

Permalink
Merge pull request #14 from teambition/feature/support-show-unselecte…
Browse files Browse the repository at this point in the history
…d-title-box

feature: support show unselected title box
  • Loading branch information
D-Wang authored Jun 18, 2020
2 parents d4b94b9 + fa6c528 commit d65bb20
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 12 deletions.
61 changes: 50 additions & 11 deletions SegmentedControl/SegmentedControl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ open class SegmentedControl: UIControl {
open var selectionBoxCornerRadius: CGFloat = 0
/// Only available in fixed layout policy
open var selectionBoxEdgeInsets = UIEdgeInsets.zero

/// Only available in selectionBoxStyle == .default
open var shouldShowAllBox: Bool = false
open var unselectedBoxColor = UIColor(red: 38.0/255.0, green: 38.0/255.0, blue: 38.0/255.0, alpha: 0.04)
private var allBoxLayers: [CALayer] = []

open var selectionIndicatorStyle: SegmentedControlSelectionIndicatorStyle = .none
open var selectionIndicatorColor = UIColor.black
Expand All @@ -55,6 +60,7 @@ open class SegmentedControl: UIControl {
open var selectionIndicatorCornerRadius: CGFloat = 0
open var titleAttachedIconPositionOffset: (x: CGFloat, y: CGFloat) = (0, 0)


/// Use center alignment when not fill the width
open var horizontallyCenterIfPossible: Bool = true

Expand All @@ -63,6 +69,7 @@ open class SegmentedControl: UIControl {
updateTitleSizes()
}
}

open fileprivate(set) var selectedTitles: [NSAttributedString]?
open fileprivate(set) var images = [UIImage]()
open fileprivate(set) var selectedImages: [UIImage]?
Expand Down Expand Up @@ -166,15 +173,28 @@ open class SegmentedControl: UIControl {
if !(0..<segmentsCount() ~= selectedIndex) {
return
}
let oldSelectedIndex = selectedIndex
selectedIndex = index
scrollToSelectedIndex(animated: animated)
if !animated {
selectionBoxLayer.actions = ["position": NSNull(), "bounds": NSNull()]
if shouldShowAllBox {
allBoxLayers[oldSelectedIndex].backgroundColor = unselectedBoxColor.cgColor
allBoxLayers[selectedIndex].backgroundColor = selectionBoxColor.cgColor
} else {
selectionBoxLayer.actions = ["position": NSNull(), "bounds": NSNull()]
selectionBoxLayer.frame = frameForSelectionBox(with: selectedIndex)
}

selectionIndicatorLayer.actions = ["position": NSNull(), "bounds": NSNull()]
selectionBoxLayer.frame = frameForSelectionBox()
selectionIndicatorLayer.frame = frameForSelectionIndicator()
} else {
selectionBoxLayer.actions = nil
if shouldShowAllBox {
allBoxLayers[oldSelectedIndex].backgroundColor = unselectedBoxColor.cgColor
allBoxLayers[selectedIndex].backgroundColor = selectionBoxColor.cgColor
} else {
selectionBoxLayer.actions = nil
}

selectionIndicatorLayer.actions = nil
}
}
Expand Down Expand Up @@ -250,6 +270,18 @@ open class SegmentedControl: UIControl {
selectionBoxLayer.backgroundColor = selectionBoxColor.cgColor
selectionIndicatorLayer.backgroundColor = selectionIndicatorColor.cgColor

if shouldShowAllBox {
allBoxLayers.removeAll()
for index in 0..<segmentsCount() {
let titleBoxLayer = CALayer()
titleBoxLayer.frame = frameForSelectionBox(with: index)
titleBoxLayer.cornerRadius = selectionBoxCornerRadius
titleBoxLayer.backgroundColor = unselectedBoxColor.cgColor
scrollView.layer.addSublayer(titleBoxLayer)
allBoxLayers.append(titleBoxLayer)
}
}

switch style {
case .text:
drawTitles()
Expand Down Expand Up @@ -514,6 +546,7 @@ public extension SegmentedControl {
}
return title
}()

let titleLayer: CATextLayer = {
let titleLayer = CATextLayer()
titleLayer.frame = titleRect
Expand Down Expand Up @@ -579,11 +612,17 @@ public extension SegmentedControl {
}

fileprivate func drawSelectionBox() {
selectionBoxLayer.frame = frameForSelectionBox()
selectionBoxLayer.cornerRadius = selectionBoxCornerRadius
if selectionBoxLayer.superlayer == nil {
scrollView.layer.insertSublayer(selectionBoxLayer, at: 0)
if shouldShowAllBox {
let selectedBoxLayer = allBoxLayers[selectedIndex]
selectedBoxLayer.backgroundColor = selectionBoxColor.cgColor
} else {
selectionBoxLayer.frame = frameForSelectionBox(with: selectedIndex)
selectionBoxLayer.cornerRadius = selectionBoxCornerRadius
if selectionBoxLayer.superlayer == nil {
scrollView.layer.insertSublayer(selectionBoxLayer, at: 0)
}
}

}

fileprivate func drawSelectionIndicator() {
Expand Down Expand Up @@ -643,17 +682,17 @@ public extension SegmentedControl {
}
}

fileprivate func frameForSelectionBox() -> CGRect {
fileprivate func frameForSelectionBox(with index: Int) -> CGRect {
if selectionBoxStyle == .none {
return CGRect.zero
}

let xPosition: CGFloat = {
switch layoutPolicy {
case .fixed:
return singleSegmentWidth() * CGFloat(selectedIndex)
return singleSegmentWidth() * CGFloat(index)
case .dynamic:
let frontWidths = totalSegmentsWidths(before: selectedIndex)
let frontWidths = totalSegmentsWidths(before: index)
return contentInset.left + frontWidths.reduce(0, +) + segmentSpacing * CGFloat(frontWidths.count)
}
}()
Expand All @@ -669,7 +708,7 @@ public extension SegmentedControl {
case .dynamic:
return CGRect(x: xPosition,
y: (frame.height - selectionBoxHeight) / 2,
width: singleSegmentWidth(at: selectedIndex),
width: singleSegmentWidth(at: index),
height: selectionBoxHeight)
}
}()
Expand Down
4 changes: 3 additions & 1 deletion SegmentedControlExample/ExampleViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,13 @@ class ExampleViewController: UIViewController {
segmentedControl3.setTitles(titles, selectedTitles: selectedTitles)
segmentedControl3.delegate = self
segmentedControl3.layoutPolicy = .dynamic
segmentedControl3.segmentSpacing = 5
segmentedControl3.segmentSpacing = 20
segmentedControl3.selectionBoxHeight = 30
segmentedControl3.selectionHorizontalPadding = 15
segmentedControl3.selectionBoxStyle = .default
segmentedControl3.selectionBoxCornerRadius = 15
segmentedControl3.shouldShowAllBox = true

segmentedControl3.selectionBoxColor = kLivelyBlueColor
segmentedControl3.contentInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
segmentedControl3.setTitleAttachedIcons([#imageLiteral(resourceName: "taskSegmentAdditionIcon")], selectedTitleAttachedIcons: [#imageLiteral(resourceName: "taskSegmentAdditionIconSelected")])
Expand Down

0 comments on commit d65bb20

Please sign in to comment.