菜鸟教程小白 发表于 2022-12-13 00:21:09

objective-c - 识别用户手势的路径


                                            <p><p>我正在开发一个屏幕上有 9 个 View 的应用程序,我希望用户以他们想要的方式连接 View ,并将他们的序列记录为密码。
但我不知道我应该使用哪个手势识别器。</p>

<p>我应该使用 CMUnistrokeGestureRecognizer 还是几个滑动手势的组合或其他什么?
谢谢。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>您可以使用 <a href="http://developer.apple.com/library/ios/#documentation/uikit/reference/UIPanGestureRecognizer_Class/Reference/Reference.html" rel="noreferrer noopener nofollow"><code>UIPanGestureRecognizer</code></a> ,类似:</p>

<pre><code>CGFloat const kMargin = 10;

- (void)viewDidLoad
{
    ;

    // create a container view that all of our subviews for which we want to detect touches are:

    CGFloat containerWidth = fmin(self.view.bounds.size.width, self.view.bounds.size.height) - kMargin * 2.0;

    UIView *container = [ initWithFrame:CGRectMake(kMargin, kMargin, containerWidth, containerWidth)];
    container.backgroundColor = ;
    ;

    // now create all of the subviews, specifying a tag for each; and

    CGFloat cellWidth = (containerWidth - (4.0 * kMargin)) / 3.0;

    for (NSInteger column = 0; column &lt; 3; column++)
    {
      for (NSInteger row = 0; row &lt; 3; row++)
      {
            UIView *cell = [ initWithFrame:CGRectMake(kMargin + column * (cellWidth + kMargin),
                                                                  kMargin + row    * (cellWidth + kMargin),
                                                                  cellWidth, cellWidth)];
            cell.tag = row * 3 + column;
            cell.backgroundColor = ;
            ;
      }
    }

    // finally, create the gesture recognizer

    UIPanGestureRecognizer *pan = [ initWithTarget:self
                                                                        action:@selector(handlePan:)];
    ;
}

- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
    static NSMutableArray *gesturedSubviews;

    // if we&#39;re starting a gesture, initialize our list of subviews that we&#39;ve gone over

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
      gesturedSubviews = ;
    }

    // now figure out whether:
    //   (a) are we over a subview; and
    //   (b) is this a different subview than we last were over

    CGPoint location = ;

    for (UIView *subview in gesture.view.subviews)
    {
      if (CGRectContainsPoint(subview.frame, location))
      {
            if (subview != )
            {
                ;

                // an example of the sort of graphical flourish to give the
                // some visual cue that their going over the subview in question
                // was recognized

                [UIView animateWithDuration:0.25
                                    delay:0.0
                                    options:UIViewAnimationOptionAutoreverse
                                 animations:^{
                                     subview.alpha = 0.5;
                                 }
                                 completion:^(BOOL finished){
                                     subview.alpha = 1.0;
                                 }];
            }
      }
    }

    // finally, when done, let&#39;s just log the subviews
    // you would do whatever you would want here

    if (gesture.state == UIGestureRecognizerStateEnded)
    {
      NSLog(@&#34;We went over:&#34;);

      for (UIView *subview in gesturedSubviews)
      {
            NSLog(@&#34;%d&#34;, subview.tag);
      }

      // you might as well clean up your static variable when you&#39;re done

      gesturedSubviews = nil;
    }
}
</code></pre>

<p>显然,您可以按自己的方式创建 subview ,并以任何方式跟踪它们,但我们的想法是让 subview 具有唯一的 <code>tag</code> 编号,而手势识别器只需查看您以一个手势遍历它们的顺序。 </p>

<p>即使我没有准确捕捉到您想要的内容,它至少向您展示了如何使用平移手势识别器来跟踪手指从一个 subview 到另一个 subview 的移动。</p>

<hr/>

<p><strong>更新:</strong></p>

<p>如果您想在用户登录时在屏幕上绘制路径,您可以使用 <code>UIBezierPath</code> 创建一个 <code>CAShapeLayer</code>。我将在下面演示,但作为警告,我不得不指出这可能不是一个很好的安全功能:通常输入密码时,你会向用户展示足够多的内容,以便他们确认他们正在做他们想要什么,但还不够,以至于有人可以回头看看整个密码是什么。输入文本密码时,通常 iOS 会暂时显示您按下的最后一个键,但很快会将其转换为星号,这样您就无法看到整个密码。这就是我最初的建议。</p>

<p>但是,如果您真的一心想在用户绘制路径时向他们展示路径,您可以使用类似以下的内容。首先,这需要<a href="https://developer.apple.com/library/ios/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/Introduction/Introduction.html" rel="noreferrer noopener nofollow">Quartz 2D</a> .因此将 <code>QuartzCore.framework</code> 添加到您的项目中(参见 <a href="http://developer.apple.com/library/ios/#recipes/xcode_help-project_editor/Articles/AddingaLibrarytoaTarget.html" rel="noreferrer noopener nofollow">Linking to a Library or Framework</a> )。二、导入QuartCore头文件:</p>

<pre><code>#import &lt;QuartzCore/QuartzCore.h&gt;
</code></pre>

<p>第三,将 pan 处理程序替换为:</p>

<pre><code>- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
    static NSMutableArray *gesturedSubviews;
    static UIBezierPath *path = nil;
    static CAShapeLayer *shapeLayer = nil;

    // if we&#39;re starting a gesture, initialize our list of subviews that we&#39;ve gone over

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
      gesturedSubviews = ;
    }

    // now figure out whether:
    //   (a) are we over a subview; and
    //   (b) is this a different subview than we last were over

    CGPoint location = ;

    for (UIView *subview in gesture.view.subviews)
    {
      if (!path)
      {
            // if the path hasn&#39;t be started, initialize it and the shape layer

            path = ;
            ;
            shapeLayer = [ init];
            shapeLayer.strokeColor = .CGColor;
            shapeLayer.fillColor = .CGColor;
            shapeLayer.lineWidth = 2.0;
            ;
      }
      else
      {
            // otherwise add this point to the layer&#39;s path

            ;
            shapeLayer.path = path.CGPath;
      }

      if (CGRectContainsPoint(subview.frame, location))
      {
            if (subview != )
            {
                ;

                [UIView animateWithDuration:0.25
                                    delay:0.0
                                    options:UIViewAnimationOptionAutoreverse
                                 animations:^{
                                     subview.alpha = 0.5;
                                 }
                                 completion:^(BOOL finished){
                                     subview.alpha = 1.0;
                                 }];
            }
      }
    }

    // finally, when done, let&#39;s just log the subviews
    // you would do whatever you would want here

    if (gesture.state == UIGestureRecognizerStateEnded)
    {
      // assuming the tags are numbers between 0 and 9 (inclusive), we can build the password here

      NSMutableString *password = ;

      for (UIView *subview in gesturedSubviews)
            ;

      NSLog(@&#34;Password = %@&#34;, password);

      // clean up our array of gesturedSubviews

      gesturedSubviews = nil;

      // clean up the drawing of the path on the screen the user drew

      ;
      shapeLayer = nil;
      path = nil;
    }
}
</code></pre>

