Xamarin.iOS での 3D Touch の概要

この記事では、新しい iPhone 6s および iPhone 6s Plus 3D Touch ジェスチャをアプリで使用する方法について説明します。

3D Touch 対応アプリの例

この記事では、新しい 3D Touch API を使って、新しい iPhone 6s および iPhone 6s Plus デバイス上で実行されている Xamarin.iOS アプリに感圧ジェスチャを追加する方法について説明します。

3D Touch を使うと、iPhone アプリはユーザーがデバイスの画面に触れていることを認識できるだけでなく、ユーザーが加えている圧力の強さを感知し、さまざまな圧力レベルに対応することもできます。

3D Touch は、アプリに次の機能を提供します。

  • 感圧性 - アプリは、ユーザーが画面に触れている強弱の程度を測定し、その情報を利用できるようになりました。 たとえば、ペイント アプリは、ユーザーが画面をタッチする強さに基づいて線を太くしたり、細くしたりできます。
  • Peek と Pop - ユーザーが現在のコンテキストから移動しなくてもデータを操作できるようになりました。 画面を強く押すと、興味のある項目をクイック表示することができます (メッセージのプレビューなど)。 より強く押すことで、項目にポップ表示することができます。
  • クイック アクション - クイック アクションは、ユーザーがデスクトップ アプリで項目を右クリックしたときにポップアップされるコンテキスト メニューのようなものだと考えてください。 クイック アクションを使用すると、ホーム画面のアプリ アイコンから直接、アプリ内の関数にショートカットを追加できます。
  • シミュレーターでの 3D Touch のテスト - 正しい Mac ハードウェアを使用して、iOS シミュレーターで 3D Touch 対応アプリをテストできます。

筆圧対応機能

前述のように、UITouch クラスの新しいプロパティを使用すると、ユーザーが iOS デバイスの画面に適用している負荷の量を測定し、ユーザー インターフェイスでこの情報を使用できます。 たとえば、圧力の量に基づいてブラシ ストロークの半透明度を高めたり不透明にしたりします。

圧力の量に基づいて半透明度を高めたり不透明にしたりしてレンダリングされるブラシ ストローク

3D Touch では、アプリが iOS 9 (またはそれ以上) で実行されていて、iOS デバイスが 3D Touch をサポートできる場合、圧力の変化によって TouchesMoved イベントが発生します。

たとえば、TouchesMovedUIView イベントを監視する場合に、次のコードを使用して、ユーザーが画面に適用している現在の負荷を取得することができます。

public override void TouchesMoved (NSSet touches, UIEvent evt)
{
    base.TouchesMoved (touches, evt);
    UITouch touch = touches.AnyObject as UITouch;
    if (touch != null)
    {
        // Get the pressure
        var force = touch.Force;
        var maxForce = touch.MaximumPossibleForce;

        // Do something with the touch and the pressure
        ...
    }
}

この MaximumPossibleForce プロパティは、アプリが実行されている iOS デバイスに基づいて、UITouchForce プロパティの可能な限り高い値を返します。

重要

圧力が変化すると、X/Y 座標が変更されていなくても TouchesMoved イベントが発生します。 この動作の変更に伴い、iOS アプリは、TouchesMoved イベントをより頻繁に呼び出し、X/Y 座標が最後の TouchesMoved 呼び出しと同じになるようにする必要があります。

詳細については、Apple の 「TouchCanvas: UITouch を効率的かつ効果的に」の サンプル アプリと「UITouch クラス リファレンス」を参照してください。

クイック表示とポップ表示

3D Touch は、ユーザーが現在の場所から移動しなくても、アプリ内の情報をこれまで以上に迅速に操作するための新しい方法を提供します。

たとえば、アプリにメッセージのテーブルが表示されている場合、ユーザーはアイテムを強く押して、オーバーレイ ビュー (Apple はクイック表示と呼んでいます) でそのコンテンツをプレビューできます。

コンテンツのピークの例

ユーザーが強く押すと、通常のメッセージ ビュー (-ping をビューにポップ表示する と呼ばれます) に入ります。

