zoukankan      html  css  js  c++  java
  • 简单方法实现手势解锁

    手势解锁这样的例子网上很多。对于新手而言,如果对iOS不是很熟悉,做这样的功能有一种无从下手的感觉,主要是因为某些细节看起来不好实现。我平时在开发项目的时候,一般遵循一个原则就是,先详细分析,把整个逻辑理清楚,先不管看起来多么难,一个一个的细节剥离开来,然后开始构思,最好是越简单越好,条理性越清楚越好。我最初学习iOS的时候,当时很想做一个手势解锁这样的功能,但是因为当时对iOS开发不熟悉,尝试了很多复杂的方式,但是总是不是很完美。现在就采用一种简单地方式来实现一个手势解锁组件。这是我目前想到的最简单的方法。

    先看一下具体的效果图:


     

    下面我先详细分析一下,具体的实现方式:

    1.实现3行3列排布圆形,每个圆之间的间距相等,总体摆匀称就行了(这里涉及到一些坐标运算)。

    2.截获用户手指在屏幕上滑动的事件,然后根据滑动的具体坐标绘制折线(请允许我把这些连接起来的线称为折线)。

    3.触摸手指离开屏幕时,清除所有的绘制图案。

    这里有个比较棘手的细节不好处理,简单归纳如下:

    如果某个点已经被连过,那么下次再次移动到此点上的时候,不能再重复连线。

    现在我们开始分析前面所述的三个步骤如何实现:

    1.这里的圆形,我们观察到,有两种状态,一种是发光的,一种是不发光的。我最初刚开始看到这样的效果的效果的时候,我直观的使用绘图的方式绘制了9个圆形,但这样思考问题的时候,很显然感觉到异常复杂,仅仅是处理圆形的两种状态就已经很让人头痛了。这里,我们直接创建9个按钮,然后设置不同状态的图片即可。所以我们在初始化方法里面创建9个button,并添加到父视图。这里最好对按钮做一些封装,屏蔽一些细节,让总体的代码更加简洁。这里我继承UIButton类,实现了一个名为HGCircleView的类。在后面创建的时候,我们直接引用这个类:

    \在initWithFrame方法里面实现如下的代码 创建圆形

        for (NSUInteger i = 0; i < COL_COUNT * ROW_COUNT; ++i) {
            HGCircleView* circleView = [HGCircleView circleView];
            [self addSubview:circleView];
        }

    2.主要的逻辑就在于第2步了,当用户在屏幕上移动触摸点的时候,我们要追踪到移动的轨迹,然后绘制折线。

    首先,要追踪用户触摸的轨迹,我们需要重写三个方法:

    touchesBegan、touchesMoved、touchesEnded

    这三个方法里面我们可以记录下用户最初按压时的点,移动过程中的当前点,以及手指离开时的点。

    在这里,先不要急于绘制移动的路径。最终的目的是要把所有触摸轨迹经过的圆形串起来并生成密码。所以我在这里用一个容器,保存了路径经过的所有的circleView。这里处理一个细节就是,当触摸到圆形的时候,我们设置圆形的状态是selected.并在circleView类的内部设置好selected状态下,显示发光效果的图片。

    这里顺便就可以处理前面提到的那个比较棘手的细节,在手势经过圆形的时候,先做一个检查,如果发现圆形已经处于selected状态,那么,就不在把圆形加入容器,这样就不会重复选择,很轻松就解决了那个问题。

    接下来,在drawRect方法里面绘制触摸轨迹,遍历容器,然后把所有的圆形的center加入UIBezierPath,然后绘制UIBezierPath即可。


    这样会出现一个新的问题,就是,当触摸移动到其他位置(不在圆形上),这个时候,不能同步绘制,这里我采取的处理方式是,用一个点记录当前用户手指触摸移动的位置,然后把这个点作为最后一个点加入到UIBezierPath中,为了保证这个点的可靠性,在每次按压屏幕的时候将这个点置为(-10, -10),并且在添加到UIBezierPath路径之前检查一下,如果不是(-10, -10)则加入路径。

    // 1.容器为空,不执行任何绘制 

      if (0 == self.circleViews.count) {
            return;
        }
       
        UIBezierPath* bezierPath = [UIBezierPath new];
        [bezierPath moveToPoint: [[self.circleViews firstObject] center]];
        for (NSUInteger i = 1; i < self.circleViews.count; ++i) {
            [bezierPath addLineToPoint:[[self.circleViews objectAtIndex:i] center]];
        }
       
        if (NO == CGPointEqualToPoint(self.curlastPoint, CGPointMake(-10.0f, -10.0f))) {
            [bezierPath addLineToPoint:self.curlastPoint];
        }
        // 2.设置线形
        bezierPath.lineWidth = 7;
        bezierPath.lineJoinStyle = kCGLineJoinBevel;
        [[UIColor colorWithRed:36/255.0 green:200/255.0 blue:260/255.0 alpha:0.5]  set];       

    // 3.绘制路径 

       [bezierPath stroke];


    3.手指触摸弹起来的时候,需要清空绘制,这个时候,这需要清空保存所有被选择circleView的容器即可。注意在清空之前,应该先利用容器内的圆形的相关信息生成密码。并且把所有圆形的状态置为Normal状态。

          上述这些步骤即可以完成一个手势解锁功能。好了,说了半天,也没有用上手势识别器,仅仅处理了三个事件。你可以下载详细代码参考。

         详细代码实现github地址:https://github.com/hoowang/HGGestureLockerExample



    文/大雁南飞(简书作者)
    原文链接:http://www.jianshu.com/p/1b81a4483391
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
  • 相关阅读:
    java如何实现以数据流的形式下载压缩包到本地?
    在用easyui中做CRUD功能时,当删除一行或多行数据后再点击修改会提示你选中了多行,如何解决这个bug了?
    windows中当你的键盘无法使用时我们可以用另一种方法哦
    Idea中如何将web项目打包成war包并放到tomcat中启动
    [CSS3] Use media query to split css files and Dark mode (prefers-color-scheme: dark)
    [PWA] Storage information for PWA application
    [HTML5] Native lazy-loading for the web
    [Dynamic Programming] 198. House Robber
    [Javascript] Sort by multi factors
    [Javascript] Keyword 'in' to check prop exists on Object
  • 原文地址:https://www.cnblogs.com/Hakim/p/5341597.html
Copyright © 2011-2022 走看看