A segmented control with custom appearance and interactive animations. Written in Swift 3.0.

Overview

SJFluidSegmentedControl

Version Downloads License Platform Language

About

If you are bored with using the default UISegmentedControl, this might save your day. SJFluidSegmentedControl is a customizable segmented control with an interactive transition, written in Swift 3.0 and it is based on LUNSegmentedControl by LunApps which is written in Objective-C.

Sample

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

  • iOS 8.0+
  • Xcode 8.0+
  • Swift 3.0+

Note: SJFluidSegmentedControl is not intended to be used from Objective-C. For an Objective-C version of this library, please refer to the LUNSegmentedControl.

Features

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Apps using this library

If your app is using this library, I would love to add it to this README. Please reach out to me!

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

CocoaPods 1.1.0+ is required to build SJFluidSegmentedControl 1.0.0+.

To integrate SJFluidSegmentedControl into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'SJFluidSegmentedControl', '~> 1.0'
end

Then, run the following command:

$ pod install

Manual installation

SJFluidSegmentedControl can also be installed manually by simply dragging and dropping the files located in the Classes folder.

Usage

Using Interface Builder

  1. Drag & drop a UIView in the View.
    • By setting the background color of this view, you will also be setting the background color of the segmented control.
  2. Change its class to SJFluidSegmentedControl.
  3. Connect its data source.
  4. Implement the only required data source method that returns the number of segments in the segmented control:
func numberOfSegmentsInSegmentedControl(_ segmentedControl: SJFluidSegmentedControl) -> Int

Additionaly, you can set the cornerRadius, textColor, selectedSegmentTextColor, selectorViewColor, applyCornerRadiusToSelectorView, gradientBounceColor, shadowShowDuration, shadowHideDuration and shadowsEnabled properties by using the Attributes inspector.

Attributes

For customizing other of the available properties, create an @IBOutlet of the segmented control and access them via code.

Using Code

It's very similar to using Interface Builder, instead you just setup the custom view in code. There are several methods to do this, here's an example:

// Conform to the data source (optionally, you can conform to the delegate)
class ViewController: UIViewController, SJFluidSegmentedControlDataSource {

	// Define a lazy var
	lazy var segmentedControl: SJFluidSegmentedControl = {
	    [unowned self] in
	    // Setup the frame per your needs
	    let segmentedControl = SJFluidSegmentedControl(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
	    segmentedControl.dataSource = self
	    return segmentedControl
	}()

	// Add it as a subview in viewDidLoad()
	override func viewDidLoad() {
		super.viewDidLoad()
		view.addSubview(segmentedControl)
	}

	// Don't forget to implement the required data source method
	func numberOfSegmentsInSegmentedControl(_ segmentedControl: SJFluidSegmentedControl) -> Int {
		return 3
	}

}

Data Source Implementation

You must implement the required data source method that returns the number of segments:

func numberOfSegmentsInSegmentedControl(_ segmentedControl: SJFluidSegmentedControl) -> Int

Return the titles for the segments of the segmented control, and take advantage of the NSAttributedString features to customize the text appearance using the following data source methods:

@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     titleForSegmentAtIndex index: Int) -> String?
@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     attributedTitleForSegmentAtIndex index: Int) -> NSAttributedString?

If necessary, you can set the titles for the selected state of the segments with the help of the following data source methods:

@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     titleForSelectedSegmentAtIndex index: Int) -> String?
@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     attributedTitleForSelectedSegmentAtIndex index: Int) -> NSAttributedString?

You can also set the title color for the selected state of the segments using this data source method:

@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     titleColorForSelectedSegmentAtIndex index: Int) -> UIColor

In addition, you can set a color (or an array of colors to form a gradient) for each segment, as well as colors for the left and right bounces with the help of the following data source methods:

@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     gradientColorsForSelectedSegmentAtIndex index: Int) -> [UIColor]
@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     gradientColorsForBounce bounce: SJFluidSegmentedControlBounce) -> [UIColor]

If you need a more complex layout for each segment, you can return a custom view instead with these data source methods:

@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     viewForSegmentAtIndex index: Int) -> UIView
@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     viewForSelectedSegmentAtIndex index: Int) -> UIView

Delegate Implementation

The delegate methods provide callbacks for some of the most commonly needed events, such as:

@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     didChangeFromSegmentAtIndex fromIndex: Int,
                                     toSegmentAtIndex toIndex:Int)
@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     willChangeFromSegment fromSegment: Int)
@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     didScrollWithXOffset offset: CGFloat)

Additionaly, if you need to take control over the transitions between the segments, you can use the following delegate methods:

@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     setupSegmentAtIndex segmentIndex: Int,
                                     unselectedView unselectedSegmentView: UIView,
                                     selectedView selectedSegmentView: UIView,
                                     withSelectionPercent percent: CGFloat)
@objc optional func segmentedControl(_ segmentedControl: SJFluidSegmentedControl,
                                     resetSegmentAtIndex segmentIndex: Int,
                                     unselectedView unselectedSegmentView: UIView,
                                     selectedView selectedSegmentView: UIView)

