1.最终效果图
2.思路:
2.1.首先把界面搭建起来:以绘制九宫格的方式,在view上绘制出九个button
2.2.然后在layoutSubview里设置子控件的frame值
2.3.手指触摸和移动的时候都判断下当前触摸的点是否在button范围之内&&这个button的状态不是选中状态,如果是,就设置选中状态,并把这些被选中的按钮添加到一个可变的数组中
2.4.手指移动的时候获取当前的移动的点的位置作为一个全局的属性
2.5.在drawRect方法中,常见路径;循环被选中的按钮组成的数组,判断当前选中的按钮是不是第一个,如果是。就作为路径的起始点,如果不是,就作为路径的终点。然后渲染一下,此时要记得一定要在移动的方法中重绘一下,否则连线是不会被显示的(self setNeedDisplay)
2.6.我们拖拽连线的时候,发现在移动的时候一直有一根线,所以我们应该在绘制的时候加上这一根线,[pathaddLineToPoint:self.current];
2.7.在手指抬起的时候,我们要判断一下密码是否正确(此时用到代理),拼接密码通过代理传值到主控制器中,在实现这个代理方法的时候,绘制位图上下文,把绘制密码的view的图片截图给到上面的imageView,
2.8.此时有一个小bug,我们看到截图的图片有一个小尾巴,原因是因为我们在绘制密码的时候给它加了一根线,所以此时我们可以通过在手指抬起的方法中,把全局变量的当前点的位置设置成为被选中数组中最后一个button的中心点。
3.源代码
#import"HMUnlockView.h"
@interfaceHMUnlockView()
@property(nonatomic,strong)NSMutableArray*secletBtn;
@property(nonatomic,assign)CGPointcurrent;
@end
@implementationHMUnlockView
-(NSMutableArray*)secletBtn{
if(_secletBtn==nil) {
_secletBtn=[NSMutableArrayarray];
}
return_secletBtn;
}
-(void)awakeFromNib{
for(inti=0; i<9; i++) {
UIButton*btn=[[UIButtonalloc]init];
btn.userInteractionEnabled=NO;
[btnsetImage:[UIImageimageNamed:@"gesture_node_normal"]forState:UIControlStateNormal];
[btnsetImage:[UIImageimageNamed:@"gesture_node_highlighted"]forState:UIControlStateSelected];
[selfaddSubview:btn];
}
}
-(void)layoutSubviews{
[superlayoutSubviews];
intcolm=3;
CGFloatw=74;
CGFloath=w;
CGFloatmargenX=(self.bounds.size.width-colm*w)/(colm+1);
CGFloatmargenY=(self.bounds.size.height-colm*h)/(colm+1);
for(inti=0; i
UIButton*btn=self.subviews[i];
CGFloatx=margenX+(i%colm)*(margenX+w);
CGFloaty=margenY+(i/colm)*(margenY+h);
btn.frame=CGRectMake(x, y, w, h);
}
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{
UITouch*touch=touches.anyObject;
//判断触摸的点在不在btn范围之内
CGPointcurrent=[touchlocationInView:touch.view];
for(inti=0; i
UIButton*btn=self.subviews[i];
if(CGRectContainsPoint(btn.frame, current)&&btn.selected==NO) {
btn.selected=YES;
btn.tag=i;
[self.secletBtnaddObject:btn];
}
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent*)event{
//移动
UITouch*touch=touches.anyObject;
CGPointcurrent=[touchlocationInView:touch.view];
self.current=current;
[selftouchesBegan:toucheswithEvent:event];
[selfsetNeedsDisplay];
}
//在手指抬起的时候判断密码是否正确,并且延迟几秒钟之后清屏
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent*)event{
//在手指抬起的时候设置当前的点为最后一个按钮的中心点
self.current=[self.secletBtn.lastObjectcenter];
[selfsetNeedsDisplay];
NSMutableString*pwd=[NSMutableStringstring];
for(UIButton*btninself.secletBtn) {
[pwdappendFormat:@"%@",@(btn.tag)];
}
if([self.delegaterespondsToSelector:@selector(unlockView:withPwdString:)]) {
[self.delegateunlockView:selfwithPwdString:pwd];
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 *NSEC_PER_SEC)),dispatch_get_main_queue(), ^{
for(UIButton*btninself.secletBtn) {
btn.selected=NO;
}
[self.secletBtnremoveAllObjects];
[selfsetNeedsDisplay];
});
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
if(self.secletBtn.count==0) {
return;
}
//连线
UIBezierPath*path=[UIBezierPathbezierPath];
[[UIColorwhiteColor]set];
path.lineWidth=10;
path.lineCapStyle=kCGLineCapRound;
path.lineJoinStyle=kCGLineJoinRound;
//循环数组判断被选中的按钮是不是第一个,如果是就作为连线的起始点,如果不是就作为终点
for(inti=0;i<self.secletBtn.count;i++){
UIButton*btn=self.secletBtn[i];
CGPointcenter=btn.center;
if(i==0) {
[pathmoveToPoint:center];
}else{
[pathaddLineToPoint:center];
}
[pathaddLineToPoint:self.current];
[pathstroke];
}
网友评论