当前位置: 首页 > 编程日记 > 正文

3D Touch介绍: 一个数字压力器App和Quick Actions

随着iPhone 6s and 6s Plus的发布,苹果介绍了全新的手机交互方式:重按手势。你应该知道,这个特性其实早已应用在苹果手表和MacBook产品中,名字叫Force Touch。它给用户交互添加了全新的维度!


或许你对Force Touch为什么被重命名为3D touch感到奇怪。在克雷格·费德里吉(CraigFederighi,苹果工程师、高级副总裁)介绍这个新事物时(他自己也为名字感到困惑),大家就热烈讨论起来了。Force Touch这个名字有什么问题呢?太多星球大战的梗?


但是它们之间其实是有区别的!3D Touch能感应压力的大小,而Force Touch只可以检测到发生了重按。


虽然这个改变看起来并不十分重要,它允许开发者获得按压iPhone的压力明确值。这个实例app叫做 Gravity ,使得你的iPhone变为一个可以显示数字等级的Force Touch.虽然由于不明原因,苹果拒绝这样做,但是这个想法是有趣的,演示了3D Touch是如何工作的,让我们开始这个app吧!

Let’s Get Started

首先,我们下载项目的模板。基本上,这只是一个空的 Single View iPhone应用。我创建了app的界面(UILabels 和 a UIImage),并且连接了IBOutlets到ViewController.swift中。




我们设计的app十分简单:一个包含两个label的view controller,其中一个是标题,另一个显示iPhone的压力百分比。


我们开始编码吧!在iPhone 6s 和 6s Plus,UITouch对象有两个CGFloat类型的属性,分别是force和maximumPossibleForce。force代表触摸的压力的大小,1.0表示正常的触摸。MaximumPossibleForce表示一次触摸的最大压力。


