iOS 九宫格解锁
思路:
1.画9个按钮,通过按钮的选中状态控制按钮.
2.连线通过贝塞尔曲线绘制.
3.校验密码通过给按钮绑定tag值判断.
主要代码:
OC版本:
- //
- // NineLockView.m
- // lockView
- //
- // Created by Shaoting Zhou on 2018/1/24.
- // Copyright © 2018年 Shaoting Zhou. All rights reserved.
- //
- #import "NineLockView.h"
- CGFloat const btnCount = ; //九宫格个数
- CGFloat const btnW = ; //单个按钮宽
- CGFloat const btnH = ; //单个按钮高
- CGFloat const viewY = ; //视图Y
- int const columnCount = ; //列数
- #define kScreenWidth [UIScreen mainScreen].bounds.size.width
- @interface NineLockView ()
- @property (nonatomic, strong) NSMutableArray * selectBtnsAry; //选中按钮的数组
- @property (nonatomic, assign) CGPoint currentPoint; //当前的点 坐标 用于判断最后一个点
- @end
- @implementation NineLockView
- -(NSMutableArray *)selectBtnsAry{
- if(!_selectBtnsAry){
- _selectBtnsAry = [NSMutableArray array];
- }
- return _selectBtnsAry;
- }
- //通过代码布局时会调用这个方法
- -(instancetype)initWithFrame:(CGRect)frame{
- if(self = [super initWithFrame:frame]){
- self.backgroundColor = [UIColor clearColor];
- [self addButton];
- }
- return self;
- }
- //通过sb xib布局时会调用这个方法
- -(instancetype)initWithCoder:(NSCoder *)aDecoder{
- if(self = [super initWithCoder:aDecoder]){
- [self addButton];
- }
- return self;
- }
- #pragma Mark - 布局按钮
- - (void)addButton{
- CGFloat height = ;;
- for (int i = ; i < btnCount; i++) {
- UIButton * btn = [UIButton buttonWithType:(UIButtonTypeCustom)];
- btn.tag = i;
- btn.userInteractionEnabled = NO; //不可交互
- //设置默认的图片
- [btn setBackgroundImage:[UIImage imageNamed:@"gesture_normal"] forState:(UIControlStateNormal)];
- //设置选中的图片
- [btn setBackgroundImage:[UIImage imageNamed:@"gesture_selected"] forState:(UIControlStateSelected)];
- int row = i / columnCount; //第几行
- int column = i % columnCount; //第几列
- CGFloat margin = (self.frame.size.width - columnCount * btnW) / (columnCount + ); //边距
- CGFloat btnX = margin + column * (btnW + margin); //x轴
- CGFloat btnY = row * (btnW + margin); //y轴
- // btn.backgroundColor =[UIColor redColor];
- btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
- height = btnH + btnY; //视图高等于 最后一个点的高+y
- [self addSubview:btn];
- }
- self.frame = CGRectMake(, viewY, kScreenWidth, height); //视图frame
- }
- - (CGPoint)pointWithTouch:(NSSet *)touches{
- UITouch * touch = [touches anyObject];
- CGPoint point = [touch locationInView:self];
- return point;
- }
- - (UIButton *)buttonWithPoint:(CGPoint)point{
- for (UIButton * btn in self.subviews) {
- if(CGRectContainsPoint(btn.frame, point)){
- return btn;
- }
- }
- return nil;
- }
- #pragma Mark - 开始移动
- - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
- //1.拿到触摸的点
- CGPoint point = [self pointWithTouch:touches];
- //2.根据触摸的点拿到相应的按钮
- UIButton * btn = [self buttonWithPoint:point];
- //3.设置状态
- if(btn && btn.selected == NO){
- btn.selected = YES;
- [self.selectBtnsAry addObject:btn];
- }
- }
- #pragma Mark - 移动中
- - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
- //1.拿到触摸的点
- CGPoint point = [self pointWithTouch:touches];
- //2.根据触摸的点拿到相应的按钮
- UIButton * btn = [self buttonWithPoint:point];
- //3.设置状态
- if(btn && btn.selected == NO){
- btn.selected = YES;
- [self.selectBtnsAry addObject:btn];
- }else{
- self.currentPoint = point;
- }
- [self setNeedsDisplay];
- }
- #pragma Mark - 结束移动
- - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
- if([self.delegete respondsToSelector:@selector(lockView:didFinishPath:)]){
- NSMutableString * path = [NSMutableString string];
- for (UIButton * btn in self.selectBtnsAry) {
- [path appendFormat:@"%ld",(long)btn.tag];
- }
- [self.delegete lockView:self didFinishPath:path];
- }
- //清空状态
- for(int i = ; i < self.selectBtnsAry.count; i++ ){
- UIButton * button = self.selectBtnsAry[i];
- button.selected = NO;
- }
- [self.selectBtnsAry removeAllObjects];
- [self setNeedsDisplay];
- }
- #pragma Mark - 取消移动
- - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
- [self touchesEnded:touches withEvent:event];
- }
- #pragma Mark - 绘图
- - (void)drawRect:(CGRect)rect{
- if(self.selectBtnsAry.count == ){
- return;
- }
- UIBezierPath * path = [UIBezierPath bezierPath];
- path.lineWidth = ;
- path.lineJoinStyle = kCGLineJoinRound;
- [[UIColor colorWithRed:/255.0 green:/255.0 blue:/255.0 alpha:0.5] set];
- //遍历按钮
- for(int i = ; i < self.selectBtnsAry.count; i++ ){
- UIButton * button = self.selectBtnsAry[i];
- NSLog(@"%d",i);
- if(i == ){
- //设置起点
- [path moveToPoint:button.center];
- }else{
- //连线
- [path addLineToPoint:button.center];
- }
- }
- [path addLineToPoint:self.currentPoint]; //最后一点 连接自己
- [path stroke];
- }
- @end
OC版本
- //
- // ViewController.m
- // lockView
- //
- // Created by Shaoting Zhou on 2018/1/24.
- // Copyright © 2018年 Shaoting Zhou. All rights reserved.
- //
- #import "ViewController.h"
- #import "NineLockView.h"
- #define kScreenWidth [UIScreen mainScreen].bounds.size.width
- #define kScreenHeight [UIScreen mainScreen].bounds.size.height
- @interface ViewController () <NineLockViewDelegate>
- @end
- @implementation ViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- self.view.backgroundColor = [UIColor brownColor];
- NineLockView * lockView = [[NineLockView alloc]initWithFrame:CGRectMake(, , kScreenWidth, kScreenHeight)];
- lockView.delegete = self;
- [self.view addSubview:lockView];
- }
- -(void)lockView:(NineLockView *)lockView didFinishPath:(NSString *)path{
- if(path.length <= ){
- NSLog(@"请至少连4个点");
- return;
- }
- if([path isEqualToString:@""]){
- NSLog(@"OK");
- }else{
- NSLog(@"error");
- }
- }
- - (void)didReceiveMemoryWarning {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- @end
OC版本
swift版本:
- //
- // ViewController.swift
- // lockView-Swift
- //
- // Created by Shaoting Zhou on 2018/1/25.
- // Copyright © 2018年 Shaoting Zhou. All rights reserved.
- //
- import UIKit
- class ViewController: UIViewController,nineLockViewDelegate {
- let kScreenHeight = UIScreen.main.bounds.size.height
- let kScreenWidth = UIScreen.main.bounds.size.width
- override func viewDidLoad() {
- super.viewDidLoad()
- self.view.backgroundColor = UIColor.brown
- let nineLockView = NineLockView.init(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight))
- nineLockView.delegate = self
- self.view.addSubview(nineLockView)
- // Do any additional setup after loading the view, typically from a nib.
- }
- //MARK: - 代理方法
- func lockView(lockView: NineLockView, path: String) {
- if(path.description.count < 4){
- print("至少连4个");
- return;
- }
- if(path == "01258"){
- print("密码正确");
- }else{
- print("密码错误");
- }
- }
- override func didReceiveMemoryWarning() {
- super.didReceiveMemoryWarning()
- // Dispose of any resources that can be recreated.
- }
- }
Swift版本
- //
- // NineLockView.swift
- // lockView-Swift
- //
- // Created by Shaoting Zhou on 2018/1/25.
- // Copyright © 2018年 Shaoting Zhou. All rights reserved.
- //
- import UIKit
- let btnCount = 9; //九宫格个数
- let btnW:CGFloat = 74.0; //单个按钮宽
- let btnH:CGFloat = 74.0; //单个按钮高
- let viewY:CGFloat = 300.0; //视图Y
- let columnCount = 3; //列数
- let kScreenHeight = UIScreen.main.bounds.size.height
- let kScreenWidth = UIScreen.main.bounds.size.width
- //创建协议
- protocol nineLockViewDelegate:NSObjectProtocol
- {
- func lockView(lockView:NineLockView,path:String)
- }
- class NineLockView: UIView {
- weak var delegate:nineLockViewDelegate?
- var selectBtnsAry = [UIButton] ()
- var currentPoint:CGPoint!
- override init(frame: CGRect) {
- super.init(frame: frame)
- self.backgroundColor = UIColor.clear
- self .addButton();
- }
- // MARK: 添加按钮
- func addButton(){
- var height:CGFloat = 0.0
- for var i in 0 ..< btnCount{
- let btn = UIButton.init(type: .custom)
- btn.setImage(#imageLiteral(resourceName: "gesture_normal"), for: .normal) //默认图片
- btn.setImage(#imageLiteral(resourceName: "gesture_selected"), for: .selected) //选中图片
- btn.tag = i
- btn.isUserInteractionEnabled = false //取消用户交互
- let row = i / columnCount //行数
- let column = i % columnCount //列数
- let margin:CGFloat = (self.frame.size.width - CGFloat(columnCount) * btnW) / CGFloat( (columnCount + 1)); //边距
- let btnX:CGFloat = margin + CGFloat(column) * (btnW + margin); //x轴
- let btnY:CGFloat = CGFloat(row) * (btnW + margin); //y轴
- btn.frame = CGRect.init(x: btnX, y: btnY, width: btnW, height: btnH)
- height = btnY + btnH //视图的高 = 最后一个按钮的高 + y
- self.addSubview(btn)
- }
- self.frame = CGRect.init(x: 0, y: viewY, width: kScreenWidth, height: height)
- }
- func pointWithTouch(touches:Set<UITouch>) -> CGPoint{
- let touch:UITouch = (touches as NSSet).anyObject() as! UITouch
- let point = touch.location(in: self)
- return point;
- }
- func buttonWithPoint(point:CGPoint) -> UIButton?{
- for var view:UIView in self.subviews {
- let btn:UIButton = view as! UIButton
- if(btn.frame.contains(point)){
- return btn
- }
- }
- return nil
- }
- // MARK: 开始移动
- override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
- //1.拿到触摸的点
- let point:CGPoint = self.pointWithTouch(touches: touches)
- //2.根据触摸的点拿到相应的按钮
- guard let btn:UIButton = self.buttonWithPoint(point: point) else{
- return;
- }
- //3.设置状态
- if(btn.isSelected == false){
- btn.isSelected = true
- self.selectBtnsAry.append(btn)
- }
- }
- // MARK: 移动中
- override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
- //1.拿到触摸的点
- let point:CGPoint = self.pointWithTouch(touches: touches)
- //2.根据触摸的点拿到相应的按钮
- guard let btn:UIButton = self.buttonWithPoint(point: point) else{
- return;
- }
- //3.设置状态
- if(btn.isSelected == false){
- btn.isSelected = true
- self.selectBtnsAry.append(btn)
- }else{
- self.currentPoint = point;
- }
- self.setNeedsDisplay()
- }
- // MARK: 移动停止
- override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
- if delegate != nil{
- var str = "";
- for var i in 0 ..< self.selectBtnsAry.count{
- let btn:UIButton = self.selectBtnsAry[i]
- str = str + String(btn.tag)
- }
- self.delegate?.lockView(lockView: self, path: str)
- }
- for var i in 0 ..< self.selectBtnsAry.count{
- let btn:UIButton = self.selectBtnsAry[i]
- btn.isSelected = false
- }
- self.selectBtnsAry.removeAll()
- self.setNeedsDisplay()
- }
- // MARK: 移动取消
- override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
- self.touchesEnded(touches, with: event)
- }
- // MARK: 绘图
- override func draw(_ rect: CGRect) {
- if(self.selectBtnsAry.count == 0){
- return;
- }
- let path:UIBezierPath = UIBezierPath.init()
- path.lineWidth = 8
- path.lineJoinStyle = .round
- UIColor.init(red: 32/255.0, green: 210/255.0, blue: 254/255.0, alpha: 0.5).set()
- //遍历按钮
- for var i in 0 ..< self.selectBtnsAry.count{
- let btn:UIButton = self.selectBtnsAry[i]
- if(i == 0){
- //起点
- path.move(to: btn.center)
- }else{
- //划线
- path.addLine(to: btn.center)
- }
- }
- path.addLine(to: self.currentPoint) //最后一点 连接自己
- path.stroke()
- }
- required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
Swift版本
基本演示:
这里的只演示下基本九宫格校验密码(密码已经存在:01258).
创建密码,修改密码思路类似.
github: https://github.com/pheromone/iOS-nineLock
iOS 九宫格解锁的更多相关文章
- appium 九宫格解锁招商银行手机客户端app
之前研究了一段时间的appium for native app 相应的总结如下: appium测试环境搭建 :ht ...
- App自动化(2)--Python&Appium实现安卓手机九宫格解锁
九宫格作为常见的手势密码,我们在使用的时候,是从起点开始,按住不放,然后滑动手指,直到最后一个点松开手指,如果与设置的手势密码匹配,则解锁成功. 现在大多数九宫格作为一个元素存在,很难定位到每一个点. ...
- iOS 指纹解锁 验证TouchID
iOS指纹解锁 1.首先,引入依赖框架 LocalAuthentication.framework #import <LocalAuthentication/LocalAuthenticatio ...
- iOS 九宫格手势密码
代码地址如下:http://www.demodashi.com/demo/11490.html 一.准备工作 需要准备什么环境 xcode,iOS8+ 本例子实现什么功能 主要实现手势密码设置,验证 ...
- Android之九宫格解锁的实现
<ignore_js_op> 下面是最重要的那个LocusPassWordView ...
- uiautomator2 实现App九宫格解锁
App九宫格解锁 之前在testerhome社区看见codeskyblue大佬写过一种方法,但是这种办法存在一个弊端,那就是多个点的坐标是写死的,也就是说要是换了部手机,九宫格解锁就行不通了,于是就想 ...
- Python+Appium自动化测试(10)-TouchAction类与MultiAction类(控件元素的滑动、拖动,九宫格解锁,手势操作等)
滑动屏幕方法swipe一般用于对页面进行上下左右滑动操作,但自动化过程中还会遇到其他情况,如对控件元素进行滑动.拖拽操作,九宫格解锁,手势操作,地图的放大与缩小等.这些需要针对控件元素的滑动操作,或者 ...
- iOS开发 - Swift - 自己写的一个九宫格解锁的Demo
前段时间做项目,公司要用到一个九宫格的手势解锁的需求. 虽然在很多地方都可以找到写好的第三方源码, 但是我的性格是不喜欢Ctrl+V的,于是自己凭着理解敲了一个出来,功能很简单,只是单纯的返回结果.附 ...
- IOS仿Android九宫格解锁效果[转]
原理很简单,监听view中touch的一系列事件,当判定手指位置在某个按钮附近的时候则判断此按钮选中,并画出线. 效果图如下: 你可以在NineGridUnlockView.m文件中方法 touche ...
随机推荐
- PAT 1136 A Delayed Palindrome
1136 A Delayed Palindrome (20 分) Consider a positive integer N written in standard notation with k ...
- 102. Binary Tree Level Order Traversal二叉树层序遍历
网址:https://leetcode.com/problems/binary-tree-level-order-traversal/ 参考:https://www.cnblogs.com/grand ...
- java Comparable and Comparator
1.Comparable简介 此接口对实现它的每个类的对象强加一个总排序.这种排序被称为类的自然排序,类的compareTo方法被称为其自然比较方法.可以通过 Collections.sort(和Ar ...
- thymeleaf下拉框从后台动态获取集合数据并回显选中
今天遇到从后台集合中取出对象在前台页面下拉列表展示: <select name="signature" lay-search="" class=" ...
- Python3+Scapy安装使用教程
一.说明 之前写DoS程序的时候(见"拒绝服务(DoS)理解.防御与实现"),数据包完全是自己构造的,这其中的难处一是要清楚各层协议的字段.字段长度.字段是数值还是字符.大头还是小 ...
- CentOS下运行Java文件Error: Could not find or load main class
今天,因为测试拷贝一个JvmTest.java文件到CentOS虚机上运行,发现文件编译没有问题,但运行时却报错,如下图: Java代码如下: package com.zhi.test; public ...
- 干货!一篇文章集合所有Linux基础命令
1 文件{ls -rtl # 按时间倒叙列出所有目录和文件 ll -rttouch file # 创建空白文件rm -rf 目录名 # 不提示删除非空目录(-r:递归删除 -f强制)dos2unix ...
- 【调试基础】Part 2 文本字符
01 字节存储顺序 大端:低字节存在高地址,高字节存在低地址.eg:IBM: 小端:低字节存在低地址,高字节存在高地址.eg:INTEL: 02 字符集 ASCII:128=26小写 + 26大写 + ...
- Linux Mysql创建用户并分配权限
1.查看全部的用户: select user,host from mysql.user\G; 2.新建用户: create user ‘用户名’@‘主机名’ identified by ‘用户密码 ...
- 'weinre' 不是内部或外部命令,也不是可运行的程序 或批处理文件。 解决方案
使用 npm install -g weinre 全局安装 weinre,weinre 安装目录是:C:\Users\Administrator\AppData\Roaming\npm 需要配置环境变 ...