Additional properties

Other customization options are available through the following publicly available properties:

// The index of the currently selected segment. It ranges from 0 to segmentsCount-1. Default is `0`.
open var currentSegment: Int

// The number of segments in the segmented control. Default is `1`.
fileprivate(set) public var segmentsCount: Int

// The transition style between the default and selected state of the segments. Default is `.fade`.
open var transitionStyle: SJFluidSegmentedControlTransitionStyle

// The style of the selecton shape. Default is `.liquid`.
open var shapeStyle: SJFluidSegmentedControlShapeStyle

// The corner radius of the segmented control. Default is `0.0`.
@IBInspectable open var cornerRadius: CGFloat

// The color of the text for the default state of a segment. Default is `.black`. This property will be overriden if the delegate for attributed titles/views is implemented.
@IBInspectable open var textColor: UIColor

// The color of the text for the selected state of a segment. Default is `.white`. This property will be overriden if the delegate for attributed titles for selected state or views for selected state is implemented.
@IBInspectable open var selectedSegmentTextColor: UIColor

// The text font for the titles of the segmented control in both states if the data source does not provide attributed titles or views. Default is `.systemFont(ofSize: 14)`.
open var textFont: UIFont

// The color of the selector. Default is `.clear`. **Note:** If set, it is overlayed over the gradient colors.
@IBInspectable open var selectorViewColor: UIColor

// A boolean value to determine whether the selector should have rounded corners. Default is `false`.
@IBInspectable open var applyCornerRadiusToSelectorView: Bool

// The color for the bounce if the data source does not provide colors for bounces. Default is `.red`.
@IBInspectable open var gradientBounceColor: UIColor

// The duration of the show shadow animation. Default is `0.5`.
@IBInspectable open var shadowShowDuration: CGFloat

// The duration of the hide shadow animation. Default is `0.8`.
@IBInspectable open var shadowHideDuration: CGFloat

// A boolean value to determine whether shadows should be applied. Default is `true`.
@IBInspectable open var shadowsEnabled: Bool

Reload data

If you need to reload the data of the segmented control, simply call:

segmentedControl.reloadData()

Author

This library has been adapted for Swift 3.0+ by Sasho Jadrovski, http://jadrovski.com. The original creators are LunApps, as stated above.

License

SJFluidSegmentedControl is available under the MIT license. See the LICENSE file for more info.

Comments
  • Programmatically change segment index

    Programmatically change segment index

    Hi, thanks for great lib :) I have a few questions. Is it possible to change the selected segment programmatically, and if yes, how can I do that?

    And my second question is: is it possible not to have any index selected at all? Say, set the index to -1?

    Thanks

    feature request 
    opened by khoren93 2
  • Make datasource and delegate to be of the correct type.

    Make datasource and delegate to be of the correct type.

    Currently, both the datasource property and the delegate property are of type AnyObject?. Why not change them to be of type SJFluidSegmentedControlDatasource? and SJFluidSegmentedControlDelegate? respectively? This way errors can be detected at compile time.

    opened by Sweeper777 1
  • Setting current segment index in viewDidLoad

    Setting current segment index in viewDidLoad

    Hi, I have tried setting the current segment index to some other value than 0 in viewDidLoad but the segment just remains at the first position. Same in viewWillAppear.

    If I call the following line inside viewDidAppear, the segment switches to the correct position segmentedControl.setCurrentSegmentIndex(startingSegment, animated: false) If, however I make the above call in viewDidLoad or viewWillAppear or the following call anywhere, the segments just don't change

    tabBarControl.currentSegment = startingSegment

    My question is, how can I make a segment change be effective from viewDidLoad or viewWillAppear, so that there will be no visible transitioning of segment positions?

    opened by Billydubb 1
  • (Bug) Third label displayed always in white at first launch.

    (Bug) Third label displayed always in white at first launch.

    First of all, thank you fort his incredible library. There's a very small bug which displays the third (the first and the second work fine) label (in your example it's the word "IT") always in white, at the first launch. After switching the tabs, it displays correctly in the color set in the Inspector View.

    Hope to see the bug solved soon! Again, thank you so much!

    opened by MehdiBrandoMahdloo 3
  • Delegate function not being updated if swiped/scrolled to quickly.

    Delegate function not being updated if swiped/scrolled to quickly.

    Hello and thanks for the great work you've done on the project. I'm facing an issue where the delegate method is not being called when the selected index is changed via a swipe. I'm monitoring via the following delegate method segmentedControl(_ segmentedControl: SJFluidSegmentedControl, didChangeFromSegmentAtIndex fromIndex: Int, toSegmentAtIndex toIndex:Int) and it appears that if the user scrolls quickly to a new segment index this is not called as the toIndex is not updated.

    Is there another delegate function I should be monitoring for this or is it unexpected behavior? I really like the project here and will be using it in my app if I can resolve this.

    Thanks for taking the time to read/respond.

    opened by xbsjason 0
Owner
Sasho Jadrovski
Sasho Jadrovski
A customizable Segmented Control for iOS. Supports text and image.

