浅谈3D Touch 在Xamarin.iOS上的应用

新的iPhone6s和iPhone6s Plus新添加了3D Touch的功能,本文简单介绍一下如何在Xamarin.iOS上面使用该功能。


3D Touch不仅会感知用户按压屏幕,也会感知压力的大小。要注意一点的是,现在的iOS模拟器并不支持3D Touch,大家必须要在iPhone 6s/6s Plus 真机上进行测试和调试。

3D Touch可以给你的应用带来全新的交互方式.

  • Pressure Sensitivity - 应用可以感知用户按压屏幕的压力。这样一些绘画应用可以根据压力的大小改变笔触。
  • Peek and Pop - 应用可在单一页面中获取更多的内容。用户用力按压屏幕会弹出当前条目的额外信息,比如一些预览信息,这个行为叫做Peek,当用户再用力一点,可以跳转到预览信息的页面,这个行为叫做Pop。
  • Quick Actions - 这个行为有点类似于windows中的右键菜单,但是只是针对于应用图标的,显示一些关于这个应用的额外选项
下面我们分开来讲

Pressure Sensitivity



在Xamarin iOS中,获取压力的大小非常简单,我们可以通过UITouch类中的一些属性来完成。我们只需要在ToucheMoved的事件中捕获这些信息,请参考一下代码
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
        ...
    }
}

这里要注意的是,用户按压会触发TouchesMoved的事件,在这样的情况下X/Y的值是不变的,如果你的应用之前的代码是通过这个事件来判断X,Y值的是否改变,现在需要注意,X/Y不一定改变。相关文档请参考  TouchCanvas: Using UITouch efficiently and effectively   和 UITouch Class Reference.

Peek and Pop



这个交互行为会让用户更快的获取信息,比如用户在浏览一个表格,用户可以按压表格中的某项,获取一些关于该项的概况信息(这个行为叫做Peek),再用力一些,就可进入该项的详情页(这个行为叫做Pop或Pop-ping)。

检测设备是否支持3D Touch

可以通过下面的代码,在UIViewController 中判断当前设备是否支持3D Touch
public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // 检测是否支持3D Touch
    if (TraitCollection.ForceTouchCapability == UIForceTouchCapability.Available) {
        // 设备支持
        ...
    }
}


响应Peek和Pop行为

我们可以通过继承UIViewControllerPreviewingDelegate类来响应Peek和Pop的行为。请参考下面代码,假设我们之前提到的表格叫做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
        /// 继续按压触发Pop事件
        public override void CommitViewController (IUIViewControllerPreviewing previewingContext, UIViewController viewControllerToCommit)
        {
            // 直接使用之前创建好的详情页面
            MasterController.ShowViewController(viewControllerToCommit,this);
        }

        /// 创建预览页面,当用户触发Peek事件
        public override UIViewController GetViewControllerForPreview (IUIViewControllerPreviewing previewingContext, CGPoint location)
        {
            // 判断表格中的条目
            var indexPath = MasterController.TableView.IndexPathForRowAtPoint (location);
            var cell = MasterController.TableView.CellAt (indexPath);
            var item = MasterController.dataSource.Objects [indexPath.Row];

            // 创建ViewController,并设置初始位置
            var detailViewController = MasterController.Storyboard.InstantiateViewController ("DetailViewController") as DetailViewController;
            detailViewController.PreferredContentSize = new CGSize (0, 0);

            // 填入数据
            detailViewController.SetDetailItem (item);
            detailViewController.NavigationItem.LeftBarButtonItem = MasterController.SplitViewController.DisplayModeButtonItem;
            detailViewController.NavigationItem.LeftItemsSupplementBackButton = true;

            // 设置预览页面的位置,模糊其他页面
            previewingContext.SourceRect = cell.Frame;

            return detailViewController;
        }
        #endregion
    }
}

代码中GetViewControllerForPreview函数用来响应Peek行为,在这个函数中,首先我们获取当前表单,然后我们加载DetailViewController,接着通过PreferredContentSize设置Peek窗口的默认大小,最后我们通过previewingContext.SourceRect = cell.Frame  这段代码来模糊其他表单,然后返回我们想要的窗口。
CommitViewController 这个函数会利用我们在Peek行为中创建的窗口,来给Pop显示。

注册Peek和Pop行为

在使用Peek和Pop之前,我们要注册他们,在当前的ViewController,请参考下面代码
public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // 判断设备是否支持3D Touch
    if (TraitCollection.ForceTouchCapability == UIForceTouchCapability.Available) {
        // 注册Pop和Peek
        RegisterForPreviewingWithDelegate(new PreviewingDelegate(this), View);
    }
    ...

}