当用户触摸屏幕,touchesBegan会被调用,然后是touchesMoved(如果用户在屏幕上移动它的手指),再然后就要根据实际情况,可能是touchedCancelled或者TouchesEnded被调用。根据我们的需求,只有touchesMoved方法才是我们需要的。TouchesMoved有两个参数:touches和event。touches是一个存储了UITouch对象的Set对象(无顺序集合),touches中至少含有一个UITouch对象,但是谨慎起见,强烈建议先判断 touches.first是否为nil,在ViewController.swift中插入下面的方法:

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {if let touch = touches.first {if #available(iOS 9.0, *) {if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {// 3D Touch capable}}}
}


在if子句中,我们先判断设备是否支持3D Touch。如果你只是凭兴趣玩一下,这部分是可选的。如果你要将app发布到AppStore,一定要执行判断,因为iPhone6等老设备是不支持3D Touch的。


注意我同时检测了设备是否在iOS9.0及更新的版本中运行。我使用了Swift2.0的#available语句。如果你想进一步学习Swift 2.0的新特性,我建议你阅读这篇博客。如果你项目的deployment target是9.0或者以上版本,版本检测也是可选的。


为了获得压力百分比,只需要简单地将压力除以可能达到的最大压力(touch.maximumPossibleForce),然后更新label的文字:

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {if let touch = touches.first {if #available(iOS 9.0, *) {if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {// 3D Touch capablelet force = touch.force/touch.maximumPossibleForceforceLabel.text = "\(force)% force"}}}
}

如果你在iPhone 6s/6s Plus上运行项目,当你按压屏幕时,会显示压力百分比。然而你可能希望以“克”为单位来显示。根据Ryan McLeod的测试,感器的计量范围的最大值是 385g(约等于3.8牛)。通过简单的计算,你可以将 %压力转化为克。我们只需要将压力百分比乘以385。对于超过385的数据,我们只要改变label的文字,告诉用户:“385+ 克”。


现在,更新代码片段:

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {        if let touch = touches.first {if #available(iOS 9.0, *) {if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {if touch.force >= touch.maximumPossibleForce {forceLabel.text = "385+ grams"} else {let force = touch.force/touch.maximumPossibleForcelet grams = force * 385let roundGrams = Int(grams)forceLabel.text = "\(roundGrams) grams"}}}}
}

太酷了!你已经完成了一个数字压力app。



现在,当手指移开屏幕后,app并没有复位,你可以实现touchesEnded方法来将label复位。

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {forceLabel.text = "0 gram"
}


Home Screen Quick Actions

3D Touch的另一个用法是在Home页的Quick Actions(快速操作)。Quick actions 是用户直接跳转到app某些页面的一个快捷方式。简单地重压app的图标,你可以看见一个快捷菜单。在3D Touch的介绍文档,展示了Twitter 、Instagram,以及一些其它苹果app使用了这一特性。



我们就为我们的app添加Quick Action,来以蓝色的背景打开它而不是现在的白色。为了添加Quick Actions,打开项目的info.plist 文件。在文件中,添加一个’UIApplicationShortcutItems’数组。数组的每一个元素都是一个dictionary,而dictionary包含一个Quick Action的一些属性:


UIApplicationShortcutItemType(必须)一个标识Quick Action的字符串。注意这个字符串必须是唯一的。建议使用bundle ID或者其它app唯一字符串作为前缀。

UIApplicationShortcutItemTitle (必须)显示给用户看的Quick Action的标题。例如:“最新照片”。

UIApplicationShortcutItemSubtitle (可选)显示在标题底下的文字。例如:“昨天最新的照片”。如果你想在Quick Action中添加图片,有两种可能性:系统图标、用户自定义图标。

UIApplicationShortcutItemIconType (可选) 你希望在 Quick Action中显示的系统图标的字符串

UIApplicationShortcutItemIconFile (可选) 你希望在 Quick Action中显示的自定义图标的字符串

UIApplicationShortcutItemUserInfo (可选) 包含一些你想传递的额外的信息的字典。

在这个数组中,我们定义了4个属性来配置 “OpenBlue” Quick Action。你的 info.plist应该是这样子的:




说明一下,我使用’$(PRODUCT_BUNDLE_IDENTIFIER)’而不是 ‘com.appcoda.Scale’或者其它bundle ID,是为了安全着想:如果我将Bundle ID改为’General’,会影响整个项目,每个用到Bundle ID的地方都需要修改。在info.plist文件中,你会发现Bundle Identifier key也是使用‘$(PRODUCT_BUNDLE_IDENTIFIER)’来描述项目的Bundle ID。


最后需要做的是,当用户启动时,实现Quick action。在AppDelegate.swift中的performActionForShortcutItem方法中处理快捷事件。当触发了Quick Action,这个方法会被调用。所以需要在此方法中处理快捷事件。

func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {// Handle quick actionscompletionHandler(handleQuickAction(shortcutItem))}

你需要根据quick action的成功或失败,调用completionHandler,并且传递一个布尔值。这里我们创建一个单独的函数handleQuickAction来处理快捷事件。推荐使用UIApplicationShortcutItemType枚举,来表示 Quick Action的事件。像下面这样声明枚举并且实现handleQuickAction方法:

enum Shortcut: String {case openBlue = "OpenBlue"
}func handleQuickAction(shortcutItem: UIApplicationShortcutItem) -> Bool {var quickActionHandled = falselet type = shortcutItem.type.componentsSeparatedByString(".").last!if let shortcutType = Shortcut.init(rawValue: type) {switch shortcutType {case .openBlue:self.window?.backgroundColor = UIColor(red: 151.0/255.0, green: 187.0/255.0, blue: 255.0/255.0, alpha: 1.0)quickActionHandled = true}}return quickActionHandled
}

这一切都十分简单。如果你现在quick actions使用运行app,它的背景是蓝色的!




One Thing to Keep in Mind

但是你还需要记住一件事,使用Quick Action正常启动app和从后台打开是有区别的。当一个app正常启动willFinishLaunchingWithOptions和didFinishLaunchingWithOptions方法会被调用,但从后台打开时,只会执行performActionForShortcutItem方法。



在didFinishLaunchingWithOptions方法中,我们有一行代码来设置背景色为白色。在直接点击图标启动app时,这行代码会被执行。


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:[NSObject: AnyObject]?) -> Bool {// Override point for customization after application launch.self.window?.backgroundColor = UIColor.whiteColor()return true
}


这就是问题所在:当你通过quick action启动时,willFinish,didFinish,然后是performActionForShortcutItem会被执行,所以背景是由白色变为蓝色。很明显,你并不希望在通过快捷启动app启动时,将背景设为白色。


为了解决这个问题,我们需要在didFinishLaunchingWithOptions方法中执行判断:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:[NSObject: AnyObject]?) -> Bool {print("didFinishLaunchingWithOptions called")var isLaunchedFromQuickAction = false// Check if it's launched from Quick Actionif let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {isLaunchedFromQuickAction = true// Handle the sortcutItemhandleQuickAction(shortcutItem)} else {self.window?.backgroundColor = UIColor.whiteColor()}// Return false if the app was launched from a shortcut, so performAction... will not be called.return !isLaunchedFromQuickAction
}

你可以通过UIApplicationLaunchOptionsShortcutItemKey来确定app是否是通过快速启动打开的,然后决定是否调用handleQuickAction来改变背景颜色。


因为我们已经在didFinishLaunchingWithOptions中处理快捷启动,我们不需要再调用performActionForShortcutItem来处理。所以,最后我们返回一个false值,告诉系统不需要执行performActionForShortcutItem方法。


你可以测试你的app了,快捷启动应该可以完美运行!



Conclusion


3D Touch是一个好用且有意思的功能,但你需要知道,还不是所有设备都支持3D Touch。


你阅读完这篇博文后,你应该能在你的app中添加Quick Actions,知道怎么检测按压力度了。你可以下载完整的源码作为参考。(晚点上传Objective-c版本)

原文:http://www.appcoda.com/3d-touch-tutorial/





相关文章:

一些LUA函数(转载)

转自http://hi.baidu.com/chevallet/item/9a3a6410c20d929198ce3363 一些LUA函数 1、assert (v [, message])  功能&#xff1a;相当于C的断言&#xff0c;当表达式v为nil或false将触发错误,  message&#xff1a;发生错误时返回的信息&#xff0c;默认为"assertion f…

cifs------网络文件系统(1)

SMB文件共享 SMB&#xff08;Server Message Block&#xff09;通信协议是微软&#xff08;Microsoft&#xff09;和英特尔(Intel)在1987年制定的协议&#xff0c;主要是作为Microsoft网络的通讯协议。SMB 是在会话层&#xff08;session layer&#xff09;和表示层&#xff0…

Swift 教學:如何使用iOS Charts API 製作漂亮的圖表

在應付許多的資料時&#xff0c;比起只在表格中呈現&#xff0c;使用圖表來顯示資料&#xff0c;可以幫助使用者容易地了解資訊。有了圖表&#xff0c;相對於讀取整個資料表&#xff08;或幾個資料表&#xff09;你可以輕鬆地一眼便見到以圖形表示的資料&#xff0c;取得所需的…

在Proteus中添加标号

1.Proteus中添加组件后双击引脚可以快速生成一个最近的端口。 2.按A调出设置界面 3.在String中写&#xff1a;netH#,"H"可以换成自定义前缀。count为起始值&#xff0c;increment为增量。 4.依次点击想要编号的引脚。转载于:https://www.cnblogs.com/viaduct/p/58424…

九度OJ 1525 子串逆序打印 -- 2012年Google校园招聘笔试题目

题目地址&#xff1a;http://ac.jobdu.com/problem.php?pid1525 题目描述&#xff1a; 小明手中有很多字符串卡片&#xff0c;每个字符串中都包含有多个连续的空格&#xff0c;而且这些卡片在印刷的过程中将字符串的每个子串都打印反了&#xff0c;现在麻烦你帮小明将这些字符…

cifs------网络文件系统(2)

接着上篇博客继续&#xff1a; Samba 基本配置 [rootserver2 ~]# rpm -qc samba-common //查看smb的配置文件 1、黑、白名单的设定 默认白名单&#xff0c;设置的ip是黑名单用户&#xff1a;hosts deny ip 默认黑名单&#xff0c;设置的ip是白名单用户&#xff…

iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求

原文地址&#xff1a;https://github.com/ChenYilong/ParseSourceCodeStudy/blob/master/02_Parse的网络缓存与离线存储/iOS网络缓存扫盲篇.md 目录 当我们在谈论缓存的时候&#xff0c;我们在谈论什么&#xff1f;GET网络请求缓存 80%的缓存需求&#xff1a;两行代码就可满足…

YARN集群维护部分问题汇总

云梯开发人员在云梯Yarn集群的搭建和维护过程中做了许多工作&#xff0c;本文选择这期间部分较为典型的问题&#xff0c;通过对这些问题的分析和解决方案&#xff0c;为大家分享分布式系统问题调查的经验。 调查的问题 1. 2013年初引入社区0.23时&#xff0c;调查ResourceManag…

linux系统管理及vim

1.管理输入输出 在linux系统中&#xff0c;正确输出的编号为1&#xff0c;错误输出编号为2 在系统中用普通用户执行 "student" find /etc -name passwd 因为student用户权限问题会有以下输出 find: ‘/etc/pki/CA/private’: Permission denied ##没有进入权力…

如何用 OS X 的 Xcode 写C语言程序

這篇是給新手看的。 如果你在 Windows 習慣使用 Visual C 或 Dev-C 的話&#xff0c;到了 Mac OS X 可能會突然不知道要怎麼寫程式&#xff0c;尤其當你已經用 Visual C 的 Debugger 用得很上手的話。 最近我們系上的課充滿了 C programming&#xff0c;我也稍微摸懂了 Xcode 的…

【转】初等数论 ——原根、指标及其应用

转自&#xff1a;http://blog.163.com/gc_chdch126/blog/static/172279052201641935828402/ 学习总结&#xff1a;初等数论&#xff08;3&#xff09;——原根、指标及其应用 2016-05-19 15:58:28| 分类&#xff1a; 信息学——学习总 | 标签&#xff1a;初等数论 数学 |…

互联网产品评论索引

这里收集一些评论文章&#xff0c;定期查看文章观点的正确性&#xff0c;索引持续更新中 网站前期如何获得推广资源 专访陶瑾&#xff1a;微信公众平台开发先行者转载于:https://www.cnblogs.com/needrunning/p/3000353.html

Apache服务器部署(1)

apache&#xff08;web服务器&#xff09;简介&#xff1a; Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上&#xff0c;其跨平台和安全性被广泛使用&#xff0c;是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充&…

JavaScript关键字this指向

在js中this始终指向一个调用函数的那个对象 var a有种你干掉我啊; //纯粹调用函数 function test(){ console.log(this.a);//默认指向全局对象 } //test();//>windows.test() //作为对象的方法被调用 Function.prototype.logfunction(){ console.log(this.a); } //此时t为一…

项目开发过程中的收获与思考

2013年7月&#xff0c;我正式毕业了&#xff0c;到公司入职&#xff0c;也就正式成为了一名菜鸟程序员。到今天&#xff0c;2014年1月3日&#xff0c;目前主要的工作是公司一个项目中的一个功能模块&#xff0c;到我进入项目组算起&#xff0c;已经过了四个月了。因此&#xff…

【仿汽车之家】价格区间选择控件

仿照汽车之家iOS客户端“找车”栏目的价格区间选择控件&#xff0c;最终实现效果如下&#xff1a; 一、界面实现 *根据屏幕大小以及刻度的大小&#xff0c;宏定义需要用到的一些值 #define SCREENW [UIScreen mainScreen].bounds.size.width #define SCREENH [UIScreen mainScr…

Apache服务器部署(2)

签名CA证书 环境&#xff1a;server1:172.25.1.1 重置虚拟机 挂载yum源 [rootserver1 ~]# yum install mod_ssl -y //下载ssl模块 [rootserver1 ~]# yum install crypto-utils -y //安装加密软件 [rootserver1 ~]# genkey …

ASCII、Unicode、GBK和UTF-8字符编码的区别联系

一直对编码这块晕晕乎乎&#xff0c;今天终于看到一篇写的很清楚也很风趣的文章&#xff0c;转过来mark一下。 很久很久以前&#xff0c;有一群人&#xff0c;他们决定用8个可以开合的晶体管来组合成不同的状态&#xff0c;以表示世界上的万物。他们看到8个开关状态是好的&…

【iOS】快速集成轮播控件

自己写的一个轮播控件&#xff0c;初始化后只要实现两个数据源方法&#xff0c;几行代码就能快速集成&#xff0c;支持本地图片和网络图片&#xff0c;支持点击事件&#xff0c;可定制播放速度、指示器颜色/位置、默认加载图等&#xff0c;效果&#xff1a; 1.下载地址&#xf…

Hibernate中get方法和load方法的区别

一、get和load方法都是根据id去获得对应数据的&#xff0c;但是获得机制不同&#xff1a;如果使用get方法&#xff0c;hibernate会去确认该id对应的数据是否存在&#xff0c;它首先会去session中去查询(session缓存其实就hibernate的一级缓存)&#xff0c;如果没有&#xff0c;…

DNS高速缓存

DNS相关资料&#xff1a; 1.什么是DNS DNS&#xff08;Domain Name System域名系统&#xff09; 是互联网上存储域名和ip映射关系的一个分布式数据库&#xff0c;它负责把域名转换成ip地址&#xff0c;或ip地址转换为域名。DNS运行于TCP/UDP的53端口上。 2.什么是高速…

将时间改为显示:几天前,几小时前,或者几分钟前

&#xff08;原博客地址&#xff1a;http://blog.csdn.net/kenhins/article/details/38010811&#xff09; 方法一&#xff1a; 个人做法是保存时间戳&#xff0c;然后在前端用jq插件做转换&#xff0c;比如 smart-time-ago ----------------------------------------------- 方…

支持placeholder和自适配高度的TextView控件

一.应用于项目的效果如下&#xff1a; 二.使用方法&#xff1a; 1.导入JXTextView.h头文件 2.初始化,并添加到view中&#xff1a; JXTextView *textView [[JXTextView alloc] initWithFrame:CGRectMake(10, 10, 200, 30)];textView.placeholder "请输入内容";tex…

ZOJ 3735 dp

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode3735 好久没做DP题了&#xff0c;一开始没理解题目里的C(M,3)是干什么&#xff0c;原来就是组合&#xff0c;C M 取3&#xff0c;就等于n*&#xff08;n-1&#xff09;*&#xff08;n-2&#xff09;/6;题目里还有…

haproxy实现高可用及负载均衡

Haproxy简介&#xff1a; Haproxy是一个使用c语言编写的自由开发源代码软件&#xff0c;它提供高可用性、负载均衡、以及基于http和tcp的应用程序代理。Haproxy特别使用于那些负载特别大的web站点。Haproxy运行在当前的硬件上&#xff0c;完全可以支持数以万计的并发连接&#…

Apache转发到Tomcat

#vi /etc/httpd/conf/httpd.conf 添加下面配置 NameVirtualHost *:80 <VirtualHost *:80>ProxyPreserveHost OnServerName www.域名.comProxyPass / http://www.域名.com:8080/system/ErrorLog logs/error_logCustomLog logs/access_log common</VirtualHost> 作者…

.net基础问题

string sqlstr "select BranchCode,BranchName from t_sys_Branch where Jglx_DataDm{0} and IsVisible1"; sqlstr string.Format(sqlstr, departType); 上述代码运行之后 sqlstr"select BranchCode,BranchName from t_sys_Branch where Jglx_DataDmdepartTyp…

【iOS】NSDate分类,获得中国农历

1.说明&#xff1a; 参考网上代码写的一个分类&#xff0c;只需一句代码就可得到NSDate对象所对应的中国农历、星期。 2.使用方法&#xff1a; &#xff08;1&#xff09;导入分类头文件&#xff1a; #import "NSDateChineseDate.h"&#xff08;2&#xff09;NSDat…

LVS_NAT实现负载均衡

简介&#xff1a; 基于NAT机制实现。当用户请求到达director之后&#xff0c;director将请求报文的目标地址(即VIP)改成选定的realserver地址&#xff0c;同时将报文的目标端口也改成选定的realserver的相应端口&#xff0c;最后将报文请求发送到指定的realserver&#xff1b;…

自定义Push和Pop过渡动画

一、效果和源码 本文介绍如何实现一个NavigationController的自定义Push和Pop过渡动画&#xff0c;运行效果如下&#xff1a; 源码&#xff1a;https://github.com/dolacmeng/TransitionDemo 或http://download.csdn.net/detail/dolacmeng/9572384二、准备工作 首先&#xff0…