YUSegment 中文文档 A customizable segmented control for iOS. Features Supports both (Attributed)text and image Supports show separator Supports hide indic

YyGgQq 112 Jun 10, 2022
AKASegmentedControl is a fully customizable Segmented Control for iOS

#AKASegmentedControl AKASegmentedControl is a fully customizable Segmented Control for iOS ##Preview ##Usage Installation CocoaPods You can use CocoaP

Ali Karagoz 389 Sep 1, 2022
Custom UISegmentedControl replacement for iOS, written in Swift

TwicketSegmentedControl Custom UISegmentedControl replacement for iOS, written in Swift, used in the Twicket app. It handles the inertia of the moveme

Pol Quintana 1.7k Dec 31, 2022
A Pinterest-like segment control with masking animation.

PinterestSegment A Pinterest-like segment control with masking animation. Requirements iOS 8.0+ Xcode 9.0 Swift 4.0 Installation CocoaPods You can use

TBXark 672 Dec 20, 2022
Runkeeper design switch control

DGRunkeeperSwitch Runkeeper design switch control (two part segment control) developed in Swift 2.0 Requirements Xcode 7-beta or higher iOS 8.0 or hig

Danil Gontovnik 1.9k Dec 2, 2022
UISegmentedControl remake that supports selecting multiple segments, vertical stacking, combining text and images.

MultiSelectSegmentedControl UISegmentedControl remake that supports selecting multiple segments, vertical stacking, combining text and images. Feature

Yonat Sharon 286 Dec 15, 2022
Customizable segmented control with interactive animation.

LUNSegmentedControl Purpose LUNSegmentedControl is control designed to let developers use segmented control with custom appearance, customizable inter

Stormotion 346 Dec 25, 2021
Animated top/bottom segmented control written in Swift.

Segmentio Animated top/bottom segmented control written in Swift. Check this project on dribbble. Requirements Xcode 10 iOS 8.x+ Swift 5.0 Installatio

Yalantis 2.4k Jan 9, 2023
Menu controller with expandable item groups, custom position and appearance animation written with Swift. Similar to ActionSheet style of UIAlertController.

Easy to implement controller with expanding menu items. Design is very similar to iOS native ActionSheet presentation style of a UIAlertController. As

Anatoliy Voropay 22 Dec 27, 2022
RCalendarPicker A date picker control, Calendar calendar control, select control, calendar, date selection, the clock selection control.

RCalendarPicker RCalendarPicker Calendar calendar control, select control, calendar, date selection, the clock selection control. 日历控件 ,日历选择控件,日历,日期选择

杜耀辉 131 Jul 18, 2022
A customizable Segmented Control for iOS. Supports text and image.

YUSegment 中文文档 A customizable segmented control for iOS. Features Supports both (Attributed)text and image Supports show separator Supports hide indic

YyGgQq 112 Jun 10, 2022
AKASegmentedControl is a fully customizable Segmented Control for iOS

#AKASegmentedControl AKASegmentedControl is a fully customizable Segmented Control for iOS ##Preview ##Usage Installation CocoaPods You can use CocoaP

Ali Karagoz 389 Sep 1, 2022
A Swift library to take the power of UIView.animateWithDuration(_:, animations:...) to a whole new level - layers, springs, chain-able animations and mixing view and layer animations together!

ver 2.0 NB! Breaking changes in 2.0 - due to a lot of requests EasyAnimation does NOT automatically install itself when imported. You need to enable i

Marin Todorov 3k Dec 27, 2022
Custom segmented picker for SwiftUI

Custom segmented picker for SwiftUI

Sergey Kazakov 34 Dec 27, 2022
Easy to create & custom segmented view

TCSegmentedView Easy to create & custom segmented view Usage Examples An Objective-C example project demonstrating customization options is included i

Chuong Tran 22 Dec 4, 2022
🌊 - Jelly is a library for animated, non-interactive & interactive viewcontroller transitions and presentations with the focus on a simple and yet flexible API.

Jelly is a library for animated, non-interactive & interactive viewcontroller transitions and presentations with the focus on a simple and yet flexibl

Sebastian Boldt 2.4k Dec 25, 2022
🌊 - Jelly is a library for animated, non-interactive & interactive viewcontroller transitions and presentations with the focus on a simple and yet flexible API.

Jelly is a library for animated, non-interactive & interactive viewcontroller transitions and presentations with the focus on a simple and yet flexibl

Sebastian Boldt 2.4k Dec 25, 2022
VKPinCodeView is simple and elegant UI component for input PIN. You can easily customise appearance and get auto fill (OTP) iOS 12 feature right from the box.

Features Variable PIN length Underline, border and custom styles The error status with / without shake animation Resetting the error status manually,

Vladimir Kokhanevich 95 Nov 24, 2022
Mimicrated views and controls to native Apple appearance.

Mimicrated views and controls to native Apple appearance. If you have any ideas of what elements can be added, let me know. Below you will see previews of all the elements and how to use them.

Ivan Vorobei 85 Dec 3, 2022