簡體   English   中英

在Swift中將手勢識別器提取到兩個函數?

[英]Abstracting gesture recognizer to two functions in 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中完成的。

在storyboard中使用UIPanGestureRecognizer ,將其拖到相關視圖中。 ultraPan:連接到視圖控制器並將插座設置為此調用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
    }

沒關系。

但是創建UIPanGestureRecognizer的新子類(或其他東西)肯定會更好 ,因此有兩個新概念......

UIHorizontalPanGestureRecognizer

UIVerticalPanGestureRecognizer

那些基本上是一維的panners。

我完全不知道你是否會......委托子類化? 還是上課? (什么類?),或者某種擴展......的確,我基本上對此完全無能為力:)

目標是一個人的代碼,你可以有這樣的東西......

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

如何以這種方式繼承/擴展UIPanGestureRecognizer

但是創建UIPanGestureRecognizer的新子類(或其他東西)肯定會更好,因此有兩個新概念......

  • UIHorizo​​ntalPanGestureRecognizer

  • UIVerticalPanGestureRecognizer

那些基本上是一維的panners

正確。 這正是如何做到的,這是正常的做法。 實際上,這正是手勢識別器的用途 :每個gr僅識別其自己的手勢,並且當它確實時,它會使競爭的手勢識別器退避。 這是手勢識別的整 否則,我們仍然會回到純粹touchesBegan的前期日子等等(哦,恐怖)。

事實上,我的在線書籍討論了你在這里給出的一個例子

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子類。 我們覆蓋了touchesBegantouchesMoved :一旦識別開始,我們就會在看到下一次觸摸沿着錯誤的軸時失敗。 (您應該觀看Apple關於此主題的視頻;正如他們所說,當您將手勢識別器子類化時,您應該“提前失敗,經常失敗”。)我們還會覆蓋translationInView以便只能直接沿軸移動。 結果(如果您下載項目本身就可以看到)是一個可以水平或垂直拖動但不以其他方式拖動的視圖。

@Joe,這是我為了這個問題而迅速拼湊起來的東西。 為了便於實現,我只是給它一個回調而不是實現目標 - 動作系統。 隨意改變它。

enum PanDirection {
    case Horizontal
    case Vertical
}

class OneDimensionalPan: NSObject {

    var handler: (CGFloat -> ())?
    var direction: PanDirection

    @IBOutlet weak var panRecognizer: UIPanGestureRecognizer! {
        didSet {
            panRecognizer.addTarget(self, action: #selector(panned))
        }
    }

    @IBOutlet weak var panView: UIView!

    override init() {
        direction = .Horizontal
        super.init()
    }

    @objc private func panned(recognizer: UIPanGestureRecognizer) {
        let translation = panRecognizer.translationInView(panView)
        let delta: CGFloat
        switch direction {
        case .Horizontal:
            delta = translation.x
            break
        case .Vertical:
            delta = translation.y
            break
        }
        handler?(delta)
    }
}

在storyboard中,將UIPanGestureRecognizer拖到視圖控制器上,然后將Object拖到視圖控制器的頂部欄上,設置其類,並鏈接其IBOutlet 在那之后你應該好好去。 在視圖控制器代碼中,您可以設置其回調和平移方向。

更新說明>我想澄清為什么我讓這個類成為NSObject的子類:該類背后的驅動思想是將任何不必要的代碼保留在UIViewController 通過NSObject ,我可以將一個Object拖到故事板內的視圖控制器頂部欄上,並將其類設置為OneDimensionalPan 從那里,我能夠將@IBOutlet連接到它。 我本可以把它變成一個基類,但是它必須以編程方式實例化。 這更清潔了。 視圖控制器中唯一的代碼是訪問對象本身(通過@IBOutlet ),設置其方向,並設置其回調。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM