您的位置:首页 > 移动开发 > IOS开发

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

2015-10-13 06:29 483 查看
新的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实例传进去,更多信息请参考

iOS 9 ApplicationShortcuts Sample , ViewControllerPreviews:
Using the UIViewController previewing APIs ,
UIPreviewAction Class Reference,
UIPreviewActionGroup Class Reference 和 UIPreviewActionItem
Protocol Reference.

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. 希望大家能基于这些交互创造出更新颖的应用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: