3DTouch-在iPhone上缩放:入门

iPhone 6s和iPhone 6s Plus带有支持3D Touch技术的屏幕进入市场后,几乎在App Store中就出现了一个用于称重李子和桃子的应用程序。

图片

我不能肯定地说出这些水果为何正确,但是我可以肯定地说出为什么这些确切结果。 事实是,iPhone屏幕传感器的工作原理是检测传感器表面的电流泄漏,对于这种泄漏,您需要带电的手指或具有电容的东西。 我想每个人都知道i设备的屏幕不能在塑料笔或指甲上工作。 这就是为什么无法在该应用程序上称重金属的原因。 但是水果有电容量,传感器被触发并且3D Touch直接正常工作。

很快,该应用程序已从App Store中删除。 就我个人而言,这似乎是由于心胸狭窄的用户尝试在其设备上称磅重量而完成的。 当然,这些设备坏了,然后将它们带到服务中心。 然后他们在系列中说了一些话:“该应用程序是从官方商店下载的,他们没有警告那里不可能……”。

结果,商店中没有这样的应用程序,但是没有人会阻止我们为自己创建它。

挑战赛


我们需要编写一个应用程序,该应用程序由一个控制器组成,上面有一个邀请字样,一个位于屏幕中央的画圆圈,以克为单位的重量指示器和所确定的力的百分比(在本文中将更加清楚)。 当您单击屏幕时,触摸点处将出现一个圆圈,该圆圈将根据压力而增加或减少。 必须马上说在模拟器上不能测试这样的应用程序。 因此,您将需要在真实设备上运行该应用程序。 最后,您应该获得这样的应用程序:

图片

项目创建


打开Xcode,选择创建一个新项目, Single View Application模板

图片

在Xcode中建立介面


转到情节提要 ,从元素库中将几个UILabel拖动到控制器上,将它们靠近控制器的上边缘或下边缘。 原来是这样的:

图片

为了美观,我们将突出显示将对象放置在红色圆圈中的位置。 您可以用圆圈拍摄现成的图片,但这不是我们的方法))。 我们将使用Core Graphics的方法绘制圆。 从UIView创建继承类并已经使用它会更加方便。

向项目添加一个新文件,将其命名为ScaleView 。 在此文件中创建一个从UIView继承的ScaleView类。

图片

import UIKit class ScaleView: UIView { override func draw(_ rect: CGRect) { } } 

接下来,转到StoryBoard ,将其从UIView元素库转移到控制器,并将其放置在控制器的中心。 选择新添加的UIView,然后在Identity Inspector中设置我们之前创建的ScaleView类。

图片

另外,借助常量,您可以设置屏幕上元素的相对排列规则。 对我来说看起来像这样:

图片

画圆


转到ScaleView.swift文件。 在ScaleView类中我们创建了draw(_ rect :)方法,该方法将用于在此UIView的显示区域内进行绘制。

