快速简单的实现密码框UI,并自定义UI
方案
网上大致搜索了一下,绘制密码框大概有两种方案:
1、使用UITextView, 每个数字对应一个view。
2、 使用UIKeyInput, 利用coretext绘制文本。
本文使用第二种方案。
实现
一、关于UIKeyInput
@protocol UIKeyInput <UITextInputTraits>
@property(nonatomic, readonly) BOOL hasText;
- (BOOL)hasText;
- (void)insertText:(NSString *)text;
- (void)deleteBackward;
- @end
二、遵循UIKeyInput协议 并且实现协议里面的方法。
1、当监听到键盘输入时,系统回调 insertText:方法。则可以获取到输入的文本信息。同理,当删除某文本时,系统回调 deleteBackward。
三、绘制文本,密码框其实有数字 和 下划线组成
1、使用CGContextRef 绘制下划线,如:
guard let ctx = UIGraphicsGetCurrentContext() else {return}
ctx.setLineWidth(1)
//开始画底部的线
Array(1...maxLength).forEach { (index) in
ctx.move(to: CGPoint(x: 0, y: 0))
ctx.addLine(to: CGPoint(x: 20, y: 20))
ctx.strokePath()
}
2、使用coretext 绘制文本,如:
text.forEach { (t) in
let str = isEncrypt ? "*" : String(t)
let attriStr = NSAttributedString(string: str, attributes:
[NSAttributedStringKey.font: textFont,
NSAttributedStringKey.foregroundColor: textColor])
let frameSetter =
CTFramesetterCreateWithAttributedString(attriStr)
var frameSize = CTFramesetterSuggestFrameSizeWithConstraints(frameSetter, CFRangeMake(0, 1), nil, CGSize(width: width, height: rect.height), nil)
frameSize.width = ceil(frameSize.width)
frameSize.height = ceil(frameSize.height)
let offsetX = (width + space) * CGFloat(index - 1)
let path = UIBezierPath(rect: CGRect(x: offsetX + (width - frameSize.width)/2, y: (rect.height - frameSize.height)/2, width: frameSize.width, height: frameSize.height)).cgPath
let frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 1), path, nil)
CTFrameDraw(frame, ctx)
index = index + 1
}
}