<p>这会产生用户在手势进行时绘制的路径:</p>

<p> <img src="/image/Be1IO.png" alt="path of user&#39;s finger"/> </p>

<p>与其显示用户每次手指移动所绘制的路径,不如在 subview 的中心之间画线,例如:</p>

<pre><code>- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
    static NSMutableArray *gesturedSubviews;
    static UIBezierPath *path = nil;
    static CAShapeLayer *shapeLayer = nil;

    // if we&#39;re starting a gesture, initialize our list of subviews that we&#39;ve gone over

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
      gesturedSubviews = ;
    }

    // now figure out whether:
    //   (a) are we over a subview; and
    //   (b) is this a different subview than we last were over

    CGPoint location = ;

    for (UIView *subview in gesture.view.subviews)
    {
      if (CGRectContainsPoint(subview.frame, location))
      {
            if (subview != )
            {
                ;

                if (!path)
                {
                  // if the path hasn&#39;t be started, initialize it and the shape layer

                  path = ;
                  ;
                  shapeLayer = [ init];
                  shapeLayer.strokeColor = .CGColor;
                  shapeLayer.fillColor = .CGColor;
                  shapeLayer.lineWidth = 2.0;
                  ;
                }
                else
                {
                  // otherwise add this point to the layer&#39;s path

                  ;
                  shapeLayer.path = path.CGPath;
                }

                [UIView animateWithDuration:0.25
                                    delay:0.0
                                    options:UIViewAnimationOptionAutoreverse
                                 animations:^{
                                     subview.alpha = 0.5;
                                 }
                                 completion:^(BOOL finished){
                                     subview.alpha = 1.0;
                                 }];
            }
      }
    }

    // finally, when done, let&#39;s just log the subviews
    // you would do whatever you would want here

    if (gesture.state == UIGestureRecognizerStateEnded)
    {
      // assuming the tags are numbers between 0 and 9 (inclusive), we can build the password here

      NSMutableString *password = ;

      for (UIView *subview in gesturedSubviews)
            ;

      NSLog(@&#34;Password = %@&#34;, password);

      // clean up our array of gesturedSubviews

      gesturedSubviews = nil;

      // clean up the drawing of the path on the screen the user drew

      ;
      shapeLayer = nil;
      path = nil;
    }
}
</code></pre>

<p>这会产生如下内容:</p>

<p> <img src="/image/2ZMp6.png" alt="user path with lines"/> </p>

<p>您有各种各样的选择,但希望您现在拥有构建模块,以便您可以设计自己的解决方案。</p></p>
                                   
                                                <p style="font-size: 20px;">关于objective-c - 识别用户手势的路径,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/14161405/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/14161405/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: objective-c - 识别用户手势的路径