對于涉及到資金的app,類似支付寶支付密碼(一般為6位數字)的輸入框似乎已成為標配?
所以可以封裝一個自定義控件來用(主要還是想練練手??),效果如下:
效果圖
1.思路分析
要實現這個效果,有幾種思路:
1.先定義單個單元的自定義控件,然后根據個數創建排列。
2.使用CGContextRef直接繪制出邊框與黑點。
2.需要用到的姿勢
經過考慮,決定選用第二種方案,所需技能:
1.繪制:CGContextRef和UIBezierPath
2.實時預覽(可選,加上這個可以在xib中實時預覽):IB_DESIGNABLE
3.分析可變屬性
1.用一個String保存輸入的字符串
2.邊框顏色、寬度、圓角弧度以及間距
3.圓點大小、顏色
綜上,.h文件中公開的屬性如下
@property (nonatomic,copy) IBInspectable NSString * text; //內容
@property (nonatomic,assign) IBInspectable CGFloat dotRadius; //圓點的半徑大小
@property (nonatomic,copy) IBInspectable UIColor * dotColor; //圓點的顏色
@property (nonatomic,assign) IBInspectable NSInteger boxCount; //可以輸入幾位數
@property (nonatomic,assign) IBInspectable CGFloat boxMargin; //輸入框的間距
@property (nonatomic,assign) IBInspectable CGFloat boxRadius; //輸入框的圓角半徑
@property (nonatomic,assign) IBInspectable CGFloat borderWidth; //輸入框邊框寬度
@property (nonatomic,copy) IBInspectable UIColor * borderColor; //輸入框邊框顏色
4.實現
1、計算每個方框的位置
/**
* 計算方框的坐標
* i 第幾個方框
* rect
**/
-(CGRect)getBoxRect:(int)i
size:(CGSize)size{
//考慮到最后一個box需要頂到右側,所以需要加上一個_boxMargin
float boxWidth = (size.width + _boxMargin)/self.boxCount - _boxMargin;
float boxHeight = size.height;
float left = (self.boxMargin + boxWidth) * i;
float top = 0;
return CGRectMake(left, top , boxWidth , boxHeight);
}
2、使用CGContextRef繪制方框
/**
* 繪制方框
* context 上下文
* rect
**/
-(void)drawBorder:(CGContextRef)context
size:(CGSize)size{
//設置線的顏色
CGContextSetStrokeColorWithColor(context, self.borderColor.CGColor);
//設置線的寬度
CGContextSetLineWidth(context, self.borderWidth);
//調整位置,因為邊框如果超出rect會被截取
CGRect bounds = CGRectInset(rect, _borderWidth * 0.5, _borderWidth * 0.5);
for (int i = 0 ; i < self.boxCount; i ++) {
CGRect rect = [self getBoxRect:i size:bounds.size];
CGRect boxRect = CGRectInset(rect, _borderWidth * 0.5, _borderWidth * 0.5);
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:boxRect cornerRadius:_boxRadius];
CGContextAddPath(context, bezierPath.CGPath);
}
//繪制
CGContextDrawPath(context, kCGPathStroke);
}
3、繪制圓點
/**
* 繪制圓點
* context 上下文
* size 總大小(self的size)
**/
-(void)drawDot:(CGContextRef)context
rect:(CGRect)rect{
//調整位置,因為邊框如果超出rect會被截取
CGRect bounds = CGRectInset(rect, _borderWidth * 0.5, _borderWidth * 0.5);
for (int i = 0; i < self.boxCount; i ++) {
//設置填充顏色
CGContextSetFillColorWithColor(context, [self.dotColor colorWithAlphaComponent:[self.dotAlphas[i] floatValue]].CGColor);
CGRect rect = [self getBoxRect:i size:bounds.size];
//圓心的y坐標
float cy = CGRectGetMidY(rect);
//圓心的x坐標
float cx = CGRectGetMidX(rect);
//半徑
float half = self.dotRadius * [self.dotScans[i] floatValue];
//添加一個圓
CGContextAddArc(context, cx, cy,half, 0, 2 * M_PI, 0);
//繪制填充
CGContextDrawPath(context, kCGPathFill);
}
}
4、然后在drawRect:中繪制
-(void)drawRect:(CGRect)rect{
CGContextRef context = UIGraphicsGetCurrentContext();
CGSize size = self.frame.size;
[self drawBorder:context size:size];
[self drawDot:context size:size];
}
5、試試效果
到這里,基本上的效果已經可以看到了。
由于之前加了IB_DESIGNABLE,所以我們可以在xib中直接預覽和修改參數:
預覽
6、改變文字
經過前面幾個步驟,視圖效果出來了,但是圓點始終是充滿所有方框的,現在我們需要根據text的改變,改變圓點的顯示個數(只需要改變一下drawDot:size:中的判斷條件就可以了):
-(void)drawDot:(CGContextRef)context
size:(CGSize)size{
//圓心的y坐標
float cy = size.height / 2;
//半徑
float half = size.width / self.boxCount / 2;
for (int i = 0; i < MIN(self.text.length, self.boxCount); i ++) {
//設置填充顏色
CGContextSetFillColorWithColor(context, self.dotColor.CGColor);
//圓心的x坐標
float cx = size.width * i / self.boxCount + half;
//添加一個圓
CGContextAddArc(context, cx, cy, self.dotRadius, 0, 2 * M_PI, 0);
//繪制填充
CGContextDrawPath(context, kCGPathFill);
}
}
看看效果:
預覽1
以上,密碼框的基礎功能已經實現,這篇文章也告一段落。
下一篇文章,要做的是給圓點加上出現和消失的動畫。