Skyscanner / SkyFloatingLabelTextField
- суббота, 9 апреля 2016 г. в 03:12:54
Swift
A beautiful and flexible text field control implementation of "Float Label Pattern". Written in Swift. As used in the Skyscanner TravelPro iOS app.
SkyFloatingLabelTextField
is a beautiful, flexible and customizable implementation of the space saving "Float Label Pattern". This design enables adding context to input fields that is visible at time of typing, while minimizing the additional space used to display this additional context. This component is used in the Skyscanner TravelPro iOS application in several places.
On top of implementing the space-saving floating title, the component also supports using iconography, various states (error, selected, highlighted states), and is very much customizable and extensible.
To start using the component add it to your project using CocoaPods, Carthage or manually as per the Installation section.
The UI component can be used via the SkyFloatingLabelTextField
class. To use icons on the right hand side, use the SkyFloatingLabelTextFieldWithIcon
class. This control can be used very similar to UITextField
- both from Interface Builder, or from code.
To create an instance of the class, use Interface builder, or do it from code. This example will create the following textbox with the placeholder and title:
let textField = SkyFloatingLabelTextField(frame: CGRectMake(10, 10, 200, 45))
textField.placeholder = "Name"
textField.title = "Your full name"
self.view.addSubview(textField)
To customize the colors of the textfield, set a few properties - either from code, or from Interface builder. To use a textfield with an icon, utilize the SkyFloatingLabelTextFieldWithIcon
class (and bundle the font class with your app). This example will change colors for the textfield on teh right:
let lightGreyColor = UIColor(red: 197/255, green: 205/255, blue: 205/255, alpha: 1.0)
let darkGreyColor = UIColor(red: 52/255, green: 42/255, blue: 61/255, alpha: 1.0)
let overcastBlueColor = UIColor(red: 0, green: 187/255, blue: 204/255, alpha: 1.0)
let textField1 = SkyFloatingLabelTextField(frame: CGRectMake(10, 10, 120, 45))
textField1.placeholder = "First name"
textField1.title = "Given name"
self.view.addSubview(textField1)
let textField2 = SkyFloatingLabelTextField(frame: CGRectMake(150, 10, 120, 45))
textField2.placeholder = "Last name"
textField2.title = "Family name"
textField2.tintColor = overcastBlueColor // the color of the blinking cursor
textField2.textColor = darkGreyColor
textField2.lineColor = lightGreyColor
textField2.selectedTitleColor = overcastBlueColor
textField2.selectedLineColor = overcastBlueColor
textField2.lineHeight = 1.0 // bottom line height in points
textField2.selectedLineHeight = 2.0
Use the SkyFloatingLabelTextFieldWithIcon
field to display icons next to the textfields. You will have to set the iconFont
property and bundle your icon with your app (if its not a built in one). Icons can be rotated and more precise positioning is also supported:
let overcastBlueColor = UIColor(red: 0, green: 187/255, blue: 204/255, alpha: 1.0)
let textField1 = SkyFloatingLabelTextFieldWithIcon(frame: CGRectMake(10, 10, 120, 45))
textField1.placeholder = "Departure"
textField1.title = "Flying from"
textField1.iconFont = UIFont(name: "FontAwesome", size: 15)
textField1.iconText = "\u{f072}" // plane icon as per https://fortawesome.github.io/Font-Awesome/cheatsheet/
self.view.addSubview(textField1)
let textField2 = SkyFloatingLabelTextFieldWithIcon(frame: CGRectMake(150, 10, 120, 45))
textField2.placeholder = "Arrival"
textField2.title = "Flying to"
textField2.tintColor = overcastBlueColor
textField2.selectedTitleColor = overcastBlueColor
textField2.selectedLineColor = overcastBlueColor
// Set icon properties
textField2.iconColor = UIColor.lightGrayColor()
textField2.selectedIconColor = overcastBlueColor
textField2.iconFont = UIFont(name: "FontAwesome", size: 15)
textField2.iconText = "\u{f072}" // plane icon as per https://fortawesome.github.io/Font-Awesome/cheatsheet/
textField2.iconMarginBottom = 4.0 // more precise icon positioning. Usually needed to tweak on a per font basis.
textField2.iconRotationDegrees = 90 // rotate it 90 degrees
textField2.iconMarginLeft = 2.0
self.view.addSubview(textField2)
The textfield supports displaying an error state - this can be useful for example when validating fields on the fly. When the errorMessage
property is set on the control, then the control is highlighted with the color set in the errorColor
property.
To get notified of different events happening on the textfield - such as the text changing, editing starting or ending - just set the delegate
property to a class implementing the standard UITextFieldDelegate protocol:
class MyViewController: UIViewController, UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let textField1 = SkyFloatingLabelTextField(frame: CGRectMake(10, 10, 120, 45))
textField1.placeholder = "Email"
textField1.title = "Email address"
textField1.errorColor = UIColor.redColor()
textField1.delegate = self
self.view.addSubview(textField1)
}
/// Implementing a method on the UITextFieldDelegate protocol. This will notify us when something has changed on the textfield
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text {
// Note: every time when the text of the textfield changes, the error message is reset (hence we don't need to reset it)
if(text.characters.count < 3 || !text.containsString("@")) {
if let floatingLabelTextField = textField as? SkyFloatingLabelTextField {
floatingLabelTextField.errorMessage = "Invaid email"
}
}
}
return true
}
}
The control was designed to allow further customization in subclasses. The control itself inherits from UITextField
, so the standard overrides from there can all be used. A few other notable customization hooks via overriding are:
updateColors
: override this method to customzie colors whenever the state of the control changestitleLabelRectForBounds(bounds:CGRect, editing:Bool)
: override to change the bounds of the top title placeholder viewtextRectForBounds(bounds: CGRect)
: override to change the bounds of the control (inherited from UITextField
)editingRectForBounds(bounds: CGRect)
: override to change the bounds of the control when editing / selected (inherited from UITextField
)placeholderRectForBounds(bounds: CGRect)
: override to change the bounds of the placeholder view lineViewRectForBounds(bounds:CGRect, editing:Bool)
: override to change the bounds of the bottom line viewSee the SkyFloatingLabelTextField documentation on CocoaDocs.org for the full documentation.
The control is available through CocoaPods. CocoaPods can be installed using Ruby gems:
$ gem install cocoapods
Then simply add SkyFloatingLabelTextField
to your Podfile:
pod 'SkyFloatingLabelTextField', '~> 1.0'
Lastly let CocoaPods fetch the latest version of the component by running:
$ cocoapods update
When integrating the component in Objective C project, in the Podfile add use_frameworks!
. For example as shown in SkyFloatingLabelTextFieldObjectiveCExample:
use_frameworks!
target 'SkyFloatingLabelTextFieldObjectiveCExample' do
pod 'SkyFloatingLabelTextField', '~> 1.0'
end
Then to use the component in your code, add the following line to your .h
or .m
files:
@import SkyFloatingLabelTextField;
The component supports Carthage. Start by making sure you have the latest version of Carthage installed. Using Homebrew run this:
$ brew update
$ brew install carthage
Then add SkyFloatingLabelTextField
to your Cartfile
:
github "Skyscanner/SkyFloatingLabelTextField"
Finally, add the framework to the Xcode project of your App. Link the framework to your App and copy it to the App’s Frameworks directory via the “Build Phases” section.
You can download the latest files from our Releases page. After doing so, copy the files in the Sources
folder to your project.
We welcome all contributions. Please read this guide before opening issues or submitting pull requests, as well as how and who to contact with questions.
The original component was built by Daniel Langh, Gergely Orosz and Raimon Laupente.
Credits for the original design, and improving it with iconography to Matt D. Smith (@mds).
Can I use it in Objective C projects?
Of course! Please see the Integrating-into-Objective-C-projects section on how to integrate the component via CocoaPods.
Does the control work well with auto layout? What about using it programmatically?
The control was built to support both use cases. It plays nicely with autolayout. As the control is a subclass of UITextField
, overriding textRectForBounds(bounds:)
or editingRectForBounds(bounds:)
is always an option. Alternatively, overriding intrinsiccontentsize
is also another possiblity.
How can I remove the line from the bottom of the textfield?
Set lineHeight
and selectedLineHeight
to 0
, and the line won't be displayed.