20
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

3D Touch専用のカスタムGestureRecognizerの作り方

Posted at

iPhone6S, 6S Plusで新しく追加された3D Touchの機能を利用するために class ForceTouchGestureRecognizer: UIGestureRecognizerを作りました。

そこで、

  • 3D Touchについて
  • UIGestureRecognizerのサブクラスの作り方

の2つを紹介します。

作ったやつ
https://github.com/milkit/ForceTouchGesture

公式ドキュメント Adopting 3D Touch on iPhone

3D Touch API概要

3D Touchとはスクリーンを押した強さを認識してくれる新しいiPhoneの機能です。公式ドキュメントによると以下の4つに分類されます。

  1. HomeScreen quick action
  • UIKit peek and pop API
  • Web view peek and pop API
  • UITouch force properties

今回は4の紹介です。

UITouch force properties

UITouchクラスに今回追加されたのは2つのプロパティです。

  • var force: CGFloat { get }
  • var maximumPossibleForce: CGFloat { get }

名前のままで、forceでスクリーンを押した強さ、maximumPossibleForceでその最大許容値を取得できます。

また、3D Touchが有効かどうかを取得するAPIも公開されています。
3D Touchはユーザー自身で設定からオフにすることも可能なので、端末から識別できません。

UITraitCollectionクラスの

var forceTouchCapability: UIForceTouchCapability { get }

で判別することができます。以下のように定義されています。

enum UIForceTouchCapability : Int {
    case Unknown
    case Unavailable
    case Available
}

traitCollection: UITraitCollectionというプロパティがUIViewController, UIView, UIWindow, UIScreenなどにあります。正確に言うと、UITraitEnvironmentプロトコルを採用しているクラスはプロパティを持っています。
 ここで注意点としては、 例えば、UIViewのtraitCollectionから判別するときに、そのUIViewのインスタンスがビュー階層に追加されていないと、Unknownが返ってきます。 ここ要注意です。

UIGestureRecognizerのサブクラスの作り方

UIGestureRecognizerのサブクラスを作るときはフレームワークをimportする必要があります。Swiftだと以下です。

import UIKit.UIGestureRecognizerSubclass

そして、サブクラスを作っていきます。

public class ForceTouchGestureRecognizer: UIGestureRecognizer {
	
	public private(set) var force: CGFloat = 0
	public private(set) var forceTouchAvailable = false
	public var minimumForce: CGFloat = 3.0
	// 省略
}

そして以下4つのメソッドをオーバーライドしてカスタマイズしていきます。

public func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent)
public func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent)
public func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent)
public func touchesCancelled(touches: Set<UITouch>, withEvent event: UIEvent)

例えば、touchesBeganではジェスチャーを認識したいときは, stateを.Beganにして、それ以外を.Failedにします。

override public func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) {
        
        super.touchesBegan(touches, withEvent: event)
        
        guard let touch = touches.first where self.forceTouchAvailable && touches.count == 1 else {
            
            self.state = .Failed
            return
        }
        
        if #available(iOS 9, *) {
            
            self.minimumForce = min(self.minimumForce, touch.maximumPossibleForce)
            self.force = touch.force
            self.state = .Began
        } else {
            
            self.state = .Failed
        }
    }

また例えば、touchesMovedではminimumForceに設定した値を超えた場合はstateを.Endedにしてジェスチャーを終了しています。

override public func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent) {
        
        super.touchesMoved(touches, withEvent: event)
        
        if self.state == .Failed {
            
            return
        }
        
        if #available(iOS 9.0, *) {
            
            self.force = touches.first!.force
            
            if self.force > self.minimumForce {
                
                self.state = .Ended
                self.vibrateIfNeeded()
            }
        }
    }

おまけ

iPhone6Sの3D Touchのときに3D Touch専用のバイブレーションがあって、すごく気持ちが良かったので、バイブレーションの機能をつけたいなと思って探しました。しかし、通知時とかの普通のバイブレーションしかなかったです。残念。以下実装方法の紹介です。

import AudioToolbox

// バイブレーションしたいタイミングで
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)

これだけです。

20
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?