問題:項(xiàng)目需要自定義一個(gè)九宮格圖案鎖
解決問題:首先我們自定義一個(gè)LockView繼承UIView
我們要做的就是在這個(gè)LockView中去鋪設(shè)我們的9宮格圖案
LockView.m中
// tag基數(shù)
#define BaseTag 10000
@interface LockView () {
NSMutableArray* _circleArray;//鋪設(shè)的button
NSMutableArray* _selectedCircleArray;//已選擇的button
CGPoint nowPoint;//當(dāng)前觸摸位置
BOOL isWrongColor;// 標(biāo)記是否正在顯示錯(cuò)誤的繪圖
BOOL isDrawing; // 標(biāo)記是否正在繪圖中
UIColor *tempLineColor; //臨時(shí)的連接線的顏色
UIColor *wrongColor;//檔圖案錯(cuò)誤的時(shí)候顯示的顏色
UIColor *themeColor;//button未選擇時(shí)顯示的顏色
UIColor *lineColor;//連接線的顏色
UIColor *selectedPointColor;//button選中后顏色
CGFloat margin;//距離屏幕左右的距離
CGFloat buttonRaius;//button半徑
CGFloat lineWidth;//連接線的寬度
CGFloat buttonBorderWidth;//button的連接線寬度
}
@end
@implementation LockView
// 自定義初始化方法
- (instancetype)initLockViewWith:(CGRect)frame forWrongColor:(UIColor *)wrongColor themeColor:(UIColor *)themeColor lineColor:(UIColor *)lineColor selectedPointColor:(UIColor *)selectedPointColor margin:(CGFloat)margin buttonRadius:(CGFloat)buttonRaius lineWidth:(CGFloat)lineWidth buttonBorderWidth:(CGFloat)buttonBorderWidth{
self = [super initWithFrame:frame];
if (self) {
self->wrongColor = wrongColor;
self->themeColor = themeColor;
self->lineColor = lineColor;
self->selectedPointColor = selectedPointColor;
self->margin = margin;
self->buttonRaius = buttonRaius;
self->lineWidth = lineWidth;
self->buttonBorderWidth = buttonBorderWidth;
tempLineColor = lineColor;
[self initCircles];
}
return self;
}
//初始化9宮格圖案
- (void)initCircles {
self.clipsToBounds = YES;
_circleArray = [NSMutableArray array];
_selectedCircleArray = [NSMutableArray array];
for (int i = 0; i < 9; i++) {
//之所以用button 是因?yàn)?button有selected這個(gè)屬性 用起來比較方便
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, buttonRaius*2, buttonRaius*2);
button.userInteractionEnabled = NO;//禁止用戶交互(只做展示不做交互)
CGFloat pointWidth = (self.frame.size.width-margin*2-buttonRaius*2)/2;
button.center = CGPointMake(self.center.x + ((i%3)-1)*pointWidth, self.center.y+((i/3)-1)*pointWidth);
[button setBackgroundImage:[self getCircularSize:button.frame.size borderWith:buttonBorderWidth color:themeColor insideColor:lineColor solid:NO] forState:UIControlStateNormal];
[button setBackgroundImage:[self getCircularSize:button.frame.size borderWith:buttonBorderWidth color:themeColor insideColor:lineColor solid:YES] forState:UIControlStateSelected];
button.tag = i + BaseTag + 1; // tag從基數(shù)+1開始,
[self addSubview:button];
[_circleArray addObject:button];
}
self.backgroundColor = [UIColor clearColor];
}
//觸摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
isDrawing = NO;
if (isWrongColor) {
[self clearColorAndSelectedButton];
}
[self updatePositionWithTouches:touches];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
isDrawing = YES;
[self updatePositionWithTouches:touches];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[self endPosition];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self endPosition];
}
//在這里我們?nèi)ミB接路徑
- (void)drawRect:(CGRect)rect {
if (_selectedCircleArray.count) {
UIBezierPath *path = [UIBezierPath bezierPath];
for (int i = 0; i < _selectedCircleArray.count; i++) {
//如果說按鈕是第一個(gè),讓按鈕的中心點(diǎn)是路徑的起點(diǎn)
UIButton *btn = _selectedCircleArray[i];
if (i == 0) {
[path moveToPoint:btn.center];
} else {
[path addLineToPoint:btn.center];
}
}
if (!isWrongColor) {
//添加一根線到當(dāng)前手指所在的點(diǎn)
[path addLineToPoint:nowPoint];
//讓線頭看起來圓滑一點(diǎn)
UIBezierPath * rounds=[UIBezierPath bezierPathWithRoundedRect:CGRectMake(nowPoint.x-lineWidth/2, nowPoint.y-lineWidth/2, lineWidth, lineWidth) cornerRadius:lineWidth/2];
//渲染
[[UIColor greenColor] setFill];
[rounds fill];
}
//設(shè)置線的狀態(tài)
[path setLineWidth:lineWidth];
[tempLineColor set];
[path setLineJoinStyle:kCGLineJoinRound];
[path stroke];
}
}
//當(dāng)手指移動時(shí)判斷是否在九宮格button上
- (void)updatePositionWithTouches:(NSSet *)touches{
//記錄當(dāng)前手指的位置
UITouch *touch = [touches anyObject];
CGPoint curP = [touch locationInView:self];
nowPoint = curP;
//判斷當(dāng)前點(diǎn)在不在按鈕身上 如果按鈕不為空 保存選中的按鈕
UIButton *btn = [self btnContainsPoint:curP];
if (btn && btn.selected == NO) {
btn.selected = YES;
[_selectedCircleArray addObject:btn];
}
[self setNeedsDisplay];
}
- (UIButton *)btnContainsPoint:(CGPoint)point
{
for (UIButton *btn in self.subviews) {
if (CGRectContainsPoint(btn.frame, point)) {
return btn;
}
}
return nil;
}
- (void)endPosition {
isDrawing = NO;
UIButton *strbutton;
NSString *string=@"";
for (int i=0; i < _selectedCircleArray.count; i++) {
strbutton = _selectedCircleArray[i];
string= [string stringByAppendingFormat:@"%ld",(long)strbutton.tag-BaseTag];
}
//這個(gè)string 就是我們解鎖圖案數(shù)字的排列順序
[self.delegate sendLockString:string];//這里是我們的代理 用來把排列順序string傳遞到我們的父視圖
//也可以在這里判斷
if ([string isEqualToString:self.rightString]) {
....
}else{
//這里我直接當(dāng)錯(cuò)誤處理
[self showErrorCircles:string];
}
}
/**
清除至初始狀態(tài)
*/
- (void)clearColor {
if (isWrongColor) {// 重置顏色
isWrongColor = NO;
tempLineColor = lineColor;
}
}
- (void)clearSelectedButton {
for (UIButton *thisButton in _circleArray) {
[thisButton setSelected:NO];
[thisButton setBackgroundImage:[self getCircularSize:thisButton.frame.size borderWith:buttonBorderWidth color:themeColor insideColor:selectedPointColor solid:YES] forState:UIControlStateSelected];
}
[_selectedCircleArray removeAllObjects];
[self setNeedsDisplay];
}
- (void)clearColorAndSelectedButton {
if (!isDrawing) {
[self clearColor];
[self clearSelectedButton];
self.userInteractionEnabled = YES;
}
}
#pragma mark - Error Show
- (void)showErrorCircles:(NSString*)string {
isWrongColor = YES;
tempLineColor = wrongColor;
NSMutableArray* numbers = [[NSMutableArray alloc] initWithCapacity:string.length];
for (int i = 0; i < string.length; i++) {
NSRange range = NSMakeRange(i, 1);
NSNumber* number = [NSNumber numberWithInt:[string substringWithRange:range].intValue-1]; // 數(shù)字是1開始的
[numbers addObject:number];
[_circleArray[number.intValue] setSelected:YES];
}
for (UIButton* button in _circleArray) {
if (button.selected) {
[button setBackgroundImage:[self getCircularSize:button.frame.size borderWith:buttonBorderWidth color:themeColor insideColor:tempLineColor solid:YES] forState:UIControlStateSelected];
}
}
[self setNeedsDisplay];
self.userInteractionEnabled = NO;
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(clearColorAndSelectedButton) userInfo:nil repeats:NO];
}
// 生成我們選中和未選中的圖片
-(UIImage *)getCircularSize:(CGSize)size borderWith:(CGFloat)borderWith color:(UIColor *)color insideColor:(UIColor *)insideColor solid:(BOOL)solid{
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
//獲取顏色RGB
CGFloat red = 0.0;
CGFloat green = 0.0;
CGFloat blue = 0.0;
CGFloat alpha = 0.0;
[color getRed:&red green:&green blue:&blue alpha:&alpha];
CGContextSetRGBStrokeColor(context,red,green,blue,1.0);//畫筆線的顏色
CGContextSetLineWidth(context, borderWith);//線的寬度
if (solid) {
CGContextAddArc(context, size.width/2, size.height/2, size.width/2-size.width/4, 0, 2*M_PI, 0);
CGContextSetFillColorWithColor(context, insideColor.CGColor);
CGContextDrawPath(context, kCGPathFill);//繪制填充
}
CGContextAddArc(context, size.width/2, size.height/2, size.width/2-borderWith, 0, 2*M_PI, 0); //添加一個(gè)圓
CGContextDrawPath(context, kCGPathStroke); //繪制路徑
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//關(guān)閉圖形上下文
UIGraphicsEndImageContext();
return newImage;
}
在LockView.h中來寫我們的協(xié)議
@protocol LockViewDelegate
- (void)sendLockString:(NSString *)lockString;
@end
@interface LockView : UIView
- (instancetype)initLockViewWith:(CGRect)frame forWrongColor:(UIColor *)wrongColor themeColor:(UIColor *)themeColor lineColor:(UIColor *)lineColor selectedPointColor:(UIColor *)selectedPointColor margin:(CGFloat)margin buttonRadius:(CGFloat)buttonRaius lineWidth:(CGFloat)lineWidth buttonBorderWidth:(CGFloat)buttonBorderWidth;
@property id<LockViewDelegate>delegate;
@property NSString *rightString;
大功告成
QQ20180912-140117-HD.gif