3D Touch の可用性の確認

UIViewController を操作する場合、次のコードを使用して、アプリが実行されている iOS デバイスが 3D Touch をサポートしているかどうかを確認できます。

public override void TraitCollectionDidChange(UITraitCollection previousTraitCollection)
{
    //Important: call the base function
    base.TraitCollectionDidChange(previousTraitCollection);

    //See if the new TraitCollection value includes force touch
    if (TraitCollection.ForceTouchCapability == UIForceTouchCapability.Available) {
        //Do something with 3D touch, for instance...
        RegisterForPreviewingWithDelegate (this, View);
        ...

このメソッドは、 前または ViewDidLoad() 後に呼び出される場合があります。

クイック表示とポップ表示の処理

3D Touch を処理できる iOS デバイスでは、UIViewControllerPreviewingDelegate クラスのインスタンスを使用して、クイック表示ポップ表示の項目の詳細表示を処理できます。 たとえば、MasterViewController というテーブル ビュー コントローラーがある場合は、次のコードを使用してピーク表示ポップ表示をサポートできます。

using System;
using System.Collections.Generic;
using UIKit;
using Foundation;
using CoreGraphics;

namespace DTouch
{
    public class PreviewingDelegate : UIViewControllerPreviewingDelegate
    {
        #region Computed Properties
        public MasterViewController MasterController { get; set; }
        #endregion

        #region Constructors
        public PreviewingDelegate (MasterViewController masterController)
        {
            // Initialize
            this.MasterController = masterController;
        }

        public PreviewingDelegate (NSObjectFlag t) : base(t)
        {
        }

        public PreviewingDelegate (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        /// Present the view controller for the "Pop" action.
        public override void CommitViewController (IUIViewControllerPreviewing previewingContext, UIViewController viewControllerToCommit)
        {
            // Reuse Peek view controller for details presentation
            MasterController.ShowViewController(viewControllerToCommit,this);
        }

        /// Create a previewing view controller to be shown at "Peek".
        public override UIViewController GetViewControllerForPreview (IUIViewControllerPreviewing previewingContext, CGPoint location)
        {
            // Grab the item to preview
            var indexPath = MasterController.TableView.IndexPathForRowAtPoint (location);
            var cell = MasterController.TableView.CellAt (indexPath);
            var item = MasterController.dataSource.Objects [indexPath.Row];

            // Grab a controller and set it to the default sizes
            var detailViewController = MasterController.Storyboard.InstantiateViewController ("DetailViewController") as DetailViewController;
            detailViewController.PreferredContentSize = new CGSize (0, 0);

            // Set the data for the display
            detailViewController.SetDetailItem (item);
            detailViewController.NavigationItem.LeftBarButtonItem = MasterController.SplitViewController.DisplayModeButtonItem;
            detailViewController.NavigationItem.LeftItemsSupplementBackButton = true;

            // Set the source rect to the cell frame, so everything else is blurred.
            previewingContext.SourceRect = cell.Frame;

            return detailViewController;
        }
        #endregion
    }
}

この GetViewControllerForPreview メソッドは、クイック表示操作を実行するために使用されます。 テーブル セルとバッキング データにアクセスし、現在のストーリーボードから DetailViewController を読み込みます。 PreferredContentSize を (0,0) に設定すると、既定のクイック表示のビュー サイズが求められます。 最後に、表示するセル以外のすべてを previewingContext.SourceRect = cell.Frame でぼかすと、表示用の新しいビューが返されます。

ユーザーが強く押すと、CommitViewControllerポップ表示ビューのピーク表示で作成したビューを再利用します。

クイック表示とポップ表示の登録

ユーザーが項目をクイック表示およびポップ表示できるようにするビュー コントローラーから、このサービスに登録する必要があります。 上記のテーブル ビュー コントローラー (MasterViewController) の例では、次のコードを使用します。

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // Check to see if 3D Touch is available
    if (TraitCollection.ForceTouchCapability == UIForceTouchCapability.Available) {
        // Register for Peek and Pop
        RegisterForPreviewingWithDelegate(new PreviewingDelegate(this), View);
    }
    ...

}

ここでは、上記で作成した PreviewingDelegate のインスタンスを使用して RegisterForPreviewingWithDelegate メソッドを呼び出します。 3D Touch をサポートする iOS デバイスでは、ユーザーは項目を強く押してクイック表示することができます。 さらに強く押すと、項目は標準の表示ビューにポップ表示されます。

詳細については、Apple の ViewControllerPreviews: UIViewController プレビュー API サンプル アプリの使用、UIPreviewAction クラス リファレンスUIPreviewActionGroup クラス リファレンスUIPreviewActionItem プロトコル リファレンスを参照してください。

クイック アクション

3D Touch とクイック アクションを使うと、iOS デバイスのホーム画面アイコンからアプリ内の機能への共通の、すばやく簡単にアクセスできるショートカットを追加できます。

前述のように、クイック アクションは、ユーザーがデスクトップ アプリで項目を右クリックしたときにポップアップされるコンテキスト メニューのようなものだと考えてください。 クイック アクションを使用して、アプリのよく使う機能へのショートカットを提供する必要があります。

クイック アクション メニューの例

静的クイック アクションの定義

アプリに必要な 1 つ以上のクイック アクションが静的であり、変更する必要がない場合は、アプリの Info.plist ファイルで定義できます。 外部エディターでこのファイルを編集し、次のキーを追加します。

<key>UIApplicationShortcutItems</key>
<array>
    <dict>
        <key>UIApplicationShortcutItemIconType</key>
        <string>UIApplicationShortcutIconTypeSearch</string>
        <key>UIApplicationShortcutItemSubtitle</key>
        <string>Will search for an item</string>
        <key>UIApplicationShortcutItemTitle</key>
        <string>Search</string>
        <key>UIApplicationShortcutItemType</key>
        <string>com.company.appname.000</string>
    </dict>
    <dict>
        <key>UIApplicationShortcutItemIconType</key>
        <string>UIApplicationShortcutIconTypeShare</string>
        <key>UIApplicationShortcutItemSubtitle</key>
        <string>Will share an item</string>
        <key>UIApplicationShortcutItemTitle</key>
        <string>Share</string>
        <key>UIApplicationShortcutItemType</key>
        <string>com.company.appname.001</string>
    </dict>
</array>

ここでは、次のキーを使用して 2 つの静的なクイック アクション項目を定義します。

  • UIApplicationShortcutItemIconType - クイック アクション項目によって表示されるアイコンを、次のいずれかの値として定義します。

    • UIApplicationShortcutIconTypeAdd
    • UIApplicationShortcutIconTypeAlarm
    • UIApplicationShortcutIconTypeAudio
    • UIApplicationShortcutIconTypeBookmark
    • UIApplicationShortcutIconTypeCapturePhoto
    • UIApplicationShortcutIconTypeCaptureVideo
    • UIApplicationShortcutIconTypeCloud
    • UIApplicationShortcutIconTypeCompose
    • UIApplicationShortcutIconTypeConfirmation
    • UIApplicationShortcutIconTypeContact
    • UIApplicationShortcutIconTypeDate
    • UIApplicationShortcutIconTypeFavorite
    • UIApplicationShortcutIconTypeHome
    • UIApplicationShortcutIconTypeInvitation
    • UIApplicationShortcutIconTypeLocation
    • UIApplicationShortcutIconTypeLove
    • UIApplicationShortcutIconTypeMail
    • UIApplicationShortcutIconTypeMarkLocation
    • UIApplicationShortcutIconTypeMessage
    • UIApplicationShortcutIconTypePause
    • UIApplicationShortcutIconTypePlay
    • UIApplicationShortcutIconTypeProhibit
    • UIApplicationShortcutIconTypeSearch
    • UIApplicationShortcutIconTypeShare
    • UIApplicationShortcutIconTypeShuffle
    • UIApplicationShortcutIconTypeTask
    • UIApplicationShortcutIconTypeTaskCompleted
    • UIApplicationShortcutIconTypeTime
    • UIApplicationShortcutIconTypeUpdate

    UIApplicationShortcutIconType 画像

  • UIApplicationShortcutItemSubtitle - 項目の字幕を定義します。

  • UIApplicationShortcutItemTitle - 項目のタイトルを定義します。

  • UIApplicationShortcutItemType - アプリ内の項目を識別するために使用する文字列値です。 詳細については、次のセクションを参照してください。

重要

Info.plist ファイルに設定されているクイック アクションのショートカット項目に Application.ShortcutItems プロパティを使用してアクセスすることはできません。 これらは HandleShortcutItem イベント ハンドラーにのみ渡されます。

クイック アクション 項目の識別

前に説明したように、アプリの Info.plist でクイック アクション項目を定義すると、UIApplicationShortcutItemType キーを識別するための文字列値が割り当てられます。

これらの識別子をコードで操作しやすくするには、アプリのプロジェクトに呼び出された ShortcutIdentifier クラスを追加し、次のようにします。

using System;

namespace AppSearch
{
    public static class ShortcutIdentifier
    {
        public const string First = "com.company.appname.000";
        public const string Second = "com.company.appname.001";
        public const string Third = "com.company.appname.002";
        public const string Fourth = "com.company.appname.003";
    }
}

クイック アクションの処理

次に、ホーム画面でアプリのアイコンからクイック アクション項目を選択するユーザーを処理するように、アプリの AppDelegate.cs ファイルを変更する必要があります。

次の編集を行います。

using System;
...

public UIApplicationShortcutItem LaunchedShortcutItem { get; set; }

public bool HandleShortcutItem(UIApplicationShortcutItem shortcutItem) {
    var handled = false;

    // Anything to process?
    if (shortcutItem == null) return false;

    // Take action based on the shortcut type
    switch (shortcutItem.Type) {
    case ShortcutIdentifier.First:
        Console.WriteLine ("First shortcut selected");
        handled = true;
        break;
    case ShortcutIdentifier.Second:
        Console.WriteLine ("Second shortcut selected");
        handled = true;
        break;
    case ShortcutIdentifier.Third:
        Console.WriteLine ("Third shortcut selected");
        handled = true;
        break;
    case ShortcutIdentifier.Fourth:
        Console.WriteLine ("Forth shortcut selected");
        handled = true;
        break;
    }

    // Return results
    return handled;
}

public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
    var shouldPerformAdditionalDelegateHandling = true;

    // Get possible shortcut item
    if (launchOptions != null) {
        LaunchedShortcutItem = launchOptions [UIApplication.LaunchOptionsShortcutItemKey] as UIApplicationShortcutItem;
        shouldPerformAdditionalDelegateHandling = (LaunchedShortcutItem == null);
    }

    return shouldPerformAdditionalDelegateHandling;
}

public override void OnActivated (UIApplication application)
{
    // Handle any shortcut item being selected
    HandleShortcutItem(LaunchedShortcutItem);

    // Clear shortcut after it's been handled
    LaunchedShortcutItem = null;
}

public override void PerformActionForShortcutItem (UIApplication application, UIApplicationShortcutItem shortcutItem, UIOperationHandler completionHandler)
{
    // Perform action
    completionHandler(HandleShortcutItem(shortcutItem));
}

まず、ユーザーが最後に選択したクイック アクション項目を追跡するパブリック LaunchedShortcutItem プロパティを定義します。 次に、FinishedLaunching メソッドをオーバーライドし、launchOptions が渡されたかどうかや、クイック アクション項目が含まれているかどうかを確認します。 その後、クイック アクションを LaunchedShortcutItem プロパティに保存します。

次に、OnActivated メソッドをオーバーライドし、選択した起動項目を操作対象の HandleShortcutItem メソッドに渡します。 現在は、コンソールにメッセージが書き込まれるだけです。 実際のアプリでは、必要なアクションを処理します。 アクションが実行されると、LaunchedShortcutItem プロパティがクリアされます。

最後に、アプリが既に実行されている場合は、クイック アクション項目を処理するために PerformActionForShortcutItem メソッドが呼び出されるため、ここで HandleShortcutItem メソッドをオーバーライドして呼び出す必要があります。

動的クイック アクション項目の作成

アプリ Info.plist のファイルで静的なクイック アクション項目を定義するほかに、動的なクイック アクションを作成することもできます。 2 つの新しい動的クイック アクションを定義するには、AppDelegate.cs ファイルをもう一度編集し、FinishedLaunching メソッドを次のように変更します。

public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
    var shouldPerformAdditionalDelegateHandling = true;

    // Get possible shortcut item
    if (launchOptions != null) {
        LaunchedShortcutItem = launchOptions [UIApplication.LaunchOptionsShortcutItemKey] as UIApplicationShortcutItem;
        shouldPerformAdditionalDelegateHandling = (LaunchedShortcutItem == null);
    }

    // Add dynamic shortcut items
    if (application.ShortcutItems.Length == 0) {
        var shortcut3 = new UIMutableApplicationShortcutItem (ShortcutIdentifier.Third, "Play") {
            LocalizedSubtitle = "Will play an item",
            Icon = UIApplicationShortcutIcon.FromType(UIApplicationShortcutIconType.Play)
        };

        var shortcut4 = new UIMutableApplicationShortcutItem (ShortcutIdentifier.Fourth, "Pause") {
            LocalizedSubtitle = "Will pause an item",
            Icon = UIApplicationShortcutIcon.FromType(UIApplicationShortcutIconType.Pause)
        };

        // Update the application providing the initial 'dynamic' shortcut items.
        application.ShortcutItems = new UIApplicationShortcutItem[]{shortcut3, shortcut4};
    }

    return shouldPerformAdditionalDelegateHandling;
}

