抽象手势识别器在Swift中的两个功能? [英] Abstracting gesture recognizer to two functions in Swift?

查看:143
本文介绍了抽象手势识别器在Swift中的两个功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想想一下iOS屏幕,您可以将手指向上/向下进行操作(想象一下,缩放),



或者,



作为一个单独的功能,你可以移动你的手指左/右做某事(想象说,改变颜色或旋转)。



他们是



分开



功能,你只能在一个



所以,如果开始为一个水平版本,它只剩下一个水平版本。相反,如果它开始为垂直版本,它只能是一个垂直版本。



这是一个有点棘手的事情,我准确地说明了如何做以下...的基本模式是:

  if(r.state == .Began || panway == .WasZeros) 
{
prev = tr
if(tr.x == 0&& tr.y == 0)
{
panway = .WasZeros
return
}
if(abs(tr.x)> abs(tr.y))... set panway
}

这个工作非常好,这里正是在Swift中做的。



一个 UIPanGestureRecognizer ,将其拖到相关视图中。将代理连接到视图控制器,并将插座设置为此调用 ultraPan:

  enum Panway 
{
case Vertical
case水平
case WasZeros
}
var panway:Panway = .Vertical
var prev :CGPoint!

@IBAction func ultraPan(r:UIPanGestureRecognizer!)
{
let tr = r.translationInView(r.view)

if(r。 state == .Began || panway == .WasZeros)
{
prev = tr

if(tr.x == 0&& tr.y == 0)
{
panway = .WasZeros
return
}

if(abs(tr.x)> abs(tr.y))
{
panway = .Horizo​​ntal
}
else
{
panway = .Vertical
}
}

if(panway == .Horizo​​ntal)//你的左右函数
{
var h = tr.x - prev.x
let sensitivity:CGFloat = 50.0
h = h / sensitivity
//调整你的左右函数,例如
someProperty = someProperty + h
}

if(panway == .Vertical) //更大/更小
{
var v = tr.y - prev.y
let sensitivity:CGFloat = 2200.0
v = v / sensitivity
//调整你的上下函数,例如
someOtherProperty = someOtherProperty + v
}

prev = tr
}

没关系。



但是,一定要更好地制作UIPanGestureRecognizer的新子类(或某物),以便有两个新的概念......

  UIHorizo​​ntalPanGestureRecognizer 

UIVerticalPanGestureRecognizer

这些将基本上是一维的扫描仪。



我绝对不知道是否你会...分类代表?还是班级? (什么类?),或者可能是某种扩展...确实,我基本上完全没有意义:)



目标是在代码中,你可以有这样的东西...

  @IBAction func horizo​​ntalPanDelta(..?)
{
someProperty = someProperty + delta
}
@IBAction func verticalPanDelta(..?)
{
otherProperty = otherProperty + delta
}

如何以这种方式继承/扩展 UIPanGestureRecognizer

解决方案


但是,一个新的子类(或某物)的UIPanGestureRecognizer肯定会更好,所以有两个新的概念......




  • UIHorizo​​ntalPanGestureRecognizer


  • UIVerticalPanGestureRecognizer




这些将基本上是一维制图器


正确。正是这样做,而且是正常的做法。的确,这正是手势识别器 :每个g.r.仅识别其自己的手势,并且当它这样做时,它导致竞争的手势识别器退回。那就是手势识别器的整个!否则,我们仍然会回到前一个g.r。天的纯 touchesBegan 等等(哦,恐怖)。



我的在线图书实际上讨论过, #_subclassing_gesture_recognizersrel =nofollow> http://www.apeth.com/iOSBook/ch18.html#_subclassing_gesture_recognizers



这里是一个实际的在Swift中实现的可下载示例:



https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch05p203gestureRecognizers/ch18p541gestureRecognizers/HorizVertPanGestureRecognizers.swift



观察这里使用的策略。我们制作UIPanGestureRecognizer子类。我们覆盖 touchesBegan touchesMoved :一旦识别开始,我们失败,一旦看起来下一个触摸是错误的轴。 (你应该看这个主题的苹果视频;正如他们所说的,当你将手势识别器子类化时,你应该早点失败,经常失败)。我们还覆盖 translationInView 只能沿轴线直接运动是可能的。结果(您可以看到,如果您下载项目本身)是一个可以水平或垂直拖动但不以其他方式拖动的视图。


