iOS手勢解鎖和指紋解鎖
效果
網上找到一個使用圖片的方案,KKGestureLockView,但是需求的話如果要做動畫美觀,你必須自己進行繪製,在這個基礎上進行自定義,先看看效果
手勢解鎖
1.首先手勢解鎖區域是一個個自定義的button,當接收到使用者手勢的時候,根據座標把對應的button放進陣列,進一步後續判斷
2.檢測到使用者手勢滑動的時候讓按鈕不斷進行重繪,形成動畫
3.然後手勢劃過的線也是一個蓋在解鎖區域上面的一個View,根據左邊進行路徑繪製
1.初始化
- (void)_lockViewInitialize{
self.backgroundColor = [UIColor clearColor];
self.lineColor = [[UIColor blackColor] colorWithAlphaComponent:0.3];
self.lineWidth = kLineDefaultWidth;
self.isShowInner = YES;
// 解鎖區域
self.contentInsets = UIEdgeInsetsMake(0, 0, 0, 0);
self.contentView = [[UIView alloc] initWithFrame:UIEdgeInsetsInsetRect(self.bounds, self.contentInsets)];
// self.contentView.backgroundColor = [UIColor yellowColor];
[self addSubview:self.contentView];
// 手勢軌跡區域
self.gestureLineView = [[KKGestureLineView alloc] initWithFrame:self.bounds];
self.gestureLineView.backgroundColor = [UIColor clearColor];
[self addSubview:self.gestureLineView];
self.buttonSize = CGSizeMake(kNodeDefaultWidth, kNodeDefaultHeight);
// 呼叫數量的setter方法進行按鈕的新增
self.numberOfGestureNodes = kNumberOfNodes;
self.gestureNodesPerRow = kNodesPerRow;
}
2.定座標
- (void)layoutSubviews{
[super layoutSubviews];
_gestureLineView.lineColor = [UIColor redColor];
_gestureLineView.lineWidth = self.isDotShow ? 0 : kLineDefaultWidth;
self.contentView.frame = UIEdgeInsetsInsetRect(self.bounds, self.contentInsets);
CGFloat horizontalNodeMargin = (self.contentView.bounds.size.width - self.buttonSize.width * self.gestureNodesPerRow)/(self.gestureNodesPerRow - 1);
NSUInteger numberOfRows = ceilf((self.numberOfGestureNodes * 1.0 / self.gestureNodesPerRow));
CGFloat verticalNodeMargin = (self.contentView.bounds.size.height - self.buttonSize.height *numberOfRows)/(numberOfRows - 1);
for (int i = 0; i < self.numberOfGestureNodes ; i++) {
int row = i / self.gestureNodesPerRow;
int column = i % self.gestureNodesPerRow;
KKGestureLockItemView *button = [self.buttons objectAtIndex:i];
button.nodeWith = _nodeWidth?_nodeWidth:18;
button.isShowInner = _isShowInner;
button.frame = CGRectMake(floorf((self.buttonSize.width + horizontalNodeMargin) * column), floorf((self.buttonSize.height + verticalNodeMargin) * row), self.buttonSize.width, self.buttonSize.height);
}
}
3.核心解鎖區域三個方法
*touchesBegan
*touchesMoved
*touchesEnded
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
// 獲取開始的座標
UITouch *touch = [touches anyObject];
CGPoint locationInContentView = [touch locationInView:self.contentView];
// 根據座標獲取到對應的按鈕
KKGestureLockItemView *touchedButton = [self _buttonContainsThePoint:locationInContentView];
// 如果開始的時候不是按鈕區域不進行繪製
if (touchedButton != nil) {
// 觸發到按鈕進行動畫
[touchedButton setItemViewType:KKGestureLockItemTypeSelect];
[touchedButton startAnimation];//開始動畫
// 新增到選擇的陣列
[_gestureLineView.selectedButtons addObject:touchedButton];
_gestureLineView.trackedLocationInContentView = locationInContentView;
if (_delegateFlags.didBeginWithPasscode) {
[self.delegate gestureLockView:self didBeginWithPasscode:[NSString stringWithFormat:@"%d",(int)touchedButton.tag]];
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
// 獲取到座標
UITouch *touch = [touches anyObject];
CGPoint locationInContentView = [touch locationInView:self.contentView];
// 手勢區域在規定座標裡面
if (CGRectContainsPoint(self.contentView.bounds, locationInContentView)) {
// 如果觸發到了按鈕區域,按鈕進行動畫
KKGestureLockItemView *touchedButton = [self _buttonContainsThePoint:locationInContentView];
if (touchedButton != nil && [_gestureLineView.selectedButtons indexOfObject:touchedButton]==NSNotFound) {
[touchedButton setItemViewType:KKGestureLockItemTypeSelect];
[touchedButton startAnimation];//開始動畫
[_gestureLineView.selectedButtons addObject:touchedButton];
if ([_gestureLineView.selectedButtons count] == 1) {
//If the touched button is the first button in the selected buttons,
//It's the beginning of the passcode creation
if (_delegateFlags.didBeginWithPasscode) {
[self.delegate gestureLockView:self didBeginWithPasscode:[NSString stringWithFormat:@"%d",(int)touchedButton.tag]];
}
}
}
// 不斷繪製軌跡線
_gestureLineView.trackedLocationInContentView = locationInContentView;
[_gestureLineView setNeedsDisplay];
}
}
4.手勢的動畫無非就是不斷呼叫drawRect
這裡介紹幾個常用的方法,具體實現都是慢慢試出來的,知道方法就好了,需要的自己下載Demo看吧
* 1. CGContextSetStrokeColorWithColor 邊緣線的顏色 CGContextSetFillColorWithColor 填充顏色
* 2. CGContextSetLineWidth 邊緣線的寬度
* 3. CGContextAddArc 畫一個圓 x,y為圓點座標,radius半徑,startAngle為開始的弧度,endAngle為 結束的弧度,clockwise 0為順時針,1為逆時針。
* 4. CGContextDrawPath 繪製路徑,第一個引數是上下文,第二個引數是kCGPathFill--> 填充 kCGPathStroke-->路勁 kCGPathFillStroke--> 填充+路徑
* 5. CGContextStrokePath 類似上面的邊框路徑繪製
* 6. CGContextFillPath 類似上面的填充繪製
* 7. CGContextClearRect 清理上下文
* 8. CGContextSaveGState 和 CGContextRestoreGState CGContextSaveGState函式的作用是將當前圖形狀態推入堆疊。之後,您對圖形狀態所做的修改會影響隨後的描畫操作,但不影響儲存在堆疊中的拷貝。在修改完成後,您可以通過CGContextRestoreGState函式把堆疊頂部的狀態彈出,返回到之前的圖形狀態。這種推入和彈出的方式是回到之前圖形狀態的快速方法,避免逐個撤消所有的狀態修改;這也是將某些狀態(比如裁剪路徑)恢復到原有設定的唯一方式
* 9. CGContextClip 裁剪上下文
* 10. CGContextAddEllipseInRect 畫橢圓
* 11. CGContextAddQuadCurveToPoint 兩點之間正餘弦波動,雙點控制
* 12. CGContextDrawImage 這個會使圖片上下點到
小知識,以這個為例 自己用繪圖方法畫一個帶漸變的按鈕
- (void)drawRect:(CGRect)rect {
// Drawing code
//// General Declarations
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = UIGraphicsGetCurrentContext();
//// Gradient Declarations
CGFloat gradientLocations[] = {0, 0.32, 1};
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)@[(id)UIColor.greenColor.CGColor, (id)[MKJView mixColor1:[UIColor greenColor] color2:[UIColor whiteColor] ratio:0.5].CGColor, (id)UIColor.whiteColor.CGColor], gradientLocations);
//// Oval Drawing
UIBezierPath* ovalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(0, 0, 24, 24)];
CGContextSaveGState(context);
[ovalPath addClip];
CGContextDrawLinearGradient(context, gradient, CGPointMake(12, 0), CGPointMake(12, 24), 0);
CGContextRestoreGState(context);
//// Text Drawing
CGRect textRect = CGRectMake(6, 6, 13, 12);
{
NSString* textContent = @"D";
NSMutableParagraphStyle* textStyle = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
textStyle.alignment = NSTextAlignmentLeft;
NSDictionary* textFontAttributes = @{NSFontAttributeName: [UIFont systemFontOfSize: UIFont.labelFontSize], NSForegroundColorAttributeName: UIColor.blackColor, NSParagraphStyleAttributeName: textStyle};
CGFloat textTextHeight = [textContent boundingRectWithSize: CGSizeMake(textRect.size.width, INFINITY) options: NSStringDrawingUsesLineFragmentOrigin attributes: textFontAttributes context: nil].size.height;
CGContextSaveGState(context);
CGContextClipToRect(context, textRect);
[textContent drawInRect: CGRectMake(CGRectGetMinX(textRect), CGRectGetMinY(textRect) + (CGRectGetHeight(textRect) - textTextHeight) / 2, CGRectGetWidth(textRect), textTextHeight) withAttributes: textFontAttributes];
CGContextRestoreGState(context);
}
//// Cleanup
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
}
+(UIColor *)mixColor1:(UIColor*)color1 color2:(UIColor *)color2 ratio:(CGFloat)ratio
{
if(ratio > 1)
ratio = 1;
const CGFloat * components1 = CGColorGetComponents(color1.CGColor);
const CGFloat * components2 = CGColorGetComponents(color2.CGColor);
// NSLog(@"Red1: %f", components1[0]);
// NSLog(@"Green1: %f", components1[1]);
// NSLog(@"Blue1: %f", components1[2]);
// NSLog(@"Red2: %f", components2[0]);
// NSLog(@"Green2: %f", components2[1]);
// NSLog(@"Blue2: %f", components2[2]);
NSLog(@"ratio = %f",ratio);
CGFloat r = components1[0]*ratio + components2[0]*(1-ratio);
CGFloat g = components1[1]*ratio + components2[1]*(1-ratio);
CGFloat b = components1[2]*ratio + components2[2]*(1-ratio);
// CGFloat alpha = components1[3]*ratio + components2[3]*(1-ratio);
return [UIColor colorWithRed:r green:g blue:b alpha:1];
}
5.指紋解鎖
1.canEvaluatePolicy 判斷是否支援指紋或者是否開啟指紋
2.evaluatePolicy 進行指紋識別校驗,彈出系統框
3.匯入LocalAuthentication框架
4.指紋識別錯誤的明細參考參考error明細
- (BOOL)isTouchIDEnableOrNotBySystem
{
#ifdef __IPHONE_8_0
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError])
{
/**
可以驗證指紋 手機支援而且手機開啟指紋模式
*/
return YES;
}
else
{
/**
無法驗證指紋 手機不支援或者使用者未開啟指紋模式
*/
return NO;
}
#else
/**
無法驗證指紋
*/
return NO;
#endif /* __IPHONE_8_0 */
}
- (void)startVerifyTouchID:(void (^)(void))completeBlock failure:(void (^)(void))failureBlock
{
NSString *touchIDReason = [NSString stringWithFormat:@"我要解鎖%@",_appName];
#ifdef __IPHONE_8_0
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
// Hide "Enter Password" button
myContext.localizedFallbackTitle = @"";
// show the authentication UI
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError])
{
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:touchIDReason
reply:^(BOOL success, NSError *error) {
if (success) {
// User authenticated successfully, take appropriate action
dispatch_async(dispatch_get_main_queue(), ^{
/**
指紋校驗 成功
*/
[self verifySucceed:completeBlock];
});
} else {
// User did not authenticate successfully, look at error and take appropriate action
dispatch_async(dispatch_get_main_queue(), ^{
/**
指紋校驗 失敗
*/
[self authenticatedFailedWithError:error failure:failureBlock];
});
}
}];
}
else
{
// Could not evaluate policy; look at authError and present an appropriate message to user
dispatch_async(dispatch_get_main_queue(), ^{
[self evaluatePolicyFailedWithError:nil];
});
}
#endif /* __IPHONE_8_0 */
}
1.注意這裡有一個引數,我們現在用的是LAPolicyDeviceOwnerAuthenticationWithBiometrics,預設就是TouchID失敗之後不會跳轉到密碼設定,如果你換成LAPolicyDeviceOwnerAuthentication,那麼就會進行密碼設定的跳轉,還是根據需求進行配置
2.另一個引數localizedReason就是配置彈窗下顯示指紋解鎖的提示語
Demo地址
相關文章
- iOS指紋解鎖和手勢解鎖iOS
- iOS開發 手勢密碼解鎖和指紋TouchID解鎖iOS密碼
- 專案需求討論-APP手勢解鎖及指紋解鎖APP
- 微信錢包設定指紋或手勢密碼解鎖方法 微信錢包鎖怎麼開啟密碼
- win10指紋鎖如何設定_win10設定指紋解鎖的方法Win10
- WPF實現手勢解鎖
- 2018螢幕指紋解鎖智慧手機推薦 螢幕指紋手機哪些值得買?
- 新iPhone有望加入指紋解鎖,你會買嗎?iPhone
- 實現TouchID指紋解鎖(圖文並茂)
- iOS 手機螢幕手勢鎖iOS
- ios10鎖屏怎麼解鎖ios10鎖屏介面解鎖方法iOS
- 用 canvas 實現 Web 手勢解鎖CanvasWeb
- 原生 JavaScript 實現手勢解鎖元件JavaScript元件
- 網盤安全新姿勢!雲盒子企業網盤:用指紋解鎖資料
- 華為P8亮相工信部網站:支援指紋解鎖功能網站
- 實用派:iPhone 6指紋解鎖失敗問題解決辦法iPhone
- 解鎖 Redis 鎖的正確姿勢Redis
- 解鎖redis鎖的正確姿勢Redis
- 為啥溼手不能解鎖?解析手機指紋識別原理
- HTML5實現螢幕手勢解鎖HTML
- 蘋果ios10怎麼解鎖 ios10解鎖方式介紹蘋果iOS
- 防手機鎖屏解鎖自定義ViewView
- windows10系統設定裡沒有指紋解鎖選項怎麼解決Windows
- win10系統怎麼設定電腦指紋密碼解鎖Win10密碼
- windows10系統中沒有指紋解鎖設定如何解決Windows
- iPhone X人臉識別被吐槽:解鎖速度太慢 懷念指紋!iPhone
- win10怎麼加指紋密碼_win10指紋密碼鎖如何新增指紋Win10密碼
- 解鎖自定義分享功能新姿勢
- 解鎖Spring框架姿勢1Spring框架
- 指紋鎖或取代傳統防盜門鎖成為智慧家居首選
- 智慧門鎖安全嗎?超六成智慧門鎖IC卡鑰匙可破解複製 八成智慧門鎖可假指紋解
- 榮耀Magic2系統升級:新增卡路里識別、最佳化指紋解鎖
- 指紋解鎖車輛 不再遙遠,生物辨識技術變革正在進行
- iOS10怎麼用iOS9解鎖 iOS10用回iOS9解鎖方式圖文教程iOS
- 一加6T螢幕指紋解鎖設定使用教程 一加6T怎麼設定指紋識別?
- oracle 查詢鎖 && 解鎖Oracle
- Oracle查詢鎖、解鎖Oracle
- 解鎖跨域的九種姿勢跨域