ここでは、application に動的に作成された ShortcutItems のセットが既に含まれているかどうを確認します。含まれていない場合は、新しい項目を定義して ShortcutItems 配列に追加する 2 つの新しい UIMutableApplicationShortcutItem オブジェクトを作成します。

上記の「クイック アクションの処理」セクションで既に追加したコードは、静的なクイック アクションと同様に、これらの動的なクイック アクションを処理します。

(ここで行っているとおり) 静的なクイック アクション項目と動的なクイック アクション項目の両方を組み合わせて作成できることに注意してください。一方の項目だけしか使えないわけではありません。

詳細については、Apple の ApplicationShortcuts: UIApplicationShortcutItem サンプル アプリの使用、UIApplicationShortcutItem クラス リファレンスUIMutableApplicationShortcutItem クラス リファレンスUIApplicationShortcutIcon クラス リファレンスを参照してください。

シミュレーターでの 3D Touch のテスト

互換性のある Mac で最新バージョンの Xcode と iOS シミュレーターを Force Touch 対応トラックパッドと共に使用する場合は、シミュレーターで 3D Touch 機能をテストできます。

この機能を有効にするには、3D Touch (iPhone 6s 以降) をサポートするシミュレートされた iPhone ハードウェアでアプリを実行します。 次に、iOS シミュレーターで [ハードウェア] メニューを選択し、[3D タッチ メニュー項目にトラックパッド フォースを使用する] を有効にします。

iOS シミュレーターで [ハードウェア] メニューを選択し、[3D タッチ メニュー項目にトラックパッド フォースを使用する] を有効にします。

この機能をアクティブにすると、Mac のトラックパッドを強く押して、実際の iPhone ハードウェアと同じように 3D Touch を有効にすることができます。

まとめ

この記事では、iOS 9 for the iPhone 6s および iPhone 6s Plus で利用できる新しい 3D Touch API について説明しました。 アプリへの圧力感度の追加について説明しました。クイック表示とポップ表示を使用して、ナビゲーションがなくても現在のコンテキストからアプリ内情報をすばやく表示します。クイック アクションを使用して、アプリで最もよく使用される機能へのショートカットを提供します。