A drop-in replacement for UISegmentControl. Written in swift 3.0. It's heavily inspired by HMSegmentedControl
- Support both text, images and text + image (easy to set image position: left, right, top, bottom)
- Support attributed title
- Based on protocol, support custom data model as the data source
- Support horizontal scrolling
- Support advanced title styling with text attributes for font, color, kerning, shadow, etc.
- Support selection indicator both on top and bottom, and box indicator
- Support blocks
- Works with ARC and iOS >= 8
Just like the code below
let segment = NLSegmentControl(frame: CGRect(x: 0, y: 80, width: UIScreen.main.bounds.width, height: 40))
segment.segments = ["One Day", "Two", "Three", "Four dogs", "Five fingers", "Six trees", "Seven", "Eight", "Nine", "Ten"]
segment.indexChangedHandler = {
(index) in
print("index changed: \(index)")
}
self.view.addSubview(segment)
segment.reloadSegments()
See more in the demo project.
- text only:
segment.segments = ["Trending", "News", "Library"]
- image only:
segment.segments = [UIImage(named: "baby")!,UIImage(named: "bag")!,UIImage(named: "diamond")!]
if you want to set the selected image for the selected segment, try this:
let item1 = NLSegmentItem(image: UIImage(named: "baby"), selectedImage: UIImage(named: "baby_s"))
let item2 = NLSegmentItem(image: UIImage(named: "bag"), selectedImage: UIImage(named: "bag_s"))
let item3 = NLSegmentItem(image: UIImage(named: "diamond"), selectedImage:UIImage(named: "diamond_s"))
segment.segments = [item1, item2, item3]
- text and image:
1.use NLSegmentItem struct
Note: title
, image
, selectedImage
are all optional
let item1 = NLUISegmentItem(title: "Baby", image: UIImage(named: "baby"), selectedImage: UIImage(named: "baby_s"))
let item2 = NLUISegmentItem(title: "Bag", image: UIImage(named: "bag"), selectedImage: UIImage(named: "bag_s"))
let item3 = NLUISegmentItem(title: "Diamond", image: UIImage(named: "diamond"), selectedImage: UIImage(named: "diamond_s"))
segment.segments = [item1, item2, item3]
2.use your own data model, just make it implements NLSegment
protocol.
struct Category {
var categoryTitle: String?
var categoryImage: String?
var categorySelectedImage: String?
init(title: String? = nil, image: String? = nil, selectedImage: String? = nil) {
self.categoryTitle = title
self.categoryImage = image
self.categorySelectedImage = selectedImage
}
}
extension Category: NLSegment {
var segmentTitle: String? {
return categoryTitle
}
var segmentImage: UIImage? {
if let img = categoryImage {
return UIImage(named: img)
}
return nil
}
var segmentSelectedImage: UIImage? {
if let img = categorySelectedImage {
return UIImage(named: img)
}
return nil
}
}
let item1 = Category(title: "Baby", image: "baby", selectedImage: "baby_s")
let item2 = Category(title: "Bag", image: "bag", selectedImage: "bag_s")
let item3 = Category(title: "Diamond", image: "diamond", selectedImage: "diamond_s")
segment.segments = [item1, item2, item3]
- attributed title:
Set the segmentTitleFormatter
property, you can set any attribute to the segment as you want.
If return nil, the segment will use the common titleTextAttributes
property.
attrSegment.segmentTitleFormatter = {
(segment, selected) -> NSAttributedString? in
if let cate = segment as? Category {
let title = cate.categoryTitle ?? ""
let desc = cate.categoryDesc != nil ? "\n" + cate.categoryDesc! : ""
let titleRange = NSRange(location: 0, length: title.count)
let descRange = NSRange(location: title.count, length: desc.count)
let attr = NSMutableAttributedString(string: title + desc)
attr.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: 18), range: titleRange)
attr.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: 10), range: descRange)
if selected {
attr.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: descRange)
} else {
attr.addAttribute(NSForegroundColorAttributeName, value: UIColor.blue, range: descRange)
}
return attr
}
return nil
}
-
segment width style
fixed
: Each segment has equal width, equal to the widest segment.dynamic
: Each segment has different width, depends on it's content.equal(width)
: Each segment has equal width, equal to the width param.
-
selection indicator
selectionIndicatorStyle
: style of the selection indicator, supporttextWidthStripe
,fullWidthStripe
,box
selectionIndicatorHeight
: Height of the selection indicatorselectionIndicatorEdgeInset
: Edge insets of the selection indicatorselectionIndicatorColor
: Color of the selection indicatorselectionIndicatorPosition
: Position of the selection indicator, supporttop
,bottom
,none
selectionBoxColor
: Color of selection box
-
font & color
titleTextAttributes
: Text attributes to apply to labels of the unselected segmentsselectedTitleTextAttributes
: Text attributes to apply to labels of the selected segments
-
vertical divider
enableVerticalDivider
: enable vertical divider between the segmentsverticalDividerColor
: Color of vertical dividerverticalDividerWidth
: Width of vertical dividerverticalDividerInset
: Inset top and bottom of vertical divider
-
image and text
imagePosition
: image position relative to textimageTitleSpace
: space between image and title
- support attributed title
- refactor segment data source, use
NLSegment
protocol as data source - remove
titles
,images
,selectedImages
properties - support custom data model
- update
selectedSegmentIndex
property to public