Material Design refers to a set of design principles used in most applications developed by Google, most notably the Android operating system. There exist Objective-C and Swift libraries of UIControls which allow us to easily develop iOS applications in such a style.
The most popular and fully-fleshed is Material, with roughly 6,000 stars on Github.
However, Material is written in Swift, and is yet to release a Swift 3 version. This should happen in less than a week, but in the meantime, there's another great package written in Objective-C: Material Controls For iOS, which has roughly 2,000 stars on Github. I've had good experiences using this package, and it's nice to worry about the Swift version.
Installing Material-Controls-For-iOS
I'll show you how to install this package with cocoapods (a dependency manager for XCode), and how to set up a simple text field.
If you don't have cocoapods installed already, you can get it with:
$ sudo gem install cocoapods
Now set up a new single-view Swift iOS XCode project, and create a file in the root directory called Podfile
. This will have the following contents:
# Podfile
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
platform :ios, '10.0'
target 'materialExample' do
pod 'MaterialControls', '~> 1.1.0'
end
Now simply run pod install
from the root of your project directory.
This has the effect of creating a new file: materialExample.xcworkspace
. Close any .xcproject
files you have open, and use the new .xcworkspace
file from now on. Open it up, and we're ready to start using our controls
Getting A Material Text Field
In the sole view controller in main.storyboard
, create a UIView constrained on the left, right, and top, and with a height of 80.
Now simply give this a class of MDTextField:
Now if you try to build and run as of the version I'm currently using, you'll actually get an error in the source code:
This has been an open but solved issue for a while now. The fix is to replace this method with the following code:
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
if (anim == [self animationForKey:@"opacityAnim"]) {
self.opacity = 0;
} else if (flag) {
if (_userIsHolding) {
_effectIsRunning = false;
if ([self.delegate conformsToProtocol:@protocol(MDLayerDelegate)] &&
[self.delegate respondsToSelector:@selector(mdLayer:didFinishEffect:)]) {
id delegate = (id)self.delegate;
[delegate mdLayer:self didFinishEffect:anim.duration];
}
} else {
[self clearEffects];
}
}
}
Now the application will build and run, and your interface builder should look a little more interesting. You can design the text field in the interface builder with IBDesignables:
Very cool. Let's add an outlet to our ViewController now, and set it as a delegate. I'll add a couple of delegate methods too; one called when we start editing, and one whenever we change a character. I'm going to use this second delegate method to prevent users from entering 'z', as an example.
//
// ViewController.swift
// materialExample
//
import UIKit
import MaterialControls
class ViewController: UIViewController, MDTextFieldDelegate {
@IBOutlet weak var textField: MDTextField!
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
}
func textFieldDidBeginEditing(_ textField: MDTextField) {
print("Began editing!")
}
func textField(_ textField: MDTextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
print(textField.text, string, range.location)
if (string == "z") {
return false
}
return true
}
}
You now have a pretty Material text field with some very convenient delegate methods.
Any questions: ask below with Disqus.