diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff0bcff --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SegmentedControl.xcworkspace/xcuserdata diff --git a/SegmentedControl/SegmentedControl.swift b/SegmentedControl/SegmentedControl.swift index bca4b1c..900220a 100644 --- a/SegmentedControl/SegmentedControl.swift +++ b/SegmentedControl/SegmentedControl.swift @@ -12,7 +12,6 @@ open class SegmentedControl: UIControl { open weak var delegate: SegmentedControlDelegate? open var layoutPolicy: SegmentedControlLayoutPolicy = .fixed - open var contentInset = UIEdgeInsets.zero open fileprivate(set) var selectedIndex = 0 { didSet { @@ -20,13 +19,21 @@ open class SegmentedControl: UIControl { } } - open var segmentSpacing: CGFloat = 0 // Only available in dynamic layout policy - open var selectionBoxHeight: CGFloat = 0 // Only available in dynamic layout policy - open var selectionHorizontalPadding: CGFloat = Constant.defaultSelectionHorizontalPadding // Only available in dynamic layout policy + /// Only available in dynamic layout policy + open var segmentSpacing: CGFloat = 0 + /// Only available in dynamic layout policy + open var selectionBoxHeight: CGFloat = 0 + /// Only available in dynamic layout policy + open var selectionHorizontalPadding: CGFloat = Constant.defaultSelectionHorizontalPadding + /// Only available in dynamic layout policy, only the left and right inset works, the top and bottom inset will be ignored. + open var contentInset = UIEdgeInsets.zero - open var segmentWidth: CGFloat? // Only available in fixed layout policy - open var minimumSegmentWidth: CGFloat? // Only available in fixed layout policy - open var maximumSegmentWidth: CGFloat? // Only available in fixed layout policy + /// Only available in fixed layout policy + open var segmentWidth: CGFloat? + /// Only available in fixed layout policy + open var minimumSegmentWidth: CGFloat? + /// Only available in fixed layout policy + open var maximumSegmentWidth: CGFloat? open var isAnimationEnabled = true open var isUserDragEnabled = true @@ -35,12 +42,14 @@ open class SegmentedControl: UIControl { open var selectionBoxStyle: SegmentedControlSelectionBoxStyle = .none open var selectionBoxColor = UIColor.blue open var selectionBoxCornerRadius: CGFloat = 0 - open var selectionBoxEdgeInsets = UIEdgeInsets.zero // Only available in fixed layout policy + /// Only available in fixed layout policy + open var selectionBoxEdgeInsets = UIEdgeInsets.zero open var selectionIndicatorStyle: SegmentedControlSelectionIndicatorStyle = .none open var selectionIndicatorColor = UIColor.black open var selectionIndicatorHeight = SelectionIndicator.defaultHeight - open var selectionIndicatorEdgeInsets = UIEdgeInsets.zero // Only available in fixed layout policy + /// Only available in fixed layout policy + open var selectionIndicatorEdgeInsets = UIEdgeInsets.zero open var titleAttachedIconPositionOffset: (x: CGFloat, y: CGFloat) = (0, 0) open fileprivate(set) var titles = [NSAttributedString]() { @@ -236,19 +245,31 @@ open class SegmentedControl: UIControl { public extension SegmentedControl { // MARK: - Events fileprivate func update() { - scrollView.contentInset = contentInset scrollView.frame = CGRect(origin: CGPoint.zero, size: frame.size) scrollView.isScrollEnabled = isUserDragEnabled - scrollView.contentSize = CGSize(width: totalSegmentsWidth(), height: frame.height) - if layoutPolicy == .dynamic && (totalSegmentsWidth() + contentInset.left + contentInset.right) < frame.width { - let padding = (frame.width - totalSegmentsWidth() - contentInset.left - contentInset.right) / 2 - scrollView.contentInset.left = contentInset.left + padding - scrollView.contentInset.right = contentInset.right + padding + + switch layoutPolicy { + case .fixed: + scrollView.contentSize = CGSize(width: totalSegmentsWidth(), height: frame.height) + scrollView.contentInset = UIEdgeInsets.zero + case .dynamic: + scrollView.contentSize = CGSize(width: totalSegmentsWidth() + contentInset.left + contentInset.right, height: frame.height) + if (totalSegmentsWidth() + contentInset.left + contentInset.right) < frame.width { + let padding = (frame.width - totalSegmentsWidth()) / 2 + scrollView.contentInset = UIEdgeInsets(top: 0, left: padding - contentInset.left, bottom: 0, right: padding - contentInset.right) + } else { + scrollView.contentInset = UIEdgeInsets.zero + } } + scrollToSelectedIndex(animated: false) } fileprivate func scrollToSelectedIndex(animated: Bool) { + if layoutPolicy == .dynamic && (totalSegmentsWidth() + contentInset.left + contentInset.right) < frame.width { + return + } + let rectToScroll: CGRect = { var rectToScroll = self.rectForSelectedIndex() let scrollOffset: CGFloat = { @@ -263,14 +284,13 @@ public extension SegmentedControl { rectToScroll.size.width += scrollOffset * 2 return rectToScroll }() - if !(layoutPolicy == .dynamic && (totalSegmentsWidth() + contentInset.left + contentInset.right) < frame.width) { - scrollView.scrollRectToVisible(rectToScroll, animated: animated) - } + + scrollView.scrollRectToVisible(rectToScroll, animated: animated) } fileprivate func evaluateTouchIndex(fromTouchLocation touchLocation: CGPoint) -> Int? { func startX(_ index: Int) -> CGFloat { - return totalSegmentsWidths(before: index).reduce(0, +) + segmentSpacing * CGFloat(index) + return contentInset.left + totalSegmentsWidths(before: index).reduce(0, +) + segmentSpacing * CGFloat(index) } func endX(_ index: Int) -> CGFloat { return startX(index) + singleSegmentWidth(at: index) @@ -363,15 +383,15 @@ extension SegmentedControl: UIGestureRecognizerDelegate { } fileprivate func longPressDidBegin(_ gesture: UIGestureRecognizer) { - if let longPressIndex = locationIndex(for: gesture) { - if longPressIndex != selectedIndex && !isUnselectedSegmentsLongPressEnabled { - return - } - if 0.. UIImage? { - if let selectedImages = selectedImages { - if 0.. NSAttributedString? { - if let selectedTitles = selectedTitles { - if 0.. UIImage? { - if let titleAttachedIcons = titleAttachedIcons { - if 0.. UIImage? { - if let selectedTitleAttachedIcons = selectedTitleAttachedIcons { - if 0..