[英]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的新子類(或其他東西)肯定會更好,因此有兩個新概念......
UIHorizontalPanGestureRecognizer
UIVerticalPanGestureRecognizer
那些基本上是一維的panners
正確。 這正是如何做到的,這是正常的做法。 實際上,這正是手勢識別器的用途 :每個gr僅識別其自己的手勢,並且當它確實時,它會使競爭的手勢識別器退避。 這是手勢識別的整點 ! 否則,我們仍然會回到純粹touchesBegan
的前期日子等等(哦,恐怖)。
事實上,我的在線書籍討論了你在這里給出的一個例子 :
http://www.apeth.com/iOSBook/ch18.html#_subclassing_gesture_recognizers
這是一個在Swift中實現它的實際可下載示例:
觀察此處使用的策略。 我們制作UIPanGestureRecognizer子類。 我們覆蓋了touchesBegan
和touchesMoved
:一旦識別開始,我們就會在看到下一次觸摸沿着錯誤的軸時失敗。 (您應該觀看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.