在这里,我们调用RegisterForPreviewingWithDelegate方法把创建的PreviewingDelegate实例传进去,更多信息请参考

Quick Actions

使用这个功能,可以让用户从应用的图标上,更快捷和直接地调用应用内的函数,我们可以把这个功能理解为桌面程序的右键菜单



定义静态Quick Actions

Quick Actions的行为可以是一个或者多个,我们需要在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>

下面是Quick Actions可以定义的几个键
  • UIApplicationShortcutItemIconType 这个键值用于Quick Actions的图标,可以是以下这几个值
    • UIApplicationShortcutIconTypeCompose
    • UIApplicationShortcutIconTypePlay
    • UIApplicationShortcutIconTypePause
    • UIApplicationShortcutIconTypeAdd
    • UIApplicationShortcutIconTypeLocation
    • UIApplicationShortcutIconTypeSearch
    • UIApplicationShortcutIconTypeShare
  • UIApplicationShortcutItemSubtitle 可以定义副标题
  • UIApplicationShortcutItemTitle 定义标题
  • UIApplicationShortcutItemType 这个值会被代码中引用

定义Quick Action的条目

我们可以通过Info.plist定义Quick Action,然后通过UIApplicationShortcutItemType定义接入点,来确定用户点击了哪个条目,并与之交互
为了更方便的使用这些接入点,我们也在代码中定义,如下
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";
    }
}

处理Quick Action事件

接下来,我们要修改AppDelegate.cs中的代码,去响应用户选择的Quick Action事件,代码如下
using System;
...

public UIApplicationShortcutItem LaunchedShortcutItem { get; set; }

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

   
    if (shortcutItem == null) return false;

    // 根据Shortcut的定义来执行相应函数
    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 handled;
}

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

    // 获取shortcut条目
    if (launchOptions != null) {
        LaunchedShortcutItem = launchOptions [UIApplication.LaunchOptionsShortcutItemKey] as UIApplicationShortcutItem;
        shouldPerformAdditionalDelegateHandling = (LaunchedShortcutItem == null);
    }

    return shouldPerformAdditionalDelegateHandling;
}

public override void OnActivated (UIApplication application)
{
    // 处理shortcut 被选中
    HandleShortcutItem(LaunchedShortcutItem);

    // 设置为空
    LaunchedShortcutItem = null;
}

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

首先,我们定义LaunchedShortcutItem属性来记录用户选择的Quick Action,接着我们重载FinishedLaunching方法,通过launchOptions参数来获取是否用户选择了Quick Action。
我们重载OnActivated函数,在这里,我们可以处理用户的Quick Action事件,上面代码中,我们只是打印消息,但在实际的应用中,我们可以在这里加入响应的代码。在处理Quick Action之后,我们设置LaunchedShortcutItem属性为空。
最后,如果你的应用已经在运行,如果用户再触发Quick Action,这个时候PerformActionForShortcutItem函数会被响应,同样,我们也要重载这个函数,处理Quick Action事件。

创建动态Quick Action条目

除了我们在Info.plist中创建静态Quick Action条目以外,我们可以通过代码动态添加Quick Action条目,我们只需修改一下FinishedLaunching,代码如下
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
    var shouldPerformAdditionalDelegateHandling = true;

    if (launchOptions != null) {
        LaunchedShortcutItem = launchOptions [UIApplication.LaunchOptionsShortcutItemKey] as UIApplicationShortcutItem;
        shouldPerformAdditionalDelegateHandling = (LaunchedShortcutItem == null);
    }

    // 添加动态条目
    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)
        };

        // 更新应用中的动态条目
        application.ShortcutItems = new UIApplicationShortcutItem[]{shortcut3, shortcut4};
    }

    return shouldPerformAdditionalDelegateHandling;
}

首先,我们要确定application是否已经添加了动态的Quick Action条目,如果没有,我们就创建两个,给ShortcutItems属性赋值。
剩下处理Quick Action的代码跟上一节添加静态的Quick Action的一样。
我们既可以添加动态的也可以添加静态的。更多信息可以参考

iOS 9 ViewControllerPreview Sample , ApplicationShortcuts: Using UIApplicationShortcutItem , UIApplicationShortcutItem Class Reference, UIMutableApplicationShortcutItem Class Reference 和 UIApplicationShortcutIcon Class Reference.


总结

本文介绍了3D Touch API在Xamarin.iOS中的应用,其中包括Pressure Sensitivity, Peek and Pop, Quick Actions. 希望大家能基于这些交互创造出更新颖的应用


本文转载自:CSDN特邀Xamarin技术专家Jesse Jiang的博客( http://blog.csdn.net/sinat_31967441/article/details/49093073


  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值