Skip to content

Commit

Permalink
0.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Jvaeyhcd committed May 9, 2017
1 parent 7d78031 commit 2516de3
Show file tree
Hide file tree
Showing 4 changed files with 290 additions and 9 deletions.
Binary file not shown.
19 changes: 10 additions & 9 deletions HcdSpecialField.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@ Pod::Spec.new do |s|

s.name = "HcdSpecialField"
s.version = "0.0.1"
s.summary = "A short description of HcdSpecialField."
s.summary = "HcdSpecialField is a special textField."

# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = <<-DESC
仿微信、支付宝支付时输入密码框,摩拜单车输入编号框。
DESC

s.homepage = "http://EXAMPLE/HcdSpecialField"
s.homepage = "https://github.com/Jvaeyhcd/HcdSpecialField"
# s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"


Expand All @@ -38,8 +39,8 @@ Pod::Spec.new do |s|
# Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
#

s.license = "MIT (example)"
# s.license = { :type => "MIT", :file => "FILE_LICENSE" }
# s.license = "MIT (example)"
s.license = { :type => "MIT", :file => "LICENSE" }


# ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
Expand Down Expand Up @@ -78,9 +79,8 @@ Pod::Spec.new do |s|
# Specify the location from where the source should be retrieved.
# Supports git, hg, bzr, svn and HTTP.
#

s.source = { :git => "http://EXAMPLE/HcdSpecialField.git", :tag => "#{s.version}" }

s.source = { :git => "https://github.com/Jvaeyhcd/HcdSpecialField.git", :tag => "#{s.version}" }
s.resource_bundle = { 'HcdSpecialField' => 'HcdSpecialField/Resources/*' }

# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
Expand All @@ -90,8 +90,9 @@ Pod::Spec.new do |s|
# Not including the public_header_files will make all headers public.
#

s.source_files = "Classes", "Classes/**/*.{h,m}"
s.exclude_files = "Classes/Exclude"
s.ios.deployment_target = '8.0'
s.source_files = "HcdSpecialField/**/*.swift"
# s.exclude_files = "Classes/Exclude"

# s.public_header_files = "Classes/**/*.h"

Expand Down
261 changes: 261 additions & 0 deletions HcdSpecialField/HcdSpecialField.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
//
// HcdSpecialField.swift
// Pods
//
// Created by Eddie Hiu-Fung Lau on 19/12/2016.
//
//

import UIKit

@IBDesignable
public class HcdSpecialField: UIControl, UIKeyInput {

// MARK: - Public variables
@IBInspectable public var numberOfDigits: Int = 6 {
didSet {

if oldValue != numberOfDigits {

if passcode.characters.count > numberOfDigits {
let endOfString = passcode.index(passcode.startIndex, offsetBy: numberOfDigits)
passcode = passcode.substring(to: endOfString)
}

relayout()
redisplay()
}

}
}

@IBInspectable public var passcode: String = "" {
didSet {

if oldValue != passcode {

guard passcode.characters.count <= numberOfDigits else {
return
}

guard isNumeric(passcode) else {
return
}

redisplay()
sendActions(for: .valueChanged)

}
}
}

@IBInspectable public var spaceBetweenDigits: CGFloat = 10.0 {

didSet {

if oldValue != spaceBetweenDigits {

relayout()
redisplay()

}
}

}

@IBInspectable public var dashColor: UIColor = UIColor.gray {
didSet {

if oldValue != dashColor {
redisplay()
}

}
}

@IBInspectable public var textColor: UIColor = UIColor.black {
didSet {
if oldValue != textColor {
redisplay()
}
}
}

@IBInspectable public var dashBackColor: UIColor = UIColor.green {
didSet {
if oldValue != dashBackColor {
redisplay()
}
}
}

@IBInspectable public var backColor: UIColor = UIColor.yellow {
didSet {
if oldValue != backColor {
redisplay()
}
}
}

// MARK: - Private variables
private var numberLabels: [UILabel] = []
private let emptyDigit = ""
private var isSecure = false {
didSet {
if isSecure != oldValue {
redisplay()
}
}
}


// MARK: - UIView
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}

required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}

override public func layoutSubviews() {

for index in 0..<numberLabels.count {
let label = numberLabels[index]
let frame = frameOfNumberLabel(ofDigitIndex: index)
label.font = UIFont.systemFont(ofSize: frame.size.width * 0.9)
label.frame = frame
}

}


// MARK: - Private methods
private func setup() {

addTarget(self, action: #selector(HcdSpecialField.didTouchUpInside), for: .touchUpInside)
relayout()

}

private func relayout() {
numberLabels.forEach { label in
label.removeFromSuperview()
}
numberLabels = []

for _ in 0..<numberOfDigits {
let numberLabel = UILabel()
numberLabel.text = emptyDigit
numberLabel.textColor = dashColor
numberLabel.textAlignment = .center
numberLabels.append(numberLabel)
addSubview(numberLabel)
}

setNeedsLayout()

}


private func frameOfNumberLabel(ofDigitIndex index:Int) -> CGRect {

let w = (bounds.size.width - spaceBetweenDigits * (CGFloat(numberOfDigits) - 1.0)) / CGFloat(numberOfDigits)
let h = bounds.size.height
let x = (w + spaceBetweenDigits) * CGFloat(index)
let y = CGFloat(0)
return CGRect(x:x, y:y, width:w, height:h)

}

private func redisplay() {

for i in 0..<numberOfDigits {

let label = numberLabels[i]

if i < passcode.characters.count {

let start = passcode.index(passcode.startIndex, offsetBy: i)
let end = passcode.index(start, offsetBy: 1)
let number = passcode.substring(with:start..<end)
label.text = isSecureTextEntry ? "" : number
label.textColor = textColor
label.backgroundColor = backColor

} else {

label.text = emptyDigit
label.textColor = dashColor
label.backgroundColor = dashBackColor
}
}

}

private func isNumeric(_ string:String) -> Bool {

guard let regex = try? NSRegularExpression(pattern: "^[0-9]*$", options: []) else {
return false
}

return regex.numberOfMatches(in: string, options: [], range: NSMakeRange(0, string.characters.count)) == 1
}

// MARK: - Handle the touch up event
@objc private func didTouchUpInside() {
becomeFirstResponder()
}

// MARK: UIKeyInput protocol
public var hasText: Bool {
return !passcode.isEmpty
}

public func insertText(_ text: String) {

guard passcode.characters.count + text.characters.count <= numberOfDigits else {
return
}

guard isNumeric(text) else {
return
}

passcode = passcode + text
}

public func deleteBackward() {
guard passcode.characters.count > 0 else {
return
}
passcode = passcode.substring(to: passcode.index(before: passcode.endIndex))
}

public var isSecureTextEntry: Bool {
@objc(isSecureTextEntry) get {
return isSecure
}
@objc(setSecureTextEntry:) set {
isSecure = newValue
}
}

// MARK: UIResponder
public override var canBecomeFirstResponder: Bool {
return true
}

// MARK: UIKeyboardTrait

public var keyboardType: UIKeyboardType {
set {}
get {
return .numberPad
}
}


}
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
copyright (c) 2016 HcdSpecialField (https://github.com/Jvaeyhcd/HcdSpecialField)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

0 comments on commit 2516de3

Please sign in to comment.