将以下代码添加到draw(_ rect :)方法中

 override func draw(_ rect: CGRect) { let context = UIGraphicsGetCurrentContext() // 1 context?.setStrokeColor(UIColor.red.cgColor) // 2 context?.setLineWidth(14.0) // 3 context?.addArc(center: CGPoint(x: 375 / 2, y: 375 / 2), radius: 375 / 2 - 14, startAngle: 0, endAngle: 2 * CGFloat(M_PI), clockwise: true) // 4 context?.strokePath() // 5 } 

  1. 我们得到了将要绘制的图形上下文
  2. 我们设置绘制颜色。 在这种情况下。 是红色的
  3. 设置绘制线条的宽度。
  4. 我们以弧线的形式设置绘制路径,弧线的中心位于ScaleView的中心,半径等于ScaleView的宽度的一半减去14(这是将弧线插入可见的视图中),以及长弧线-围绕整个圆周360度。 请注意,我的宽度数字在上一段中使用常量进行了硬编码。
  5. 我们使用给定的参数绘制给定的路径

您可以对其进行编译以进行验证,但也可以设置指令以直接在Interface Builder中显示更改。

@IBDesignable指令中的所有魔力。 用此指令标记ScaleView

 import UIKit @IBDesignable class ScaleView: UIView { override func draw(_ rect: CGRect) { let context = UIGraphicsGetCurrentContext() context?.setStrokeColor(UIColor.red.cgColor) context?.setLineWidth(14.0) context?.addArc(center: CGPoint(x: 375 / 2, y: 375 / 2), radius: 375 / 2 - 14, startAngle: 0, endAngle: 2 * CGFloat(M_PI), clockwise: true) context?.strokePath() } } 

之后,转到StoryBoard ,稍等片刻,您将在ViewController的中心看到一个红色圆圈

图片

让我们练习并画出一个更小或更细的圆。 为此,将以下代码添加到ScaleView文件中的draw(_ rect :)方法中:

 context?.setLineWidth(1.0) context?.setStrokeColor(UIColor.lightGray.cgColor) context?.addArc(center: CGPoint(x: 375 / 2, y: 375 / 2), radius: 375 / 4 - 14, startAngle: 0, endAngle: 2 * CGFloat(M_PI), clockwise: true) context?.strokePath() 

我认为这很清楚,因此我们添加了。 实际上,我们又添加了一个圆形,灰色,半径为ScaleView宽度的四分之一和一个点的宽度。

StoryBoard中的结果:

图片

准备工作的最后一部分将是为ScaleView和两个UILabel创建出口,这将显示按百分比的屏幕强度和以克为单位的重量。 按住Ctrl键ViewController中拖动项目将创建必要的出口。

 @IBOutlet weak var scaleView: ScaleView! @IBOutlet weak var forceLabel: UILabel! @IBOutlet weak var grammLabel: UILabel! 

直接秤


因此,我们接近测量按压屏幕的力的时刻。 转到ViewController并在viewDidLoad()方法中为所有UILabel添加起始值

 override func viewDidLoad() { super.viewDidLoad() forceLabel.text = "0% force" grammLabel.text = "0 " } 

像所有与屏幕点击相关的过程一样,在控制器中,它们可以被touchesMoved(_::)方法捕获。 当屏幕及时触摸时,此方法有效。 即 如果手指在屏幕上或在屏幕上移动,则此方法有效,并且您可以跟踪所有触摸及其属性。 将其添加到ViewController并编写以下代码:

 override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { if let touch = touches.first { // 1 if #available(iOS 9.0, *) { // 2 if traitCollection.forceTouchCapability == UIForceTouchCapability.available { // 3 if touch.force >= touch.maximumPossibleForce { // 4 forceLabel.text = "100%+ force" grammLabel.text = "385 " } else { let force = (touch.force / touch.maximumPossibleForce) * 100 // 5 let grams = force * 385 / 100 // 6 let roundGrams = Int(grams) // 7 forceLabel.text = "\(Int(force))% force" // 8 grammLabel.text = "\(roundGrams) " } } } } } 

Libra iOS应用程序的所有机制都是这种方法。 我们将在本课程中进一步做的所有其他事情就是改进。 我们已经完成了所有基本工作。 让我们拆开

  1. 从整个屏幕触摸中,我们选择第一个
  2. 该伪指令检查设备上已安装的操作系统,并且仅在操作系统版本为9.0或更高时才跳过。 仅在iOS的第9版中,才可以使用3D Touch 。 尝试在较早版本的痛苦中处理它没有任何意义
  3. 在这一行中,正在测试该设备是否支持3D Touch功能的屏幕。 毕竟,iOS 10也可以安装在iPhone 6上,但是从这一点来看,这款智能手机的屏幕将无法区分压力。 此检查必须在严格的Apple要求下进行。
  4. 触摸具有force属性,每次touchesMoved(_::)方法工作时,都会传递力。 在这一行中,我们将当前按压力的值与按压力的最大可能值进行比较。 如果按压力大于最大值,则在UILabel中传递最大值,即力的100 %和385克。 应该注意为什么它是385克。 事实是3D Touch技术的制造方式是,按压力的100%相当于385克。 相应地,获得压力的百分比,我们可以轻松地计算出以克为单位的重量。
  5. 在这里,我们进行这些计算。 在这一行中,我们计算压力百分比
  6. 在这里,我们根据公式100%= 385克计算重量( 克)
  7. 这是对整个克的简单四舍五入
  8. 我们将以克为单位的强度和重量百分比传递给UILabel

在启动和检查应用程序之前,您需要添加另一种在屏幕上的所有触摸都停止touchesEnded(::)时起作用的方法,以便设置UILabel的初始位置并将其值传递给0%和0克。 将此方法添加到ViewController类。

 override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { forceLabel.text = "0% force" grammLabel.text = "0 " } 

现在您可以编译应用程序并进行检查。 当然,您需要在真实设备上执行此操作才能查看结果。 模拟器无法在屏幕上模拟强制点击。

图片

改进之处


主要功能已经准备就绪,但是当我编写此应用程序时,我决定添加三件事:

  1. 当达到最大值时,我希望振动响应起作用
  2. UILabel中的值更新非常迅速(我认为您在测试时注意到了这一点),因此需要增加一些平滑度。
  3. 半透明的圆圈应该出现在按压点处。 其直径应随压力增加而增大,而随压力减小而减小

我们将在以下文章中处理这些新增内容 :-)

Source: https://habr.com/ru/post/zh-CN417221/


All Articles