Imagine an iOS screen where you can move your finger up/down to do something (imagine say, "scale"),

Or,

as a separate function you can move your finger left/right to do something (imagine say, "change color" or "rotate").

They are

separate

functions, you can only do one at at time.

So, if it "begins as" a horizontal version, it is remains only a horizontal version. Conversely if it "begins as" a vertical version, it remains only a vertical version.

It is a little bit tricky to do this, I present exactly how to do it below...the fundamental pattern is:

if (r.state == .Began || panway == .WasZeros )
    {
    prev = tr
    if (tr.x==0 && tr.y==0)
        {
        panway = .WasZeros
        return
        }
    if (abs(tr.x)>abs(tr.y)) ... set panway
    }

This works very well and here's exactly how to do it in Swift.

In storyboard take a UIPanGestureRecognizer, drag it to the view in question. Connect the delegate to the view controller and set the outlet to this call ultraPan:

enum Panway
    { 
    case Vertical
    case Horizontal
    case WasZeros
    }
var panway:Panway = .Vertical
var prev:CGPoint!

@IBAction func ultraPan(r:UIPanGestureRecognizer!)
    {
    let tr = r.translationInView(r.view)

    if (r.state == .Began || panway == .WasZeros )
        {
        prev = tr

        if (tr.x==0 && tr.y==0)
            {
            panway = .WasZeros
            return
            }

        if (abs(tr.x)>abs(tr.y))
            {
            panway = .Horizontal
            }
        else
            {
            panway = .Vertical
            }
        }

    if (panway == .Horizontal)  // your left-right function
        {
        var h = tr.x - prev.x
        let sensitivity:CGFloat = 50.0
        h = h / sensitivity
        // adjust your left-right function, example
        someProperty = someProperty + h
        }

    if (panway == .Vertical)    // bigger/smaller
        {
        var v = tr.y - prev.y
        let sensitivity:CGFloat = 2200.0
        v = v / sensitivity
        // adjust your up-down function, example
        someOtherProperty = someOtherProperty + v
        }

    prev = tr
    }

That's fine.

But it would surely be better to make a new subclass (or something) of UIPanGestureRecognizer, so that there are two new concepts......

UIHorizontalPanGestureRecognizer

UIVerticalPanGestureRecognizer

Those would be basically one-dimensional panners.

I have absolutely no clue whether you would ... subclass the delegates? or the class? (what class?), or perhaps some sort of extension ... indeed, I basically am completely clueless on this :)

The goal is in one's code, you can have something like this ...

@IBAction func horizontalPanDelta( ..? )
    {
    someProperty = someProperty + delta
    }
@IBAction func verticalPanDelta( ..? )
    {
    otherProperty = otherProperty + delta
    }

How to inherit/extend UIPanGestureRecognizer in this way??

解决方案

But it would surely be better to make a new subclass (or something) of UIPanGestureRecognizer, so that there are two new concepts......

  • UIHorizontalPanGestureRecognizer

  • UIVerticalPanGestureRecognizer

Those would be basically one-dimensional panners

Correct. That's exactly how to do it, and is the normal approach. Indeed, that is exactly what gesture recognizers are for: each g.r. recognizes only its own gesture, and when it does, it causes the competing gesture recognizers to back off. That is the whole point of gesture recognizers! Otherwise, we'd still be back in the pre-g.r. days of pure touchesBegan and so forth (oh, the horror).

My online book discusses, in fact, the very example you are giving here:

http://www.apeth.com/iOSBook/ch18.html#_subclassing_gesture_recognizers

And here is an actual downloadable example that implements it in Swift:

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch05p203gestureRecognizers/ch18p541gestureRecognizers/HorizVertPanGestureRecognizers.swift

Observe the strategy used here. We make UIPanGestureRecognizer subclasses. We override touchesBegan and touchesMoved: the moment recognition starts, we fail as soon as it appears that the next touch is along the wrong axis. (You should watch Apple's video on this topic; as they say, when you subclass a gesture recognizer, you should "fail early, fail often".) We also override translationInView so that only movement directly along the axis is possible. The result (as you can see if you download the project itself) is a view that can be dragged either horizontally or vertically but in no other manner.

这篇关于抽象手势识别器在Swift中的两个功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